@object-ui/core 16.1.0 → 17.2.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/CHANGELOG.md +1881 -4
- package/dist/actions/ActionEngine.d.ts +11 -1
- package/dist/actions/ActionEngine.js +14 -3
- package/dist/actions/ActionRunner.d.ts +199 -24
- package/dist/actions/ActionRunner.js +189 -84
- package/dist/actions/actionKeys.d.ts +135 -0
- package/dist/actions/actionKeys.js +283 -0
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/adapters/ApiDataSource.js +10 -1
- package/dist/adapters/ValueDataSource.d.ts +2 -2
- package/dist/evaluator/fieldRules.d.ts +0 -2
- package/dist/evaluator/fieldRules.js +3 -2
- package/dist/evaluator/optionLint.js +5 -2
- package/dist/evaluator/optionRules.d.ts +13 -6
- package/dist/evaluator/optionRules.js +0 -23
- package/dist/index.d.ts +4 -0
- package/dist/index.js +7 -0
- package/dist/query/query-ast.d.ts +6 -6
- package/dist/query/query-ast.js +2 -2
- package/dist/registry/PluginSystem.d.ts +15 -5
- package/dist/registry/PluginSystem.js +1 -1
- package/dist/registry/Registry.d.ts +81 -2
- package/dist/registry/Registry.js +102 -2
- package/dist/registry/WidgetRegistry.d.ts +7 -7
- package/dist/registry/WidgetRegistry.js +1 -1
- package/dist/registry/public-blocks.js +52 -1
- package/dist/styling/scoped-styles.d.ts +14 -8
- package/dist/theme/ThemeEngine.js +0 -12
- package/dist/utils/chart-series.d.ts +42 -2
- package/dist/utils/chart-series.js +55 -0
- package/dist/utils/column-identity.d.ts +110 -0
- package/dist/utils/column-identity.js +210 -0
- package/dist/utils/dashboard-filters.d.ts +11 -2
- package/dist/utils/dashboard-filters.js +99 -4
- package/dist/utils/dataset-format.d.ts +13 -1
- package/dist/utils/dataset-format.js +10 -2
- package/dist/utils/expand-fields.js +8 -8
- package/dist/utils/filter-converter.d.ts +47 -0
- package/dist/utils/filter-converter.js +94 -7
- package/dist/utils/filter-tokens.d.ts +108 -0
- package/dist/utils/filter-tokens.js +180 -0
- package/dist/utils/freeze-schema.d.ts +14 -6
- package/dist/utils/freeze-schema.js +14 -6
- package/dist/utils/managedBy.d.ts +97 -51
- package/dist/utils/managedBy.js +117 -53
- package/dist/utils/normalize-list-view.d.ts +109 -0
- package/dist/utils/normalize-list-view.js +255 -0
- package/dist/utils/sort-values.d.ts +52 -0
- package/dist/utils/sort-values.js +125 -0
- package/dist/validation/index.d.ts +10 -1
- package/dist/validation/index.js +10 -1
- package/dist/validation/required-presence.d.ts +31 -0
- package/dist/validation/required-presence.js +36 -0
- package/dist/validation/schema-validator.d.ts +24 -8
- package/dist/validation/validators/index.d.ts +7 -1
- package/dist/validation/validators/index.js +7 -1
- package/dist/validation/validators/object-validation-engine.d.ts +151 -31
- package/dist/validation/validators/object-validation-engine.js +275 -142
- package/package.json +4 -4
|
@@ -6,23 +6,92 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
|
-
* @object-ui/core - Object-Level Validation Engine
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* -
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* -
|
|
19
|
-
*
|
|
20
|
-
*
|
|
9
|
+
* @object-ui/core - Object-Level Validation Engine — **DEPRECATED** (#3110)
|
|
10
|
+
*
|
|
11
|
+
* A client-side pre-check of the rules an object declares in
|
|
12
|
+
* `ObjectSchema.validations`. The authority is the server
|
|
13
|
+
* (`objectql/src/validation/rule-validator.ts`), which evaluates the same rules
|
|
14
|
+
* on the write path.
|
|
15
|
+
*
|
|
16
|
+
* ## Why this is deprecated rather than finished
|
|
17
|
+
*
|
|
18
|
+
* Validation rules are ENFORCEMENT, and enforcement is single-implementation on
|
|
19
|
+
* the server by design. `evaluator/fieldRules.ts` draws that line explicitly:
|
|
20
|
+
* PRESENTATION predicates (`visibleWhen` / `readonlyWhen` / `requiredWhen`) are
|
|
21
|
+
* evaluated client-side by delegating to the canonical `ExpressionEngine`,
|
|
22
|
+
* "rather than re-implementing a parallel evaluator" (ADR-0036). This module is
|
|
23
|
+
* that parallel evaluator, on the enforcement side of the line.
|
|
24
|
+
*
|
|
25
|
+
* #3103 converged its semantics onto the server rule-for-rule, with eight
|
|
26
|
+
* mutation-tested gates — and it STILL left a known divergence: the server
|
|
27
|
+
* carries ADR-0113's legacy-violation exemption (reject only when the merged
|
|
28
|
+
* state violates AND this write makes it worse, so a pre-existing violation on
|
|
29
|
+
* an old row passes), and this engine does not. Editing an unrelated field on a
|
|
30
|
+
* legacy row would be blocked here and accepted there. That is the argument in
|
|
31
|
+
* one line: mirroring cross-repo behaviour is structurally unreliable, not
|
|
32
|
+
* unreliable-this-time.
|
|
33
|
+
*
|
|
34
|
+
* ## What to use instead
|
|
35
|
+
*
|
|
36
|
+
* Let the write fail and render the server's rejection — it is already
|
|
37
|
+
* structured (`field` / `code` / `message`, plus a label since objectstack#3957).
|
|
38
|
+
* If pre-submit feedback is wanted, the answer is a **validate-only (dry-run)
|
|
39
|
+
* write** on the server: identical UX, zero parity risk, and it also covers the
|
|
40
|
+
* two rule kinds a client can never check — `unique` (needs the database) and
|
|
41
|
+
* `json_schema` (ajv lives server-side).
|
|
42
|
+
*
|
|
43
|
+
* Nothing here has been removed or changed in behaviour; existing callers keep
|
|
44
|
+
* working. `validation-engine-stays-unwired.test.ts` fails if a production
|
|
45
|
+
* module starts importing this one, so the decision is a mechanism rather than
|
|
46
|
+
* this comment (#3017).
|
|
47
|
+
*
|
|
48
|
+
* ## When to revisit
|
|
49
|
+
*
|
|
50
|
+
* Offline writes (`OfflineConfig`). With no server to ask, a client evaluator
|
|
51
|
+
* stops being redundant and becomes necessary. The precondition then is
|
|
52
|
+
* conformance fixtures shipped by `@objectstack/spec` — golden
|
|
53
|
+
* (rule, record, verdict) triples both repos run in CI — because that is the
|
|
54
|
+
* only thing that turns cross-repo parity into a mechanism instead of a habit.
|
|
55
|
+
* Reverse the decision in #3110 before reversing it here.
|
|
56
|
+
*
|
|
57
|
+
* ## Semantics (unchanged, for as long as this exists)
|
|
58
|
+
*
|
|
59
|
+
* The rule types come from `@object-ui/types`, which derives them from
|
|
60
|
+
* `@objectstack/spec/data` (objectstack#4115). Semantics mirrored from the
|
|
61
|
+
* server:
|
|
62
|
+
*
|
|
63
|
+
* - **Polarity.** A `script` / `cross_field` `condition` and a `conditional`
|
|
64
|
+
* `when` express the FAILURE condition: predicate TRUE ⇒ rule VIOLATED.
|
|
65
|
+
* - **Fail-open on broken, fail-closed on violated.** A predicate that cannot
|
|
66
|
+
* be evaluated (parse error, unknown identifier, unusable expression
|
|
67
|
+
* envelope) is a broken rule, not a violated one — it is skipped, not
|
|
68
|
+
* reported. Likewise a malformed `regex`.
|
|
69
|
+
* - **Spec defaults, not falsy reads.** `active` defaults to `true` and
|
|
70
|
+
* `events` to `['insert','update']` — they arrive absent from `/meta`
|
|
71
|
+
* because the spec applies those defaults at parse time. Reading an absent
|
|
72
|
+
* `active` as "off" would silently disable every rule authored without it.
|
|
73
|
+
* - **`priority` orders execution** (lower first, stable).
|
|
74
|
+
* - **`format` and `state_machine` only fire when the write TOUCHES the
|
|
75
|
+
* field**, matching the server; emptiness and requiredness belong to the
|
|
76
|
+
* field-shape validator.
|
|
77
|
+
*
|
|
78
|
+
* Two documented divergences from the server, both in the safe direction:
|
|
79
|
+
*
|
|
80
|
+
* 1. The default evaluator is a small non-CEL parser (see
|
|
81
|
+
* `SimpleExpressionEvaluator`), so a predicate using real CEL constructs
|
|
82
|
+
* evaluates to nothing and fails open. Pass a CEL-backed
|
|
83
|
+
* `ValidationExpressionEvaluator` to close that gap.
|
|
84
|
+
* 2. `unique` / `async` / `range` rules are still dispatched. They are
|
|
85
|
+
* @deprecated objectui-local variants that the spec's `ValidationRuleSchema`
|
|
86
|
+
* rejects outright, so they cannot arrive from `/meta` — only a caller
|
|
87
|
+
* building rules by hand can produce one.
|
|
21
88
|
*
|
|
22
89
|
* @module object-validation-engine
|
|
23
90
|
* @packageDocumentation
|
|
24
91
|
*/
|
|
25
92
|
import type { ObjectValidationRule } from '@object-ui/types';
|
|
93
|
+
/** Write contexts a rule can run on. The spec retired `delete` (objectstack#3184). */
|
|
94
|
+
export type ObjectValidationEvent = 'insert' | 'update';
|
|
26
95
|
/**
|
|
27
96
|
* Validation context for object-level validations
|
|
28
97
|
*/
|
|
@@ -56,63 +125,114 @@ export interface ValidationExpressionEvaluator {
|
|
|
56
125
|
evaluate(expression: string, context: Record<string, any>): any;
|
|
57
126
|
}
|
|
58
127
|
/**
|
|
59
|
-
* Object-Level Validation Engine
|
|
60
|
-
*
|
|
128
|
+
* Object-Level Validation Engine — the client pre-check described at the top of
|
|
129
|
+
* this module.
|
|
130
|
+
*
|
|
131
|
+
* @deprecated (#3110) Validation rules are enforcement, and enforcement is
|
|
132
|
+
* single-implementation on the server (`objectql`'s rule-validator). Render the
|
|
133
|
+
* server's rejection instead; for pre-submit feedback, use a validate-only
|
|
134
|
+
* (dry-run) write. Still functional and still correct as of #3103 — but it
|
|
135
|
+
* cannot stay in step with the server without a conformance-fixture mechanism
|
|
136
|
+
* that does not exist yet. See the module header.
|
|
61
137
|
*/
|
|
62
138
|
export declare class ObjectValidationEngine {
|
|
63
139
|
private expressionEvaluator;
|
|
64
140
|
private uniquenessChecker?;
|
|
65
141
|
constructor(expressionEvaluator?: ValidationExpressionEvaluator, uniquenessChecker?: (fields: string[], values: Record<string, any>, scope?: string, context?: ObjectValidationContext) => Promise<boolean>);
|
|
66
142
|
/**
|
|
67
|
-
* Validate a record against a set of validation rules
|
|
143
|
+
* Validate a record against a set of validation rules.
|
|
144
|
+
*
|
|
145
|
+
* Rules run in `priority` order (lower first, stable within a priority), and
|
|
146
|
+
* only when `active` is not explicitly `false` and `events` covers this write
|
|
147
|
+
* context — reading the spec's defaults, not the falsiness of an absent key.
|
|
68
148
|
*/
|
|
69
|
-
validateRecord(rules: ObjectValidationRule[], context: ObjectValidationContext, event?:
|
|
149
|
+
validateRecord(rules: ObjectValidationRule[], context: ObjectValidationContext, event?: ObjectValidationEvent): Promise<ObjectValidationResult[]>;
|
|
70
150
|
/**
|
|
71
|
-
* Validate a single rule
|
|
151
|
+
* Validate a single rule.
|
|
152
|
+
*
|
|
153
|
+
* `rule` is widened past `ObjectValidationRule` because a `conditional`'s
|
|
154
|
+
* `then` / `otherwise` branch may be any rule the SPEC's union admits —
|
|
155
|
+
* including `json_schema`, which this engine does not implement.
|
|
72
156
|
*/
|
|
73
157
|
private validateRule;
|
|
74
158
|
/**
|
|
75
|
-
*
|
|
159
|
+
* The evaluation scope for a predicate.
|
|
160
|
+
*
|
|
161
|
+
* The server binds `{ record, previous }`, so a spec-authored predicate reads
|
|
162
|
+
* `record.amount`. objectui's own rules have always been written against the
|
|
163
|
+
* bare field name (`amount`). Both are bound — the roots last so a field
|
|
164
|
+
* literally called `record` cannot shadow them.
|
|
76
165
|
*/
|
|
77
|
-
private
|
|
166
|
+
private scopeFor;
|
|
167
|
+
/**
|
|
168
|
+
* Evaluate a `script` / `cross_field` predicate.
|
|
169
|
+
*
|
|
170
|
+
* Both variants share one path on the server, and so do they here. The
|
|
171
|
+
* predicate is the FAILURE condition: TRUE means the rule is violated. A
|
|
172
|
+
* predicate that cannot be evaluated is a BROKEN rule and fails open.
|
|
173
|
+
*/
|
|
174
|
+
private validatePredicate;
|
|
78
175
|
/**
|
|
79
176
|
* Validate uniqueness constraint
|
|
80
177
|
*/
|
|
81
178
|
private validateUniqueness;
|
|
82
179
|
/**
|
|
83
|
-
* Validate state machine transitions
|
|
180
|
+
* Validate state machine transitions (ADR-0020).
|
|
181
|
+
*
|
|
182
|
+
* A flat `field` plus a `{ from: [allowedTo] }` map. Semantics mirror the
|
|
183
|
+
* server-side rule-validator:
|
|
184
|
+
*
|
|
185
|
+
* INSERT
|
|
186
|
+
* - no `initialStates` declared → allow (legacy no-op)
|
|
187
|
+
* - field absent from the write → allow (requiredness is not our job)
|
|
188
|
+
* - value empty → allow (ditto)
|
|
189
|
+
* - value ∉ initialStates → reject (the FSM entry point, #3165)
|
|
190
|
+
*
|
|
191
|
+
* UPDATE
|
|
192
|
+
* - field absent from the write → allow (no transition to police)
|
|
193
|
+
* - no prior record → allow (cannot reason)
|
|
194
|
+
* - field unchanged, or cleared → allow (no transition)
|
|
195
|
+
* - `from` not declared in the map → lenient allow (unconstrained)
|
|
196
|
+
* - `to` ∉ transitions[from] → reject
|
|
84
197
|
*/
|
|
85
198
|
private validateStateMachine;
|
|
86
|
-
/**
|
|
87
|
-
* Validate cross-field constraints
|
|
88
|
-
*/
|
|
89
|
-
private validateCrossField;
|
|
90
199
|
/**
|
|
91
200
|
* Validate async/remote validation
|
|
92
201
|
*/
|
|
93
202
|
private validateAsync;
|
|
94
203
|
/**
|
|
95
|
-
* Validate conditional
|
|
204
|
+
* Validate a conditional rule.
|
|
205
|
+
*
|
|
206
|
+
* Evaluates `when`, then recurses into `then` (TRUE) or `otherwise` (FALSE).
|
|
207
|
+
* The nested rule supplies the violation; an un-evaluable `when` is a broken
|
|
208
|
+
* rule and fails open. A branch whose own `active` is explicitly `false` is
|
|
209
|
+
* skipped, matching the server.
|
|
96
210
|
*/
|
|
97
211
|
private validateConditional;
|
|
98
212
|
/**
|
|
99
|
-
* Validate format/
|
|
213
|
+
* Validate a field's format against `regex` and/or a named `format`.
|
|
214
|
+
*
|
|
215
|
+
* Mirrors the server: the rule only fires when the write TOUCHES the field and
|
|
216
|
+
* the value is non-empty (requiredness and type-shape belong to the
|
|
217
|
+
* field-level validator, so an absent or blank value is not a format
|
|
218
|
+
* violation). Both checks apply when both are declared. A `regex` that will
|
|
219
|
+
* not compile is a BROKEN rule — logged and skipped, never a violation.
|
|
100
220
|
*/
|
|
101
221
|
private validateFormat;
|
|
102
222
|
/**
|
|
103
223
|
* Validate range constraints
|
|
104
224
|
*/
|
|
105
225
|
private validateRange;
|
|
106
|
-
/**
|
|
107
|
-
* Get predefined regex pattern
|
|
108
|
-
*/
|
|
109
|
-
private getPredefinedPattern;
|
|
110
226
|
}
|
|
111
227
|
/**
|
|
112
228
|
* Default instance
|
|
229
|
+
*
|
|
230
|
+
* @deprecated (#3110) See `ObjectValidationEngine`.
|
|
113
231
|
*/
|
|
114
232
|
export declare const defaultObjectValidationEngine: ObjectValidationEngine;
|
|
115
233
|
/**
|
|
116
234
|
* Convenience function to validate a record
|
|
235
|
+
*
|
|
236
|
+
* @deprecated (#3110) See `ObjectValidationEngine`.
|
|
117
237
|
*/
|
|
118
|
-
export declare function validateRecord(rules: ObjectValidationRule[], context: ObjectValidationContext, event?:
|
|
238
|
+
export declare function validateRecord(rules: ObjectValidationRule[], context: ObjectValidationContext, event?: ObjectValidationEvent): Promise<ObjectValidationResult[]>;
|