@inixiative/json-rules 2.26.0 → 3.0.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 +352 -70
- package/dist/index.cjs +4 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +351 -415
- package/dist/index.d.ts +351 -415
- package/dist/index.js +4 -8
- package/dist/index.js.map +1 -1
- package/package.json +18 -7
package/dist/index.d.ts
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,57 +177,15 @@ declare const ValueShape: {
|
|
|
96
177
|
readonly predicate: "predicate";
|
|
97
178
|
};
|
|
98
179
|
type ValueShape = (typeof ValueShape)[keyof typeof ValueShape];
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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[];
|
|
188
|
+
declare const getAggregateOperators: () => readonly Operator[];
|
|
150
189
|
|
|
151
190
|
type OperatorValues = typeof Operator;
|
|
152
191
|
type ArrayOperatorValues = typeof ArrayOperator;
|
|
@@ -158,21 +197,33 @@ type RuleValue = RuleScalar | Date | RegExp | RuleValue[] | {
|
|
|
158
197
|
};
|
|
159
198
|
type OrderedRuleValue = string | number | Date;
|
|
160
199
|
type DateInputValue = string | number | Date;
|
|
161
|
-
type
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
200
|
+
type SourceSlots<TValue> = {
|
|
201
|
+
value: TValue;
|
|
202
|
+
path: string;
|
|
203
|
+
bind: string;
|
|
204
|
+
bindOptional: boolean;
|
|
205
|
+
};
|
|
206
|
+
type Never<K extends PropertyKey> = {
|
|
207
|
+
[P in K]?: never;
|
|
208
|
+
};
|
|
209
|
+
type ValueSourceOf<TValue> = (Pick<SourceSlots<TValue>, 'value'> & Never<'path' | 'bind' | 'bindOptional'>) | (Pick<SourceSlots<TValue>, 'path'> & Never<'value' | 'bind' | 'bindOptional'>) | (Pick<SourceSlots<TValue>, 'bind'> & Partial<Pick<SourceSlots<TValue>, 'bindOptional'>> & Never<'value' | 'path'>);
|
|
210
|
+
type ValueSourceFields<TValue> = Partial<SourceSlots<TValue>>;
|
|
211
|
+
type Magnitude = number | ValueSourceOf<number>;
|
|
212
|
+
type RelativeUnits<TAmount = Magnitude> = {
|
|
213
|
+
years?: TAmount;
|
|
214
|
+
quarters?: TAmount;
|
|
215
|
+
months?: TAmount;
|
|
216
|
+
weeks?: TAmount;
|
|
217
|
+
days?: TAmount;
|
|
218
|
+
hours?: TAmount;
|
|
219
|
+
minutes?: TAmount;
|
|
220
|
+
seconds?: TAmount;
|
|
170
221
|
};
|
|
171
222
|
type PeriodUnit = 'year' | 'quarter' | 'month' | 'week' | 'isoWeek' | 'day' | 'hour' | 'minute' | 'second';
|
|
172
|
-
type RollingExpr = {
|
|
173
|
-
ago: RelativeUnits
|
|
223
|
+
type RollingExpr<TAmount = Magnitude> = {
|
|
224
|
+
ago: RelativeUnits<TAmount>;
|
|
174
225
|
} | {
|
|
175
|
-
ahead: RelativeUnits
|
|
226
|
+
ahead: RelativeUnits<TAmount>;
|
|
176
227
|
};
|
|
177
228
|
type PeriodExpr = {
|
|
178
229
|
this: PeriodUnit;
|
|
@@ -186,38 +237,22 @@ type EdgeExpr = {
|
|
|
186
237
|
} | {
|
|
187
238
|
end: PeriodExpr;
|
|
188
239
|
};
|
|
189
|
-
type DateExpr = RollingExpr | PeriodExpr | EdgeExpr;
|
|
240
|
+
type DateExpr<TAmount = Magnitude> = RollingExpr<TAmount> | PeriodExpr | EdgeExpr;
|
|
190
241
|
type DateInputOrExpr = DateInputValue | DateExpr;
|
|
191
242
|
type DateRuleValue = DateInputValue | DateExpr | [DateInputOrExpr, DateInputOrExpr] | string[];
|
|
192
243
|
type WeekStart = 'monday' | 'sunday';
|
|
193
|
-
type TimeZoneConfig = string |
|
|
194
|
-
bind: string;
|
|
195
|
-
};
|
|
244
|
+
type TimeZoneConfig = string | ValueSourceOf<string>;
|
|
196
245
|
type DateConfig = {
|
|
197
246
|
now?: DateInputValue;
|
|
198
247
|
timeZone?: TimeZoneConfig;
|
|
199
248
|
weekStart?: WeekStart;
|
|
200
249
|
};
|
|
201
|
-
type ValueSource<TValue> = {
|
|
202
|
-
|
|
203
|
-
path?: never;
|
|
204
|
-
bind?: never;
|
|
205
|
-
bindOptional?: never;
|
|
206
|
-
} | {
|
|
207
|
-
path: string;
|
|
208
|
-
value?: never;
|
|
209
|
-
bind?: never;
|
|
210
|
-
bindOptional?: never;
|
|
211
|
-
} | {
|
|
212
|
-
bind: string;
|
|
213
|
-
bindOptional?: boolean;
|
|
214
|
-
value?: never;
|
|
215
|
-
path?: never;
|
|
216
|
-
};
|
|
217
|
-
type NoValueSource = {
|
|
218
|
-
value?: never;
|
|
219
|
-
path?: never;
|
|
250
|
+
type ValueSource<TValue, TOffset = never> = ValueSourceOf<TValue> & {
|
|
251
|
+
offset?: TOffset;
|
|
220
252
|
};
|
|
253
|
+
type NumberOffset = ValueSourceOf<number>;
|
|
254
|
+
type DateOffset = ValueSourceOf<RollingExpr>;
|
|
255
|
+
type NoValueSource = Never<keyof SourceSlots<unknown> | 'offset'>;
|
|
221
256
|
type RuleBase<TOperator extends Operator> = {
|
|
222
257
|
field: string;
|
|
223
258
|
operator: TOperator;
|
|
@@ -230,13 +265,13 @@ type DateRuleBase<TOperator extends DateOperator> = {
|
|
|
230
265
|
dateOperator: TOperator;
|
|
231
266
|
error?: string;
|
|
232
267
|
};
|
|
233
|
-
type StrictEqualityRule<TValue = RuleValue> = (RuleBase<OperatorValues['equals']> & ValueSource<TValue>) | (RuleBase<OperatorValues['notEquals']> & ValueSource<TValue>);
|
|
234
|
-
type StrictOrderedComparisonRule = (RuleBase<OperatorValues['lessThan']> & ValueSource<OrderedRuleValue>) | (RuleBase<OperatorValues['lessThanEquals']> & ValueSource<OrderedRuleValue>) | (RuleBase<OperatorValues['greaterThan']> & ValueSource<OrderedRuleValue>) | (RuleBase<OperatorValues['greaterThanEquals']> & ValueSource<OrderedRuleValue>);
|
|
268
|
+
type StrictEqualityRule<TValue = RuleValue> = (RuleBase<OperatorValues['equals']> & ValueSource<TValue, NumberOffset>) | (RuleBase<OperatorValues['notEquals']> & ValueSource<TValue, NumberOffset>);
|
|
269
|
+
type StrictOrderedComparisonRule = (RuleBase<OperatorValues['lessThan']> & ValueSource<OrderedRuleValue, NumberOffset>) | (RuleBase<OperatorValues['lessThanEquals']> & ValueSource<OrderedRuleValue, NumberOffset>) | (RuleBase<OperatorValues['greaterThan']> & ValueSource<OrderedRuleValue, NumberOffset>) | (RuleBase<OperatorValues['greaterThanEquals']> & ValueSource<OrderedRuleValue, NumberOffset>);
|
|
235
270
|
type StrictMembershipRule<TValue = RuleValue> = (RuleBase<OperatorValues['in']> & ValueSource<TValue[]>) | (RuleBase<OperatorValues['notIn']> & ValueSource<TValue[]>);
|
|
236
271
|
type StrictContainsRule<TValue = RuleValue> = (RuleBase<OperatorValues['contains']> & ValueSource<TValue>) | (RuleBase<OperatorValues['notContains']> & ValueSource<TValue>);
|
|
237
272
|
type StrictPatternRule = (RuleBase<OperatorValues['matches']> & ValueSource<RegExp | string>) | (RuleBase<OperatorValues['notMatches']> & ValueSource<RegExp | string>);
|
|
238
|
-
type StrictStringBoundaryRule = (RuleBase<OperatorValues['startsWith']> & ValueSource<string>) | (RuleBase<OperatorValues['endsWith']> & ValueSource<string>);
|
|
239
|
-
type StrictRangeRule = (RuleBase<OperatorValues['between']> & ValueSource<[OrderedRuleValue, OrderedRuleValue]>) | (RuleBase<OperatorValues['notBetween']> & ValueSource<[OrderedRuleValue, OrderedRuleValue]>);
|
|
273
|
+
type StrictStringBoundaryRule = (RuleBase<OperatorValues['startsWith']> & ValueSource<string>) | (RuleBase<OperatorValues['notStartsWith']> & ValueSource<string>) | (RuleBase<OperatorValues['endsWith']> & ValueSource<string>) | (RuleBase<OperatorValues['notEndsWith']> & ValueSource<string>);
|
|
274
|
+
type StrictRangeRule = (RuleBase<OperatorValues['between']> & ValueSource<[OrderedRuleValue, OrderedRuleValue], NumberOffset>) | (RuleBase<OperatorValues['notBetween']> & ValueSource<[OrderedRuleValue, OrderedRuleValue], NumberOffset>);
|
|
240
275
|
type StrictPresenceRule = (RuleBase<OperatorValues['isEmpty']> & NoValueSource) | (RuleBase<OperatorValues['notEmpty']> & NoValueSource) | (RuleBase<OperatorValues['exists']> & NoValueSource) | (RuleBase<OperatorValues['notExists']> & NoValueSource);
|
|
241
276
|
type StrictRule<TValue = RuleValue> = StrictEqualityRule<TValue> | StrictOrderedComparisonRule | StrictMembershipRule<TValue> | StrictContainsRule<TValue> | StrictPatternRule | StrictStringBoundaryRule | StrictRangeRule | StrictPresenceRule;
|
|
242
277
|
type ArrayRuleBase<TOperator extends ArrayOperator> = {
|
|
@@ -272,15 +307,9 @@ type StrictArrayPresenceRule = (ArrayRuleBase<ArrayOperatorValues['empty']> & {
|
|
|
272
307
|
count?: never;
|
|
273
308
|
});
|
|
274
309
|
type StrictArrayRule<TRuleValue = RuleValue, TDateValue = DateRuleValue> = StrictArrayPredicateRule<TRuleValue, TDateValue> | StrictArrayCountRule<TRuleValue, TDateValue> | StrictArrayPresenceRule;
|
|
275
|
-
type StrictDateComparisonRule = (DateRuleBase<DateOperatorValues['before']> & ValueSource<DateInputValue>) | (DateRuleBase<DateOperatorValues['after']> & ValueSource<DateInputValue>) | (DateRuleBase<DateOperatorValues['onOrBefore']> & ValueSource<DateInputValue>) | (DateRuleBase<DateOperatorValues['onOrAfter']> & ValueSource<DateInputValue>) | (DateRuleBase<DateOperatorValues['notBefore']> & ValueSource<DateInputValue>) | (DateRuleBase<DateOperatorValues['notAfter']> & ValueSource<DateInputValue>);
|
|
276
|
-
type StrictDateRangeRule = (DateRuleBase<DateOperatorValues['between']> & ValueSource<[DateInputValue, DateInputValue]>) | (DateRuleBase<DateOperatorValues['notBetween']> & ValueSource<[DateInputValue, DateInputValue]>);
|
|
277
|
-
type StrictDateDayRule = (DateRuleBase<DateOperatorValues['dayIn']> &
|
|
278
|
-
value: string[];
|
|
279
|
-
path?: never;
|
|
280
|
-
}) | (DateRuleBase<DateOperatorValues['dayNotIn']> & {
|
|
281
|
-
value: string[];
|
|
282
|
-
path?: never;
|
|
283
|
-
});
|
|
310
|
+
type StrictDateComparisonRule = (DateRuleBase<DateOperatorValues['before']> & ValueSource<DateInputValue, DateOffset>) | (DateRuleBase<DateOperatorValues['after']> & ValueSource<DateInputValue, DateOffset>) | (DateRuleBase<DateOperatorValues['onOrBefore']> & ValueSource<DateInputValue, DateOffset>) | (DateRuleBase<DateOperatorValues['onOrAfter']> & ValueSource<DateInputValue, DateOffset>) | (DateRuleBase<DateOperatorValues['notBefore']> & ValueSource<DateInputValue, DateOffset>) | (DateRuleBase<DateOperatorValues['notAfter']> & ValueSource<DateInputValue, DateOffset>);
|
|
311
|
+
type StrictDateRangeRule = (DateRuleBase<DateOperatorValues['between']> & ValueSource<[DateInputValue, DateInputValue], DateOffset>) | (DateRuleBase<DateOperatorValues['notBetween']> & ValueSource<[DateInputValue, DateInputValue], DateOffset>);
|
|
312
|
+
type StrictDateDayRule = (DateRuleBase<DateOperatorValues['dayIn']> & ValueSource<string[]>) | (DateRuleBase<DateOperatorValues['dayNotIn']> & ValueSource<string[]>);
|
|
284
313
|
type StrictDateRule = StrictDateComparisonRule | StrictDateRangeRule | StrictDateDayRule;
|
|
285
314
|
type AggregateRuleBase<TRuleValue = RuleValue, TDateValue = DateRuleValue> = {
|
|
286
315
|
field: string;
|
|
@@ -317,19 +346,12 @@ type AggregateRule<TRuleValue = RuleValue, TDateValue = DateRuleValue> = WindowF
|
|
|
317
346
|
};
|
|
318
347
|
condition?: Condition<TRuleValue, TDateValue>;
|
|
319
348
|
operator: Operator;
|
|
320
|
-
value?: number | [number, number];
|
|
321
|
-
path?: string;
|
|
322
|
-
bind?: string;
|
|
323
|
-
bindOptional?: boolean;
|
|
324
349
|
error?: string;
|
|
325
|
-
}
|
|
326
|
-
type Rule<TValue = RuleValue> = {
|
|
350
|
+
} & ValueSourceFields<number | [number, number]>;
|
|
351
|
+
type Rule<TValue = RuleValue> = ValueSourceFields<TValue> & {
|
|
327
352
|
field: string;
|
|
328
353
|
operator: Operator;
|
|
329
|
-
|
|
330
|
-
path?: string;
|
|
331
|
-
bind?: string;
|
|
332
|
-
bindOptional?: boolean;
|
|
354
|
+
offset?: NumberOffset;
|
|
333
355
|
error?: string;
|
|
334
356
|
caseInsensitive?: boolean;
|
|
335
357
|
fuzzy?: boolean | FuzzyConfig;
|
|
@@ -342,13 +364,10 @@ type ArrayRule<TRuleValue = RuleValue, TDateValue = DateRuleValue> = WindowField
|
|
|
342
364
|
count?: number;
|
|
343
365
|
error?: string;
|
|
344
366
|
};
|
|
345
|
-
type DateRule<TValue = DateRuleValue> = {
|
|
367
|
+
type DateRule<TValue = DateRuleValue> = ValueSourceFields<TValue> & {
|
|
346
368
|
field: string;
|
|
347
369
|
dateOperator: DateOperator;
|
|
348
|
-
|
|
349
|
-
path?: string;
|
|
350
|
-
bind?: string;
|
|
351
|
-
bindOptional?: boolean;
|
|
370
|
+
offset?: DateOffset;
|
|
352
371
|
error?: string;
|
|
353
372
|
};
|
|
354
373
|
type All<TRuleValue = RuleValue, TDateValue = DateRuleValue> = {
|
|
@@ -381,24 +400,36 @@ type StrictIfThenElse<TRuleValue = RuleValue, TDateValue = DateRuleValue> = {
|
|
|
381
400
|
error?: string;
|
|
382
401
|
};
|
|
383
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[];
|
|
384
415
|
|
|
385
|
-
/**
|
|
386
|
-
|
|
416
|
+
/** `required`: leave out the names an optional bind (`bindOptional`) may go unsupplied. */
|
|
417
|
+
type ListBindingsOptions = {
|
|
418
|
+
required?: boolean;
|
|
419
|
+
};
|
|
387
420
|
/**
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
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.
|
|
391
424
|
*/
|
|
392
|
-
declare const
|
|
425
|
+
declare const listBindings: (condition: Condition, { required }?: ListBindingsOptions) => string[];
|
|
393
426
|
/**
|
|
394
427
|
* Substitute covered binds with their values; uncovered tokens stay in place (partial
|
|
395
428
|
* resolution). A supplied-but-undefined binding becomes null to stay serializable.
|
|
396
429
|
* Non-mutating.
|
|
397
430
|
*/
|
|
398
|
-
declare const
|
|
431
|
+
declare const bindRule: (condition: Condition, bindings: Record<string, RuleValue>) => Condition;
|
|
399
432
|
|
|
400
|
-
type Row$3 = Record<string, unknown>;
|
|
401
|
-
type CheckData = Row$3 | unknown[];
|
|
402
433
|
type CheckOptions = {
|
|
403
434
|
context?: CheckData;
|
|
404
435
|
bindings?: Record<string, RuleValue>;
|
|
@@ -415,6 +446,9 @@ type EngineGlobalsState = {
|
|
|
415
446
|
datasource: {
|
|
416
447
|
provider: PrismaProvider;
|
|
417
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;
|
|
418
452
|
};
|
|
419
453
|
};
|
|
420
454
|
type DeepPartial<T> = {
|
|
@@ -426,137 +460,33 @@ declare const engineGlobals: {
|
|
|
426
460
|
reset: () => void;
|
|
427
461
|
with: <T>(partial: DeepPartial<EngineGlobalsState>, fn: () => T) => T;
|
|
428
462
|
};
|
|
429
|
-
declare const supportsQueryMode: (provider: PrismaProvider) => boolean;
|
|
430
|
-
declare const resolveCaseInsensitive: (ruleFlag?: boolean) => boolean;
|
|
431
|
-
declare const resolveFuzzy: (ruleFlag?: boolean | FuzzyConfig) => FuzzyConfig | false;
|
|
432
463
|
|
|
433
|
-
type PrismaWhere = Record<string, unknown>;
|
|
434
|
-
/** A selectable option — the standard `<select>` shape: a value with an optional display
|
|
435
|
-
* label, plus the partition keys (index-aligned with the source's `groupBy` axes)
|
|
436
|
-
* when the source is grouped. */
|
|
437
|
-
type SourceOption = {
|
|
438
|
-
value: string;
|
|
439
|
-
label?: string;
|
|
440
|
-
groups?: string[];
|
|
441
|
-
};
|
|
442
|
-
type FieldMapEntry = {
|
|
443
|
-
kind: 'scalar' | 'object' | 'enum' | 'bridge';
|
|
444
|
-
type: string;
|
|
445
|
-
isList?: boolean;
|
|
446
|
-
/**
|
|
447
|
-
* Whether the column is NOT NULL. `toPrisma` reads this to decide if a negated
|
|
448
|
-
* operator needs an explicit `equals: null` arm (Prisma's `not`/`notIn` follow SQL
|
|
449
|
-
* three-valued logic and drop NULL rows); absent = unknown = no arm.
|
|
450
|
-
*/
|
|
451
|
-
isRequired?: boolean;
|
|
452
|
-
fromFields?: string[];
|
|
453
|
-
toFields?: string[];
|
|
454
|
-
relationName?: string;
|
|
455
|
-
/**
|
|
456
|
-
* Per-field allowed values, primarily for enum fields. Takes precedence over
|
|
457
|
-
* `FieldMap.enums[type]` if both are set. Pass-through from codegen
|
|
458
|
-
* (e.g. prisma-map's `EnumField.values`). Consumed by `checkRuleAgainstLens`.
|
|
459
|
-
*/
|
|
460
|
-
values?: readonly string[];
|
|
461
|
-
/**
|
|
462
|
-
* A field's selectable option set as `{ value, label? }` pairs — the display
|
|
463
|
-
* shape a picker consumes. On projection/surface output this is populated for
|
|
464
|
-
* every value-gated field (enum members normalized to `{ value, label: value }`)
|
|
465
|
-
* and for sourced fields (the fetched pairs from a materialized `SourceValues`).
|
|
466
|
-
*/
|
|
467
|
-
options?: readonly SourceOption[];
|
|
468
|
-
/**
|
|
469
|
-
* Present on projection/surface output when the field's source partitions its
|
|
470
|
-
* options: the dotted to-one axes (relative to this model) whose values are
|
|
471
|
-
* each option's `groups`, index-aligned.
|
|
472
|
-
*/
|
|
473
|
-
groupBy?: readonly string[];
|
|
474
|
-
};
|
|
475
|
-
type ModelEntry = {
|
|
476
|
-
dbName?: string | null;
|
|
477
|
-
fields: Record<string, FieldMapEntry>;
|
|
478
|
-
};
|
|
479
|
-
/**
|
|
480
|
-
* A schema map: models keyed by name, plus an optional enum registry scoped to
|
|
481
|
-
* this source. In multi-source setups (Prisma + Salesforce + CRM) each FieldMap
|
|
482
|
-
* carries its own enums so namespaces don't collide across sources.
|
|
483
|
-
*/
|
|
484
|
-
type FieldMap = {
|
|
485
|
-
models: Record<string, ModelEntry>;
|
|
486
|
-
/** Enum name → allowed values, e.g. `{ UserRole: ['ADMIN', 'USER'] }`. */
|
|
487
|
-
enums?: Record<string, readonly string[]>;
|
|
488
|
-
};
|
|
489
|
-
type StepRef = {
|
|
490
|
-
__step: number;
|
|
491
|
-
};
|
|
492
|
-
type GroupByStep = {
|
|
493
|
-
operation: 'groupBy';
|
|
494
|
-
model: string;
|
|
495
|
-
args: {
|
|
496
|
-
by: string[];
|
|
497
|
-
where: Record<string, unknown>;
|
|
498
|
-
having: Record<string, unknown>;
|
|
499
|
-
};
|
|
500
|
-
extract: string;
|
|
501
|
-
};
|
|
502
|
-
type WhereStep = {
|
|
503
|
-
operation: 'where';
|
|
504
|
-
where: Record<string, unknown>;
|
|
505
|
-
};
|
|
506
|
-
type PrismaStep = GroupByStep | WhereStep;
|
|
507
|
-
type ToPrismaResult = {
|
|
508
|
-
steps: PrismaStep[];
|
|
509
|
-
};
|
|
510
|
-
type BuildOptions = {
|
|
511
|
-
map?: FieldMap | FieldMapSet;
|
|
512
|
-
mapName?: string;
|
|
513
|
-
model?: string;
|
|
514
|
-
context?: Record<string, unknown>;
|
|
515
|
-
datasource?: {
|
|
516
|
-
provider?: PrismaProvider;
|
|
517
|
-
};
|
|
518
|
-
} & DateConfig;
|
|
519
|
-
|
|
520
|
-
type BridgeEndpoint = {
|
|
521
|
-
fieldMap: string;
|
|
522
|
-
model: string;
|
|
523
|
-
on: string;
|
|
524
|
-
};
|
|
525
|
-
type BridgeCardinality = 'oneToOne' | 'oneToMany';
|
|
526
|
-
/**
|
|
527
|
-
* A cross-source edge between two endpoints.
|
|
528
|
-
*
|
|
529
|
-
* Endpoint ordering convention for `oneToMany`:
|
|
530
|
-
* - `endpoints[0]` is the "one" side — its `on` field must be unique per row
|
|
531
|
-
* (typically a primary key).
|
|
532
|
-
* - `endpoints[1]` is the "many" side — its `on` field may repeat across rows
|
|
533
|
-
* (typically a foreign key).
|
|
534
|
-
*
|
|
535
|
-
* Mis-ordering produces wrong `isList` flags during stitching and silent
|
|
536
|
-
* row-dedup when building bridge dictionaries. `buildBridgeDictionary` throws
|
|
537
|
-
* at runtime if endpoint[0]'s data has duplicate `on` values to catch this.
|
|
538
|
-
*
|
|
539
|
-
* For `oneToOne`, both `on` fields must be unique; endpoint order is symmetric.
|
|
540
|
-
*/
|
|
541
|
-
type Bridge = {
|
|
542
|
-
endpoints: [BridgeEndpoint, BridgeEndpoint];
|
|
543
|
-
cardinality: BridgeCardinality;
|
|
544
|
-
};
|
|
545
|
-
type FieldMapSet = {
|
|
546
|
-
maps: Record<string, FieldMap>;
|
|
547
|
-
bridges?: Bridge[];
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
type Row$2 = Record<string, unknown>;
|
|
551
464
|
type BridgeDictionary = Record<string, // map name
|
|
552
465
|
Record<string, // model name
|
|
553
|
-
Record<string, Record<string, Row
|
|
554
|
-
declare const
|
|
466
|
+
Record<string, Record<string, Row | Row[]>>>>;
|
|
467
|
+
declare const indexBridges: (set: FieldMapSet, rawData: Record<string, Row[]>) => BridgeDictionary;
|
|
555
468
|
|
|
556
469
|
declare const stitchFieldMaps: (set: FieldMapSet) => FieldMapSet;
|
|
557
470
|
|
|
558
|
-
|
|
559
|
-
|
|
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;
|
|
560
490
|
|
|
561
491
|
type Lens = FieldMapSet & {
|
|
562
492
|
mapName: string;
|
|
@@ -570,8 +500,8 @@ type Lens = FieldMapSet & {
|
|
|
570
500
|
* - SCHEMA narrowing (picks/omits/enumPicks/enumOmits): controls what's visible
|
|
571
501
|
* in the type surface. AI/SDK consumers can't see narrowed-away fields.
|
|
572
502
|
* - DATA narrowing (where): controls which ROWS are in scope. Filter-first
|
|
573
|
-
* semantic, anchored to the model. Under arrayOperator: 'all',
|
|
574
|
-
*
|
|
503
|
+
* semantic, anchored to the model. Under arrayOperator: 'all', it becomes the window filter
|
|
504
|
+
* (filter-first) — see narrowRule.
|
|
575
505
|
*/
|
|
576
506
|
type ModelDefaultNarrowing = {
|
|
577
507
|
picks?: string[];
|
|
@@ -594,7 +524,7 @@ type ModelDefaultNarrowing = {
|
|
|
594
524
|
* model that path resolves to. The `where` composes AND-only across layers (general
|
|
595
525
|
* via `mapDefaults`, path-specific via `root`/`relations`); a later layer's `label` wins.
|
|
596
526
|
*/
|
|
597
|
-
sources?: Record<string,
|
|
527
|
+
sources?: Record<string, SourceEntry>;
|
|
598
528
|
};
|
|
599
529
|
/**
|
|
600
530
|
* A sourced field's eligibility `where` plus an optional display-label column — a
|
|
@@ -618,7 +548,7 @@ type SourceSpec = {
|
|
|
618
548
|
groupBy: string | string[];
|
|
619
549
|
};
|
|
620
550
|
/** A `sources` entry: a bare eligibility `Condition`, or a richer `SourceSpec`. */
|
|
621
|
-
type
|
|
551
|
+
type SourceEntry = Condition | SourceSpec;
|
|
622
552
|
/** Narrowing for a model at a specific traversal path. Adds relations to the default shape. */
|
|
623
553
|
type ModelNarrowing = ModelDefaultNarrowing & {
|
|
624
554
|
relations?: Record<string, ModelNarrowing>;
|
|
@@ -647,8 +577,6 @@ type LensNarrowing = {
|
|
|
647
577
|
mapDefaults?: Record<string, NarrowingDefaults>;
|
|
648
578
|
};
|
|
649
579
|
|
|
650
|
-
declare const applyLens: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing) => Condition;
|
|
651
|
-
|
|
652
580
|
/**
|
|
653
581
|
* Every bind name a lens (its whole narrowing chain) needs supplied to execute —
|
|
654
582
|
* `bindOptional` tokens are not required (unsupplied, they resolve to null).
|
|
@@ -657,29 +585,74 @@ declare const applyLens: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing
|
|
|
657
585
|
* this lens require" answer; pass `narrowing.parent` to see the names a child must
|
|
658
586
|
* not collide with.
|
|
659
587
|
*/
|
|
660
|
-
declare const
|
|
588
|
+
declare const listLensBindings: (lensOrNarrowing: Lens | LensNarrowing) => string[];
|
|
661
589
|
/**
|
|
662
590
|
* Preprocess a lens: resolve every `{ bind }` token the map covers in the chain's
|
|
663
591
|
* `where`/`sources`, returning a structurally-new lens with concrete conditions.
|
|
664
592
|
* Partial — uncovered tokens stay, so stages bind progressively. Once resolved,
|
|
665
|
-
* `
|
|
593
|
+
* `narrowRule` / `toPrisma` / `toSql` / `toSourceQueries` / `projectPaths` consume the
|
|
666
594
|
* lens unchanged: a bind needs nothing new downstream. `parent:name` draws the same
|
|
667
595
|
* value as the ancestor's `name`. Does not mutate the input.
|
|
668
596
|
*/
|
|
669
|
-
declare const
|
|
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
|
+
|
|
670
613
|
/**
|
|
671
|
-
*
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
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.
|
|
675
619
|
*/
|
|
676
|
-
|
|
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[];
|
|
677
650
|
|
|
678
651
|
type LensPathHop = {
|
|
679
652
|
field: string;
|
|
680
653
|
entry: FieldMapEntry;
|
|
681
654
|
mapName: string;
|
|
682
|
-
|
|
655
|
+
model: string;
|
|
683
656
|
/** The relation path from the lens anchor to the model this hop reads. */
|
|
684
657
|
relPath: string[];
|
|
685
658
|
};
|
|
@@ -700,35 +673,9 @@ type LensPathResolution = {
|
|
|
700
673
|
hops: LensPathHop[];
|
|
701
674
|
};
|
|
702
675
|
|
|
703
|
-
type RuleLensViolation = {
|
|
704
|
-
path: string;
|
|
705
|
-
reason: string;
|
|
706
|
-
};
|
|
707
|
-
type RuleLensCheck = {
|
|
708
|
-
ok: boolean;
|
|
709
|
-
violations: RuleLensViolation[];
|
|
710
|
-
};
|
|
711
|
-
declare const checkRuleAgainstLens: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing) => RuleLensCheck;
|
|
712
|
-
|
|
713
|
-
type CreateLensInput = {
|
|
714
|
-
maps: Record<string, FieldMap>;
|
|
715
|
-
bridges?: Bridge[];
|
|
716
|
-
mapName: string;
|
|
717
|
-
model: string;
|
|
718
|
-
};
|
|
719
|
-
declare const createLens: (input: CreateLensInput) => Lens;
|
|
720
|
-
|
|
721
|
-
type RuleDescription = {
|
|
722
|
-
sources: string[];
|
|
723
|
-
bridgesCrossed: boolean;
|
|
724
|
-
supportedTargets: RuleTarget[];
|
|
725
|
-
violations: string[];
|
|
726
|
-
};
|
|
727
|
-
declare const describeRule: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing) => RuleDescription;
|
|
728
|
-
|
|
729
676
|
type ProjectedVisit = {
|
|
730
677
|
mapName: string;
|
|
731
|
-
|
|
678
|
+
model: string;
|
|
732
679
|
fields: Record<string, FieldMapEntry>;
|
|
733
680
|
whereClauses: Condition[];
|
|
734
681
|
/** Per-field source eligibility wheres, composed across layers (general + path). */
|
|
@@ -739,12 +686,13 @@ type ProjectedVisit = {
|
|
|
739
686
|
/** Per-field option-partition axes for a sourced field (from a SourceSpec's `groupBy`). */
|
|
740
687
|
sourceGroupBys: Record<string, string[]>;
|
|
741
688
|
};
|
|
742
|
-
|
|
689
|
+
/** Each declared path's projected visit, keyed by dotted path from the lens model. */
|
|
690
|
+
type PathProjection = Record<string, ProjectedVisit>;
|
|
743
691
|
/**
|
|
744
692
|
* The materialized option set for one sourced field — the fetched companion to a
|
|
745
693
|
* serializable lens. Its `options` are `{ value, label? }` pairs (the standard
|
|
746
|
-
* `<select>` shape); it feeds both projections: `
|
|
747
|
-
* `path`+`field` (exact), `
|
|
694
|
+
* `<select>` shape); it feeds both projections: `projectPaths` keys by
|
|
695
|
+
* `path`+`field` (exact), `projectModels` by `mapName`+`model`+`field` (union).
|
|
748
696
|
*/
|
|
749
697
|
type SourceValues = {
|
|
750
698
|
path: string;
|
|
@@ -753,61 +701,37 @@ type SourceValues = {
|
|
|
753
701
|
field: string;
|
|
754
702
|
options: readonly SourceOption[];
|
|
755
703
|
};
|
|
756
|
-
type
|
|
704
|
+
type ProjectLensOptions = {
|
|
757
705
|
sourceValues?: readonly SourceValues[];
|
|
758
706
|
};
|
|
759
|
-
declare const projectByPath: (lensOrNarrowing: Lens | LensNarrowing, opts?: ProjectOptions) => PathProjection;
|
|
760
707
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
* against the narrowing at that visit, so a relation the narrowing dropped is `hidden`, a column the
|
|
768
|
-
* model lacks is `missing`, and a segment past a scalar is `pastScalar`. This is the walk
|
|
769
|
-
* `checkRuleAgainstLens` gates a rule's field with, exposed for consumers that resolve paths of their
|
|
770
|
-
* own (template tokens, loop bindings, presence guards).
|
|
771
|
-
*/
|
|
772
|
-
declare const resolveLensPath: (lensOrNarrowing: Lens | LensNarrowing, path: string) => LensPathResolution;
|
|
773
|
-
|
|
774
|
-
/**
|
|
775
|
-
* The values one rule compares at one declared source — keyed the way `projectByPath`
|
|
776
|
-
* keys a source (`path` + `field`), so the caller can join it back to the source's
|
|
777
|
-
* model without spelling a path of its own. A `mapDefaults`-declared source resolves
|
|
778
|
-
* wherever its model appears, so `path` may name a relation chain the narrowing never
|
|
779
|
-
* spelled under `root.relations`; the dotted format is the same.
|
|
780
|
-
*/
|
|
781
|
-
type RuleSourceValues = {
|
|
782
|
-
path: string;
|
|
783
|
-
mapName: string;
|
|
708
|
+
type PrismaWhere = Record<string, unknown>;
|
|
709
|
+
type StepRef = {
|
|
710
|
+
__step: number;
|
|
711
|
+
};
|
|
712
|
+
type GroupByStep = {
|
|
713
|
+
operation: 'groupBy';
|
|
784
714
|
model: string;
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
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
|
+
};
|
|
795
734
|
};
|
|
796
|
-
/**
|
|
797
|
-
* Which values a rule names at each source the lens declares — the lens owns the
|
|
798
|
-
* vocabulary, so it answers questions about it; callers never spell a path. A leaf reaches a
|
|
799
|
-
* source by its absolute path through the lens: nested (`{ field: 'orders', arrayOperator,
|
|
800
|
-
* condition: { field: 'sku' } }`) and dotted (`{ field: 'orders.sku' }`) spellings are one path,
|
|
801
|
-
* resolved by `walkLensPath` — visibility, `mapDefaults`, and the Json boundary all apply, so a
|
|
802
|
-
* source declared in `mapDefaults` answers wherever its model appears. Quantifier-blind on
|
|
803
|
-
* purpose — a `none` relation names its value as much as an `any` one, `notIn` as much as `in` —
|
|
804
|
-
* but shape-aware via the operator catalog: only literal-naming shapes contribute `values`;
|
|
805
|
-
* substring / pattern / range / window operators, and operators the catalog does not know, mark
|
|
806
|
-
* the source `dynamic` instead of inventing values. A relation node's own comparison (an
|
|
807
|
-
* aggregate's threshold, an array `count`) belongs to the node, not to a source. Paths invisible
|
|
808
|
-
* under the lens, unmapped segments, and sub-paths beneath a Json column are silent.
|
|
809
|
-
*/
|
|
810
|
-
declare const ruleSourceValues: (lensOrNarrowing: Lens | LensNarrowing, rule: Condition) => RuleSourceValues[];
|
|
811
735
|
|
|
812
736
|
/** Prisma `select` shape — nested for a grouped source's relation path. */
|
|
813
737
|
type SourceSelect = {
|
|
@@ -818,11 +742,11 @@ type SourceSelect = {
|
|
|
818
742
|
type SourcePrismaQuery = {
|
|
819
743
|
model: string;
|
|
820
744
|
/** Absent for grouped sources — DISTINCT on the value column alone would collapse
|
|
821
|
-
* same-value rows across groups; dedup happens in `
|
|
745
|
+
* same-value rows across groups; dedup happens in `materializeSourceQuery`. */
|
|
822
746
|
distinct?: string[];
|
|
823
747
|
select: SourceSelect;
|
|
824
748
|
where: PrismaWhere;
|
|
825
|
-
/** Present only if the composed where used count operators (run via
|
|
749
|
+
/** Present only if the composed where used count operators (run via executePrismaPlan). */
|
|
826
750
|
steps?: PrismaStep[];
|
|
827
751
|
};
|
|
828
752
|
/** `sql` is null when the composed where uses a predicate SQL can't express
|
|
@@ -854,41 +778,89 @@ type SourceQuery = {
|
|
|
854
778
|
* the projected lens. The WHERE is the field's composed eligibility: the model's
|
|
855
779
|
* own narrowing at that path AND its source where(s). The app runs these (with
|
|
856
780
|
* its own client) to materialize each field's option set — feed the fetched rows
|
|
857
|
-
* to `
|
|
781
|
+
* to `materializeSourceQuery`.
|
|
858
782
|
*/
|
|
859
|
-
declare const
|
|
783
|
+
declare const toSourceQueries: (lensOrNarrowing: Lens | LensNarrowing) => SourceQuery[];
|
|
860
784
|
|
|
861
|
-
type Row$1 = Record<string, unknown>;
|
|
862
785
|
/** Which executor produced the rows — the caller always knows; never guessed. */
|
|
863
786
|
type SourceRowShape = 'prisma' | 'sql';
|
|
864
787
|
/**
|
|
865
788
|
* Materialize one compiled `SourceQuery`'s fetched rows into its `SourceValues` —
|
|
866
|
-
* the executor-side counterpart of `
|
|
789
|
+
* the executor-side counterpart of `toSourceQueries`, so apps never hand-map rows.
|
|
867
790
|
* `rowShape` names the wire format: prisma rows (default) nest each `groupBy` axis
|
|
868
791
|
* (and a dotted `label`) as related objects; sql rows carry them flat under the
|
|
869
792
|
* statement's `__group_i` / `__label` aliases. Grouped queries fetch without
|
|
870
793
|
* DISTINCT, so dedup per (groups, value) happens here.
|
|
871
794
|
*/
|
|
872
|
-
|
|
795
|
+
/** `rowShape`: how the rows came back — nested Prisma rows (the default) or flat SQL rows. */
|
|
796
|
+
type MaterializeSourceQueryOptions = {
|
|
873
797
|
rowShape?: SourceRowShape;
|
|
874
|
-
}
|
|
798
|
+
};
|
|
799
|
+
declare const materializeSourceQuery: (query: SourceQuery, rows: readonly Row[], opts?: MaterializeSourceQueryOptions) => SourceValues;
|
|
875
800
|
|
|
876
|
-
type Row = Record<string, unknown>;
|
|
877
801
|
/**
|
|
878
802
|
* Materialize each sourced field's option set from an already-fetched collection —
|
|
879
|
-
* the in-memory executor of `sources` declarations, alongside `
|
|
803
|
+
* the in-memory executor of `sources` declarations, alongside `toSourceQueries`
|
|
880
804
|
* (which compiles the same declarations to DISTINCT queries for a DB). Rows are
|
|
881
|
-
* the collection fetched
|
|
882
|
-
*
|
|
883
|
-
*
|
|
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
|
|
884
809
|
* option per element, labels take the first non-null value of the label column
|
|
885
810
|
* (a sibling, or a dotted to-one path read through the nested rows), and sorting is
|
|
886
|
-
* numeric-aware in a fixed locale. Feed the result to `
|
|
887
|
-
* `projectByPath` as `{ sourceValues }`.
|
|
811
|
+
* numeric-aware in a fixed locale. Feed the result to `projectLens` as `{ sourceValues }`.
|
|
888
812
|
*/
|
|
889
|
-
declare const
|
|
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;
|
|
890
817
|
|
|
891
|
-
declare const
|
|
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).
|
|
862
|
+
*/
|
|
863
|
+
declare const walkLensPath: (lensOrNarrowing: Lens | LensNarrowing, path: string) => LensPathResolution;
|
|
892
864
|
|
|
893
865
|
type ScopeRef = {
|
|
894
866
|
depth: number;
|
|
@@ -902,7 +874,7 @@ type ScopedRef<S> = {
|
|
|
902
874
|
type ScopeOutOfBounds = {
|
|
903
875
|
outOfBounds: string;
|
|
904
876
|
};
|
|
905
|
-
declare const
|
|
877
|
+
declare const readScopeRef: <S>(ref: string, scopes: readonly S[]) => ScopedRef<S> | ScopeOutOfBounds;
|
|
906
878
|
|
|
907
879
|
/**
|
|
908
880
|
* Execute a Prisma query plan produced by toPrisma().
|
|
@@ -918,75 +890,39 @@ declare const resolveScopeRef: <S>(ref: string, scopes: readonly S[]) => ScopedR
|
|
|
918
890
|
*
|
|
919
891
|
* @example
|
|
920
892
|
* const plan = toPrisma(condition, { map, model: 'User' });
|
|
921
|
-
* const where = await
|
|
893
|
+
* const where = await executePrismaPlan(plan, { post: prisma.post });
|
|
922
894
|
* await prisma.user.findMany({ where });
|
|
923
895
|
*/
|
|
924
|
-
declare const
|
|
896
|
+
declare const executePrismaPlan: (plan: ToPrismaResult, prismaDelegate: Record<string, Record<string, (...args: unknown[]) => unknown>>) => Promise<Record<string, unknown>>;
|
|
925
897
|
|
|
926
898
|
/**
|
|
927
|
-
*
|
|
928
|
-
*
|
|
929
|
-
*
|
|
930
|
-
*
|
|
931
|
-
* - `steps` – optional array of groupBy steps for count-based relation filters
|
|
932
|
-
* (only present when `atLeast`/`atMost`/`exactly` operators are used with a map)
|
|
933
|
-
*
|
|
934
|
-
* When `steps` is present, pass the result to `executePrismaQueryPlan` to
|
|
935
|
-
* resolve step refs before using `where` in a Prisma query.
|
|
936
|
-
*
|
|
937
|
-
* @param condition - The rule condition to convert
|
|
938
|
-
* @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.
|
|
939
903
|
*
|
|
940
904
|
* @example
|
|
941
905
|
* ```typescript
|
|
942
|
-
*
|
|
943
|
-
*
|
|
944
|
-
* // → { where: { status: { equals: 'active' } } }
|
|
945
|
-
*
|
|
946
|
-
* // JSON field detection (map required)
|
|
947
|
-
* toPrisma({ field: 'metadata.theme', operator: Operator.equals, value: 'dark' }, { map, model: 'User' })
|
|
948
|
-
* // → { where: { metadata: { path: ['theme'], equals: 'dark' } } }
|
|
949
|
-
*
|
|
950
|
-
* // Context path ref
|
|
951
|
-
* toPrisma({ field: 'userId', operator: Operator.equals, path: 'currentUser.id' }, { context: { currentUser: { id: '123' } } })
|
|
952
|
-
* // → { where: { userId: { equals: '123' } } }
|
|
906
|
+
* toPrisma({ field: 'status', operator: Operator.equals, value: 'active' }).steps
|
|
907
|
+
* // → [{ operation: 'where', where: { status: { equals: 'active' } } }]
|
|
953
908
|
*
|
|
954
|
-
*
|
|
955
|
-
* const
|
|
956
|
-
* 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);
|
|
957
911
|
* await prisma.user.findMany({ where });
|
|
958
912
|
* ```
|
|
959
913
|
*/
|
|
960
|
-
declare const toPrisma: (condition: Condition, options?:
|
|
914
|
+
declare const toPrisma: (condition: Condition, options?: ToPrismaOptions) => ToPrismaResult;
|
|
961
915
|
|
|
962
|
-
type
|
|
916
|
+
type ToSqlResult = {
|
|
963
917
|
sql: string;
|
|
964
918
|
params: unknown[];
|
|
965
919
|
joins: string[];
|
|
966
920
|
};
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
map?: FieldMap;
|
|
970
|
-
model?: string;
|
|
921
|
+
type ToSqlOptions = CompileOptions & {
|
|
922
|
+
/** The root table alias; `t0` when a map is given. */
|
|
971
923
|
alias?: string;
|
|
972
|
-
context?: Record<string, unknown>;
|
|
973
|
-
} & DateConfig;
|
|
974
|
-
declare const toSql: (condition: Condition, options?: SqlBuildOptions) => SqlResult;
|
|
975
|
-
|
|
976
|
-
type ValidationIssue = {
|
|
977
|
-
path: string;
|
|
978
|
-
message: string;
|
|
979
|
-
code: string;
|
|
980
|
-
};
|
|
981
|
-
type ValidationResult = {
|
|
982
|
-
ok: boolean;
|
|
983
|
-
errors: ValidationIssue[];
|
|
984
924
|
};
|
|
985
|
-
declare const validateRule: (condition: unknown, options?: {
|
|
986
|
-
target?: RuleTarget;
|
|
987
|
-
}) => ValidationResult;
|
|
988
|
-
declare const assertValidRule: (condition: unknown, options?: {
|
|
989
|
-
target?: RuleTarget;
|
|
990
|
-
}) => asserts condition is Condition;
|
|
991
925
|
|
|
992
|
-
|
|
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 };
|