@timeax/digital-service-engine 0.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/core/index.cjs +2933 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +507 -0
- package/dist/core/index.d.ts +507 -0
- package/dist/core/index.js +2899 -0
- package/dist/core/index.js.map +1 -0
- package/dist/react/index.cjs +4015 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +1572 -0
- package/dist/react/index.d.ts +1572 -0
- package/dist/react/index.js +3984 -0
- package/dist/react/index.js.map +1 -0
- package/dist/schema/index.cjs +19 -0
- package/dist/schema/index.cjs.map +1 -0
- package/dist/schema/index.d.cts +671 -0
- package/dist/schema/index.d.ts +671 -0
- package/dist/schema/index.js +1 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/workspace/index.cjs +9755 -0
- package/dist/workspace/index.cjs.map +1 -0
- package/dist/workspace/index.d.cts +1995 -0
- package/dist/workspace/index.d.ts +1995 -0
- package/dist/workspace/index.js +9711 -0
- package/dist/workspace/index.js.map +1 -0
- package/package.json +97 -0
- package/schema/editor-snapshot.schema.json +1138 -0
- package/schema/policies.schema.json +148 -0
- package/schema/service-props.schema.json +772 -0
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
type PricingRole = "base" | "utility";
|
|
2
|
+
type FieldType = "custom" | (string & {});
|
|
3
|
+
/** ── Marker types (live inside meta; non-breaking) ───────────────────── */
|
|
4
|
+
type QuantityMark = {
|
|
5
|
+
quantity?: {
|
|
6
|
+
valueBy: "value" | "length" | "eval";
|
|
7
|
+
code?: string;
|
|
8
|
+
multiply?: number;
|
|
9
|
+
clamp?: {
|
|
10
|
+
min?: number;
|
|
11
|
+
max?: number;
|
|
12
|
+
};
|
|
13
|
+
fallback?: number;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
type UtilityMark = {
|
|
17
|
+
utility?: {
|
|
18
|
+
rate: number;
|
|
19
|
+
mode: "flat" | "per_quantity" | "per_value" | "percent";
|
|
20
|
+
valueBy?: "value" | "length";
|
|
21
|
+
percentBase?: "service_total" | "base_service" | "all";
|
|
22
|
+
label?: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
type WithQuantityDefault = {
|
|
26
|
+
quantityDefault?: number;
|
|
27
|
+
};
|
|
28
|
+
/** ---------------- Core schema (as you designed) ---------------- */
|
|
29
|
+
interface BaseFieldUI {
|
|
30
|
+
name?: string;
|
|
31
|
+
label: string;
|
|
32
|
+
required?: boolean;
|
|
33
|
+
/** Host-defined prop names → typed UI nodes */
|
|
34
|
+
ui?: Record<string, Ui>;
|
|
35
|
+
/** Host-defined prop names → runtime default values (untyped base) */
|
|
36
|
+
defaults?: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
type Ui = UiString | UiNumber | UiBoolean | UiAnyOf | UiArray | UiObject;
|
|
39
|
+
/** string */
|
|
40
|
+
interface UiString {
|
|
41
|
+
type: "string";
|
|
42
|
+
enum?: string[];
|
|
43
|
+
minLength?: number;
|
|
44
|
+
maxLength?: number;
|
|
45
|
+
pattern?: string;
|
|
46
|
+
format?: string;
|
|
47
|
+
}
|
|
48
|
+
/** number */
|
|
49
|
+
interface UiNumber {
|
|
50
|
+
type: "number";
|
|
51
|
+
minimum?: number;
|
|
52
|
+
maximum?: number;
|
|
53
|
+
multipleOf?: number;
|
|
54
|
+
}
|
|
55
|
+
/** boolean */
|
|
56
|
+
interface UiBoolean {
|
|
57
|
+
type: "boolean";
|
|
58
|
+
}
|
|
59
|
+
/** enumerated choices */
|
|
60
|
+
interface UiAnyOf {
|
|
61
|
+
type: "anyOf";
|
|
62
|
+
multiple?: boolean;
|
|
63
|
+
items: Array<{
|
|
64
|
+
type: "string" | "number" | "boolean";
|
|
65
|
+
title?: string;
|
|
66
|
+
description?: string;
|
|
67
|
+
value: string | number | boolean;
|
|
68
|
+
}>;
|
|
69
|
+
}
|
|
70
|
+
/** arrays: homogeneous (item) or tuple (items) */
|
|
71
|
+
interface UiArray {
|
|
72
|
+
type: "array";
|
|
73
|
+
item?: Ui;
|
|
74
|
+
items?: Ui[];
|
|
75
|
+
minItems?: number;
|
|
76
|
+
maxItems?: number;
|
|
77
|
+
uniqueItems?: boolean;
|
|
78
|
+
}
|
|
79
|
+
/** objects: nested props */
|
|
80
|
+
interface UiObject {
|
|
81
|
+
type: "object";
|
|
82
|
+
fields: Record<string, Ui>;
|
|
83
|
+
required?: string[];
|
|
84
|
+
order?: string[];
|
|
85
|
+
}
|
|
86
|
+
type FieldOption = {
|
|
87
|
+
id: string;
|
|
88
|
+
label: string;
|
|
89
|
+
value?: string | number;
|
|
90
|
+
service_id?: number;
|
|
91
|
+
pricing_role?: PricingRole;
|
|
92
|
+
meta?: Record<string, unknown> & UtilityMark & WithQuantityDefault;
|
|
93
|
+
};
|
|
94
|
+
type Field = BaseFieldUI & {
|
|
95
|
+
id: string;
|
|
96
|
+
type: FieldType;
|
|
97
|
+
bind_id?: string | string[];
|
|
98
|
+
name?: string;
|
|
99
|
+
options?: FieldOption[];
|
|
100
|
+
description?: string;
|
|
101
|
+
component?: string;
|
|
102
|
+
pricing_role?: PricingRole;
|
|
103
|
+
meta?: Record<string, unknown> & QuantityMark & UtilityMark & {
|
|
104
|
+
multi?: boolean;
|
|
105
|
+
};
|
|
106
|
+
} & ({
|
|
107
|
+
button?: false;
|
|
108
|
+
service_id?: undefined;
|
|
109
|
+
} | ({
|
|
110
|
+
button: true;
|
|
111
|
+
service_id?: number;
|
|
112
|
+
} & WithQuantityDefault));
|
|
113
|
+
type ConstraintKey = string;
|
|
114
|
+
type Tag = {
|
|
115
|
+
id: string;
|
|
116
|
+
label: string;
|
|
117
|
+
bind_id?: string;
|
|
118
|
+
service_id?: number;
|
|
119
|
+
includes?: string[];
|
|
120
|
+
excludes?: string[];
|
|
121
|
+
meta?: Record<string, unknown> & WithQuantityDefault;
|
|
122
|
+
/**
|
|
123
|
+
* Which flags are set for this tag. If a flag is not set, it's inherited from the nearest ancestor with a value set.
|
|
124
|
+
*/
|
|
125
|
+
constraints?: Partial<Record<ConstraintKey, boolean>>;
|
|
126
|
+
/** Which ancestor defined the *effective* value for each flag (nearest source). */
|
|
127
|
+
constraints_origin?: Partial<Record<ConstraintKey, string>>;
|
|
128
|
+
/**
|
|
129
|
+
* Present only when a child explicitly set a different value but was overridden
|
|
130
|
+
* by an ancestor during normalisation.
|
|
131
|
+
*/
|
|
132
|
+
constraints_overrides?: Partial<Record<ConstraintKey, {
|
|
133
|
+
from: boolean;
|
|
134
|
+
to: boolean;
|
|
135
|
+
origin: string;
|
|
136
|
+
}>>;
|
|
137
|
+
};
|
|
138
|
+
type ServiceProps = {
|
|
139
|
+
order_for_tags?: Record<string, string[]>;
|
|
140
|
+
filters: Tag[];
|
|
141
|
+
fields: Field[];
|
|
142
|
+
includes_for_buttons?: Record<string, string[]>;
|
|
143
|
+
excludes_for_buttons?: Record<string, string[]>;
|
|
144
|
+
schema_version?: string;
|
|
145
|
+
fallbacks?: ServiceFallback;
|
|
146
|
+
};
|
|
147
|
+
type ServiceIdRef = number | string;
|
|
148
|
+
type NodeIdRef = string;
|
|
149
|
+
type ServiceFallback = {
|
|
150
|
+
/** Node-scoped fallbacks: prefer these when that node’s primary service fails */
|
|
151
|
+
nodes?: Record<NodeIdRef, ServiceIdRef[]>;
|
|
152
|
+
/** Primary→fallback list used when no node-scoped entry is present */
|
|
153
|
+
global?: Record<ServiceIdRef, ServiceIdRef[]>;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
type NodeKind$1 = "tag" | "field" | "comment" | "option";
|
|
157
|
+
type EdgeKind = "child" | "bind" | "include" | "exclude" | "error" | "anchor";
|
|
158
|
+
type GraphNode = {
|
|
159
|
+
id: string;
|
|
160
|
+
kind: NodeKind$1;
|
|
161
|
+
bind_type?: "bound" | "utility" | null;
|
|
162
|
+
errors?: string[];
|
|
163
|
+
label: string;
|
|
164
|
+
};
|
|
165
|
+
type GraphEdge = {
|
|
166
|
+
from: string;
|
|
167
|
+
to: string;
|
|
168
|
+
kind: EdgeKind;
|
|
169
|
+
meta?: Record<string, unknown>;
|
|
170
|
+
};
|
|
171
|
+
type GraphSnapshot = {
|
|
172
|
+
nodes: GraphNode[];
|
|
173
|
+
edges: GraphEdge[];
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
type TimeRangeEstimate = {
|
|
177
|
+
min_seconds?: number;
|
|
178
|
+
max_seconds?: number;
|
|
179
|
+
label?: string;
|
|
180
|
+
meta?: Record<string, unknown>;
|
|
181
|
+
};
|
|
182
|
+
type SpeedEstimate = {
|
|
183
|
+
amount?: number;
|
|
184
|
+
per?: "minute" | "hour" | "day" | "week" | "month";
|
|
185
|
+
unit?: string;
|
|
186
|
+
label?: string;
|
|
187
|
+
meta?: Record<string, unknown>;
|
|
188
|
+
};
|
|
189
|
+
type ServiceEstimates = {
|
|
190
|
+
start?: TimeRangeEstimate;
|
|
191
|
+
speed?: SpeedEstimate;
|
|
192
|
+
average?: TimeRangeEstimate;
|
|
193
|
+
meta?: Record<string, unknown>;
|
|
194
|
+
};
|
|
195
|
+
type ServiceFlag = {
|
|
196
|
+
enabled: boolean;
|
|
197
|
+
description: string;
|
|
198
|
+
meta?: Record<string, unknown>;
|
|
199
|
+
};
|
|
200
|
+
type IdType = string | number;
|
|
201
|
+
type ServiceFlags = Record<string, ServiceFlag>;
|
|
202
|
+
type DgpServiceCapability = {
|
|
203
|
+
id: IdType;
|
|
204
|
+
name?: string;
|
|
205
|
+
rate: number;
|
|
206
|
+
min?: number;
|
|
207
|
+
max?: number;
|
|
208
|
+
category?: string;
|
|
209
|
+
flags?: ServiceFlags;
|
|
210
|
+
estimates?: ServiceEstimates;
|
|
211
|
+
meta?: Record<string, unknown>;
|
|
212
|
+
[x: string]: any;
|
|
213
|
+
};
|
|
214
|
+
type DgpServiceMap = Record<string, DgpServiceCapability> & Record<number, DgpServiceCapability>;
|
|
215
|
+
|
|
216
|
+
type ValidationCode = "root_missing" | "cycle_in_tags" | "bad_bind_reference" | "duplicate_id" | "duplicate_tag_label" | "duplicate_field_name" | "label_missing" | "duplicate_visible_label" | "bad_option_key" | "option_include_exclude_conflict" | "service_field_missing_service_id" | "user_input_field_has_service_option" | "rate_mismatch_across_base" | "utility_without_base" | "unsupported_constraint" | "constraint_contradiction" | "custom_component_missing" | "policy_violation" | "field_unbound" | "constraint_overridden" | "unsupported_constraint_option" | "custom_component_unresolvable" | "quantity_multiple_markers" | "utility_with_service_id" | "utility_missing_rate" | "utility_invalid_mode" | "fallback_bad_node" | "fallback_unknown_service" | "fallback_cycle" | "fallback_no_primary" | "fallback_rate_violation" | "fallback_constraint_mismatch" | "fallback_no_tag_context";
|
|
217
|
+
type ValidationError = {
|
|
218
|
+
code: ValidationCode;
|
|
219
|
+
message: string;
|
|
220
|
+
severity: "error" | "warning" | "info";
|
|
221
|
+
nodeId?: string;
|
|
222
|
+
details?: Record<string, unknown> & {
|
|
223
|
+
affectedIds?: string[];
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
type ServiceWhereOp = "eq" | "neq" | "in" | "nin" | "exists" | "truthy" | "falsy" | "sw";
|
|
227
|
+
/**
|
|
228
|
+
* Host-extensible service filter clause.
|
|
229
|
+
* `path` should usually be "service.<prop>" or "service.meta.<prop>" etc.
|
|
230
|
+
*/
|
|
231
|
+
type ServiceWhereClause = {
|
|
232
|
+
path: string;
|
|
233
|
+
op?: ServiceWhereOp;
|
|
234
|
+
value?: unknown;
|
|
235
|
+
};
|
|
236
|
+
type DynamicRule = {
|
|
237
|
+
id: string;
|
|
238
|
+
label?: string;
|
|
239
|
+
scope: "global" | "visible_group";
|
|
240
|
+
subject: "services";
|
|
241
|
+
/**
|
|
242
|
+
* Package-level filter surface:
|
|
243
|
+
* - role/tag/field are core to the builder schema
|
|
244
|
+
* - where[] allows hosts to filter against extra service properties (handler_id/platform_id/type/key/category_id/etc.)
|
|
245
|
+
*/
|
|
246
|
+
filter?: {
|
|
247
|
+
role?: "base" | "utility" | "both";
|
|
248
|
+
tag_id?: string | string[];
|
|
249
|
+
field_id?: string | string[];
|
|
250
|
+
where?: ServiceWhereClause[];
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* Projection is intentionally open:
|
|
254
|
+
* hosts may project custom service properties.
|
|
255
|
+
*/
|
|
256
|
+
projection?: "service.id" | "service.name" | "service.rate" | "service.min" | "service.max" | "service.category" | string;
|
|
257
|
+
op: "all_equal" | "unique" | "no_mix" | "all_true" | "any_true" | "max_count" | "min_count";
|
|
258
|
+
value?: number | boolean;
|
|
259
|
+
severity?: "error" | "warning";
|
|
260
|
+
message?: string;
|
|
261
|
+
};
|
|
262
|
+
type ValidatorOptions = {
|
|
263
|
+
serviceMap?: DgpServiceMap;
|
|
264
|
+
allowUnsafe?: boolean;
|
|
265
|
+
selectedOptionKeys?: string[];
|
|
266
|
+
globalUtilityGuard?: boolean;
|
|
267
|
+
policies?: DynamicRule[];
|
|
268
|
+
fallbackSettings?: FallbackSettings;
|
|
269
|
+
};
|
|
270
|
+
type RatePolicy = {
|
|
271
|
+
kind: "lte_primary";
|
|
272
|
+
} | {
|
|
273
|
+
kind: "within_pct";
|
|
274
|
+
pct: number;
|
|
275
|
+
} | {
|
|
276
|
+
kind: "at_least_pct_lower";
|
|
277
|
+
pct: number;
|
|
278
|
+
};
|
|
279
|
+
type FallbackSettings = {
|
|
280
|
+
/** Require fallbacks to satisfy tag constraints (dripfeed/refill/cancel) when a tag context is known. Default: true */
|
|
281
|
+
requireConstraintFit?: boolean;
|
|
282
|
+
/** Rate rule policy. Default: { kind: 'lte_primary' } i.e. candidate.rate <= primary.rate */
|
|
283
|
+
ratePolicy?: RatePolicy;
|
|
284
|
+
/** When multiple candidates remain, choose first (priority) or cheapest. Default: 'priority' */
|
|
285
|
+
selectionStrategy?: "priority" | "cheapest";
|
|
286
|
+
/** Validation mode: 'strict' → node-scoped violations reported as ValidationError; 'dev' → only collect diagnostics. Default: 'strict' */
|
|
287
|
+
mode?: "strict" | "dev";
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
type NormaliseOptions = {
|
|
291
|
+
/** default pricing role for fields/options when missing */
|
|
292
|
+
defaultPricingRole?: PricingRole;
|
|
293
|
+
constraints?: string[];
|
|
294
|
+
};
|
|
295
|
+
declare function normalise(input: unknown, opts?: NormaliseOptions): ServiceProps;
|
|
296
|
+
|
|
297
|
+
declare function validate(props: ServiceProps, ctx?: ValidatorOptions): ValidationError[];
|
|
298
|
+
|
|
299
|
+
/** Options you can set on the builder (used for validation/visibility) */
|
|
300
|
+
type BuilderOptions = Omit<ValidatorOptions, "serviceMap"> & {
|
|
301
|
+
serviceMap?: DgpServiceMap;
|
|
302
|
+
/** max history entries for undo/redo */
|
|
303
|
+
historyLimit?: number;
|
|
304
|
+
/**
|
|
305
|
+
* Field ids whose options should be shown as nodes in the graph.
|
|
306
|
+
* If a field id is NOT in this set, its options are not materialized as nodes:
|
|
307
|
+
* - include/exclude wires keyed by an option id will be drawn from the FIELD instead.
|
|
308
|
+
*/
|
|
309
|
+
showOptionNodes?: Set<string> | string[];
|
|
310
|
+
};
|
|
311
|
+
interface Builder {
|
|
312
|
+
/** Replace current payload (injects root if missing, rebuilds indexes) */
|
|
313
|
+
load(props: ServiceProps): void;
|
|
314
|
+
/** Graph for visualisation */
|
|
315
|
+
tree(): GraphSnapshot;
|
|
316
|
+
/** Deterministic save payload (drops unbound utility fields, prunes dead maps) */
|
|
317
|
+
cleanedProps(): ServiceProps;
|
|
318
|
+
/** Validation errors for current state */
|
|
319
|
+
errors(): ValidationError[];
|
|
320
|
+
/**
|
|
321
|
+
* Compute IDs of fields visible under a tag.
|
|
322
|
+
* If selectedOptionKeys provided, applies option-level include/exclude.
|
|
323
|
+
* NOTE: keys are “button ids”: either option.id or field.id for option-less buttons.
|
|
324
|
+
*/
|
|
325
|
+
visibleFields(tagId: string, selectedOptionKeys?: string[]): string[];
|
|
326
|
+
/** Update builder options (validator context etc.) */
|
|
327
|
+
setOptions(patch: Partial<BuilderOptions>): void;
|
|
328
|
+
/** History */
|
|
329
|
+
undo(): boolean;
|
|
330
|
+
redo(): boolean;
|
|
331
|
+
/** Access the current props (already normalised) */
|
|
332
|
+
getProps(): ServiceProps;
|
|
333
|
+
/** Service map for validation/rules */
|
|
334
|
+
getServiceMap(): DgpServiceMap;
|
|
335
|
+
getConstraints(): {
|
|
336
|
+
id: string;
|
|
337
|
+
label: string;
|
|
338
|
+
description: string;
|
|
339
|
+
value: string;
|
|
340
|
+
}[];
|
|
341
|
+
}
|
|
342
|
+
declare function createBuilder(opts?: BuilderOptions): Builder;
|
|
343
|
+
|
|
344
|
+
type FailedFallbackContext = {
|
|
345
|
+
scope: "node" | "global";
|
|
346
|
+
nodeId?: string;
|
|
347
|
+
primary: ServiceIdRef;
|
|
348
|
+
candidate: ServiceIdRef;
|
|
349
|
+
tagContext?: string;
|
|
350
|
+
reason: "unknown_service" | "no_primary" | "rate_violation" | "constraint_mismatch" | "cycle" | "no_tag_context";
|
|
351
|
+
details?: Record<string, unknown>;
|
|
352
|
+
};
|
|
353
|
+
declare function resolveServiceFallback(params: {
|
|
354
|
+
primary: ServiceIdRef;
|
|
355
|
+
nodeId?: NodeIdRef;
|
|
356
|
+
tagId?: string;
|
|
357
|
+
services: DgpServiceMap;
|
|
358
|
+
fallbacks?: ServiceFallback;
|
|
359
|
+
settings?: FallbackSettings;
|
|
360
|
+
props: ServiceProps;
|
|
361
|
+
}): ServiceIdRef | null;
|
|
362
|
+
declare function collectFailedFallbacks(props: ServiceProps, services: DgpServiceMap, settings?: FallbackSettings): FailedFallbackContext[];
|
|
363
|
+
/**
|
|
364
|
+
* Return all fallback candidates that are eligible for the given primary,
|
|
365
|
+
* respecting:
|
|
366
|
+
* - node-scoped list first (if nodeId provided), then global list for `primary`
|
|
367
|
+
* - rate policy vs. primary
|
|
368
|
+
* - (optional) tag constraint fit, only when tagId is provided and requireConstraintFit=true
|
|
369
|
+
* - excludes (including primary automatically)
|
|
370
|
+
* - selectionStrategy: 'priority' keeps list order, 'cheapest' sorts by rate asc
|
|
371
|
+
* - unique (dedupe) and optional limit
|
|
372
|
+
*/
|
|
373
|
+
declare function getEligibleFallbacks(params: {
|
|
374
|
+
primary: ServiceIdRef;
|
|
375
|
+
nodeId?: NodeIdRef;
|
|
376
|
+
tagId?: string;
|
|
377
|
+
services: DgpServiceMap;
|
|
378
|
+
fallbacks?: ServiceFallback;
|
|
379
|
+
settings?: FallbackSettings;
|
|
380
|
+
props: ServiceProps;
|
|
381
|
+
exclude?: Array<ServiceIdRef>;
|
|
382
|
+
unique?: boolean;
|
|
383
|
+
limit?: number;
|
|
384
|
+
}): ServiceIdRef[];
|
|
385
|
+
|
|
386
|
+
type BaseCandidate = {
|
|
387
|
+
kind: "field" | "option";
|
|
388
|
+
id: string;
|
|
389
|
+
label?: string;
|
|
390
|
+
service_id: number;
|
|
391
|
+
rate: number;
|
|
392
|
+
};
|
|
393
|
+
/** Result for each violation discovered during deep simulation. */
|
|
394
|
+
type RateCoherenceDiagnostic = {
|
|
395
|
+
scope: "visible_group";
|
|
396
|
+
tagId: string;
|
|
397
|
+
/** The “primary” used for comparison in this simulation:
|
|
398
|
+
* anchor service if present; otherwise, the first base service among simulated candidates.
|
|
399
|
+
* (Tag service is never used as primary.)
|
|
400
|
+
*/
|
|
401
|
+
primary: BaseCandidate;
|
|
402
|
+
/** The item that violated the policy against the primary. */
|
|
403
|
+
offender: {
|
|
404
|
+
kind: "field" | "option";
|
|
405
|
+
id: string;
|
|
406
|
+
label?: string;
|
|
407
|
+
service_id: number;
|
|
408
|
+
rate: number;
|
|
409
|
+
};
|
|
410
|
+
policy: RatePolicy["kind"];
|
|
411
|
+
policyPct?: number;
|
|
412
|
+
message: string;
|
|
413
|
+
/** Which button triggered this simulation */
|
|
414
|
+
simulationAnchor: {
|
|
415
|
+
kind: "field" | "option";
|
|
416
|
+
id: string;
|
|
417
|
+
fieldId: string;
|
|
418
|
+
label?: string;
|
|
419
|
+
};
|
|
420
|
+
};
|
|
421
|
+
/** Run deep rate-coherence validation by simulating each button selection in the active tag. */
|
|
422
|
+
declare function validateRateCoherenceDeep(params: {
|
|
423
|
+
builder: Builder;
|
|
424
|
+
services: DgpServiceMap;
|
|
425
|
+
tagId: string;
|
|
426
|
+
/** Optional rate policy (defaults to { kind: 'lte_primary' }) */
|
|
427
|
+
ratePolicy?: RatePolicy;
|
|
428
|
+
}): RateCoherenceDiagnostic[];
|
|
429
|
+
|
|
430
|
+
type NodeKind = "tag" | "field" | "option" | "unknown";
|
|
431
|
+
type RelKind = "self" | "ancestor" | "descendant" | "unrelated";
|
|
432
|
+
interface AncestryHit {
|
|
433
|
+
kind: RelKind;
|
|
434
|
+
node: TagNode;
|
|
435
|
+
index: number;
|
|
436
|
+
direct: boolean;
|
|
437
|
+
path: string[];
|
|
438
|
+
}
|
|
439
|
+
interface WithAncestry {
|
|
440
|
+
ancestry(baseTag: string | TagNode): readonly AncestryHit[];
|
|
441
|
+
isAncestorOf(baseTag: string | TagNode): boolean;
|
|
442
|
+
isDescendantOf(baseTag: string | TagNode): boolean;
|
|
443
|
+
isWithin(baseTag: string | TagNode): boolean;
|
|
444
|
+
}
|
|
445
|
+
interface TagNode extends WithAncestry {
|
|
446
|
+
kind: "tag";
|
|
447
|
+
id: string;
|
|
448
|
+
raw: Tag;
|
|
449
|
+
includes: ReadonlySet<string>;
|
|
450
|
+
excludes: ReadonlySet<string>;
|
|
451
|
+
isInherited?: boolean;
|
|
452
|
+
parent(): TagNode | undefined;
|
|
453
|
+
children(): readonly TagNode[];
|
|
454
|
+
ancestors(): readonly {
|
|
455
|
+
node: TagNode;
|
|
456
|
+
direct: boolean;
|
|
457
|
+
index: number;
|
|
458
|
+
path: string[];
|
|
459
|
+
}[];
|
|
460
|
+
pathTo(descendant: string | TagNode): string[] | null;
|
|
461
|
+
isBoundTo(tagId: string | TagNode): boolean;
|
|
462
|
+
getDescendant(id: string): FieldNode | undefined;
|
|
463
|
+
getDescendants(): readonly FieldNode[];
|
|
464
|
+
}
|
|
465
|
+
interface FieldNode extends WithAncestry {
|
|
466
|
+
kind: "field";
|
|
467
|
+
id: string;
|
|
468
|
+
raw: Field;
|
|
469
|
+
includes: ReadonlySet<string>;
|
|
470
|
+
excludes: ReadonlySet<string>;
|
|
471
|
+
isInherited?: boolean;
|
|
472
|
+
bindIds(): readonly string[];
|
|
473
|
+
ownerTags(): readonly TagNode[];
|
|
474
|
+
isBoundTo(tagId: string | TagNode): boolean;
|
|
475
|
+
getDescendant(id: string, contextId?: string): FieldNode | undefined;
|
|
476
|
+
getDescendants(tagId?: string): readonly FieldNode[];
|
|
477
|
+
}
|
|
478
|
+
interface OptionNode extends WithAncestry {
|
|
479
|
+
kind: "option";
|
|
480
|
+
id: string;
|
|
481
|
+
raw: FieldOption;
|
|
482
|
+
includes: ReadonlySet<string>;
|
|
483
|
+
excludes: ReadonlySet<string>;
|
|
484
|
+
isInherited?: boolean;
|
|
485
|
+
field(): FieldNode;
|
|
486
|
+
ownerTags(): readonly TagNode[];
|
|
487
|
+
isBoundTo(tagId: string | TagNode): boolean;
|
|
488
|
+
getDescendant(id: string, contextId?: string): FieldNode | undefined;
|
|
489
|
+
getDescendants(tagId?: string): readonly FieldNode[];
|
|
490
|
+
}
|
|
491
|
+
interface UnknownNode extends WithAncestry {
|
|
492
|
+
kind: "unknown";
|
|
493
|
+
id: string;
|
|
494
|
+
includes: ReadonlySet<string>;
|
|
495
|
+
excludes: ReadonlySet<string>;
|
|
496
|
+
isInherited?: boolean;
|
|
497
|
+
}
|
|
498
|
+
type AnyNode = TagNode | FieldNode | OptionNode | UnknownNode;
|
|
499
|
+
interface NodeIndex {
|
|
500
|
+
getNode(input: string | Tag | Field | FieldOption): AnyNode;
|
|
501
|
+
getTag(id: string): TagNode | undefined;
|
|
502
|
+
getField(id: string): FieldNode | undefined;
|
|
503
|
+
getOption(id: string): OptionNode | undefined;
|
|
504
|
+
}
|
|
505
|
+
declare function createNodeIndex(builder: Builder): NodeIndex;
|
|
506
|
+
|
|
507
|
+
export { type AncestryHit, type AnyNode, type Builder, type BuilderOptions, type FailedFallbackContext, type FieldNode, type NodeIndex, type NodeKind, type NormaliseOptions, type OptionNode, type RateCoherenceDiagnostic, type RelKind, type TagNode, type UnknownNode, type WithAncestry, collectFailedFallbacks, createBuilder, createNodeIndex, getEligibleFallbacks, normalise, resolveServiceFallback, validate, validateRateCoherenceDeep };
|