@object-ui/core 17.6.0 → 17.7.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 +6610 -0
- package/README.md +101 -14
- package/dist/actions/ActionEngine.d.ts +4 -2
- package/dist/actions/ActionEngine.js +13 -8
- package/dist/actions/ActionRunner.d.ts +288 -27
- package/dist/actions/ActionRunner.js +443 -63
- package/dist/actions/TransactionManager.d.ts +7 -2
- package/dist/actions/actionKeys.d.ts +9 -7
- package/dist/actions/actionKeys.js +57 -14
- package/dist/actions/actionResponse.js +2 -2
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/actions/recordDelete.d.ts +118 -0
- package/dist/actions/recordDelete.js +112 -0
- package/dist/adapters/ValueDataSource.d.ts +6 -1
- package/dist/adapters/ValueDataSource.js +1090 -98
- package/dist/adapters/batchTransaction.d.ts +1 -1
- package/dist/adapters/batchTransaction.js +1 -1
- package/dist/builder/schema-builder.d.ts +38 -81
- package/dist/builder/schema-builder.js +33 -152
- package/dist/data-scope/ViewDataProvider.d.ts +1 -1
- package/dist/data-scope/ViewDataProvider.js +21 -1
- package/dist/data-scope/element-data-source.d.ts +261 -7
- package/dist/data-scope/element-data-source.js +342 -52
- package/dist/data-scope/index.d.ts +9 -4
- package/dist/data-scope/index.js +9 -4
- package/dist/evaluator/ExpressionEvaluator.d.ts +86 -0
- package/dist/evaluator/ExpressionEvaluator.js +184 -12
- package/dist/evaluator/FormulaFunctions.d.ts +0 -10
- package/dist/evaluator/FormulaFunctions.js +166 -27
- package/dist/evaluator/declaredPredicate.d.ts +93 -9
- package/dist/evaluator/declaredPredicate.js +117 -16
- package/dist/evaluator/fieldRules.d.ts +88 -4
- package/dist/evaluator/fieldRules.js +203 -31
- package/dist/evaluator/index.d.ts +1 -0
- package/dist/evaluator/index.js +1 -0
- package/dist/evaluator/listConditional.d.ts +103 -34
- package/dist/evaluator/listConditional.js +127 -50
- package/dist/evaluator/optionRules.d.ts +77 -6
- package/dist/evaluator/optionRules.js +87 -10
- package/dist/evaluator/predicateInput.d.ts +15 -4
- package/dist/evaluator/predicateInput.js +35 -2
- package/dist/evaluator/rowPredicateCanon.d.ts +7 -18
- package/dist/evaluator/rowPredicateCanon.js +65 -115
- package/dist/evaluator/subjectPermissions.d.ts +76 -0
- package/dist/evaluator/subjectPermissions.js +44 -0
- package/dist/evaluator/unevaluablePredicate.d.ts +57 -0
- package/dist/evaluator/unevaluablePredicate.js +70 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +80 -2
- package/dist/protocols/index.d.ts +0 -1
- package/dist/protocols/index.js +9 -1
- package/dist/registry/Registry.d.ts +358 -31
- package/dist/registry/Registry.js +263 -11
- package/dist/registry/WidgetRegistry.js +7 -3
- package/dist/registry/html-tier-intrinsics.d.ts +90 -0
- package/dist/registry/html-tier-intrinsics.js +110 -0
- package/dist/registry/public-blocks.d.ts +8 -0
- package/dist/registry/public-blocks.js +57 -0
- package/dist/theme/ThemeEngine.js +1 -1
- package/dist/utils/chart-category-key.d.ts +82 -0
- package/dist/utils/chart-category-key.js +84 -0
- package/dist/utils/chart-measure-key.d.ts +64 -0
- package/dist/utils/chart-measure-key.js +65 -0
- package/dist/utils/chart-presentation.d.ts +95 -112
- package/dist/utils/chart-presentation.js +169 -104
- package/dist/utils/chart-series.d.ts +131 -5
- package/dist/utils/chart-series.js +98 -16
- package/dist/utils/column-sortability.d.ts +157 -0
- package/dist/utils/column-sortability.js +217 -0
- package/dist/utils/dashboard-filters.d.ts +38 -6
- package/dist/utils/dashboard-filters.js +107 -61
- package/dist/utils/dataset-format.d.ts +211 -30
- package/dist/utils/dataset-format.js +389 -46
- package/dist/utils/date-display.d.ts +354 -0
- package/dist/utils/date-display.js +463 -0
- package/dist/utils/date-macros.js +7 -0
- package/dist/utils/drill-down.d.ts +78 -0
- package/dist/utils/drill-down.js +93 -0
- package/dist/utils/emptiness.d.ts +96 -0
- package/dist/utils/emptiness.js +101 -0
- package/dist/utils/expand-fields.d.ts +76 -6
- package/dist/utils/expand-fields.js +76 -6
- package/dist/utils/extract-records.d.ts +65 -5
- package/dist/utils/extract-records.js +65 -8
- package/dist/utils/filter-converter.d.ts +152 -4
- package/dist/utils/filter-converter.js +1092 -22
- package/dist/utils/filter-tokens.d.ts +49 -5
- package/dist/utils/filter-tokens.js +105 -33
- package/dist/utils/grouping-fields.d.ts +61 -0
- package/dist/utils/grouping-fields.js +84 -0
- package/dist/utils/managedBy.d.ts +3 -3
- package/dist/utils/managedBy.js +5 -5
- package/dist/utils/native-date-value.d.ts +48 -0
- package/dist/utils/native-date-value.js +167 -0
- package/dist/utils/non-grid-row-ceiling.d.ts +143 -0
- package/dist/utils/non-grid-row-ceiling.js +141 -0
- package/dist/utils/normalize-list-view.d.ts +121 -1
- package/dist/utils/normalize-list-view.js +186 -6
- package/dist/utils/number-display.d.ts +63 -14
- package/dist/utils/number-display.js +34 -12
- package/dist/utils/object-aggregate-query.d.ts +113 -0
- package/dist/utils/object-aggregate-query.js +50 -0
- package/dist/utils/parent-scope.d.ts +123 -0
- package/dist/utils/parent-scope.js +140 -0
- package/dist/utils/predicate-fields.d.ts +45 -12
- package/dist/utils/predicate-fields.js +137 -12
- package/dist/utils/record-color.d.ts +75 -0
- package/dist/utils/record-color.js +65 -0
- package/dist/utils/record-source.d.ts +298 -0
- package/dist/utils/record-source.js +331 -0
- package/dist/utils/record-title.d.ts +148 -8
- package/dist/utils/record-title.js +220 -26
- package/dist/utils/reference-keys.d.ts +21 -22
- package/dist/utils/reference-keys.js +532 -29
- package/dist/utils/sort-query.d.ts +115 -15
- package/dist/utils/sort-query.js +240 -13
- package/dist/utils/text-comparand.d.ts +92 -0
- package/dist/utils/text-comparand.js +99 -0
- package/dist/utils/without-denied-fields.d.ts +49 -0
- package/dist/utils/without-denied-fields.js +52 -0
- package/dist/validation/index.d.ts +8 -4
- package/dist/validation/index.js +8 -4
- package/dist/validation/schema-validator.d.ts +1 -1
- package/dist/validation/schema-validator.js +200 -82
- package/dist/validation/validators/object-validation-engine.d.ts +1 -1
- package/dist/validation/validators/object-validation-engine.js +14 -3
- package/package.json +8 -9
- package/dist/data-scope/DataScopeManager.d.ts +0 -127
- package/dist/data-scope/DataScopeManager.js +0 -229
- package/dist/protocols/ResponsiveProtocol.d.ts +0 -73
- package/dist/protocols/ResponsiveProtocol.js +0 -158
- package/dist/validation/validation-engine.d.ts +0 -88
- package/dist/validation/validation-engine.js +0 -434
|
@@ -23,6 +23,34 @@ export type FilterNode = [string, string, any] | [string, ...FilterNode[]];
|
|
|
23
23
|
* @param operator - MongoDB-style operator (e.g., '$gte', '$in')
|
|
24
24
|
* @returns ObjectStack operator or null if not recognized
|
|
25
25
|
*/
|
|
26
|
+
/**
|
|
27
|
+
* What the refusal is ABOUT, as structured data rather than as prose to scrape.
|
|
28
|
+
*
|
|
29
|
+
* `message` already names both, but a renderer that wants to say "the
|
|
30
|
+
* $icontains condition cannot be applied" must not recover the token with a
|
|
31
|
+
* regular expression over an English paragraph that every one of these
|
|
32
|
+
* refusals deliberately writes differently. objectui#9050's step 2 requires the
|
|
33
|
+
* render-time diagnostic to NAME the operator, so the name travels as a field.
|
|
34
|
+
*
|
|
35
|
+
* `operator` is the spelling the AUTHOR wrote — `$startswith` for a retired
|
|
36
|
+
* alias, `icontains` for a view rule — never a canonical form substituted for
|
|
37
|
+
* it, for the reason the view-rule arm's own tail already gives: prescribing a
|
|
38
|
+
* spelling the author's vocabulary does not have sends them looking for a key
|
|
39
|
+
* their metadata cannot contain.
|
|
40
|
+
*
|
|
41
|
+
* It is OPTIONAL because some refusals are not about an operator at all: the
|
|
42
|
+
* bare-array and exotic-comparand arms judge a COMPARAND written in the
|
|
43
|
+
* implicit-equality position, and the empty-operator-map arm judges a field
|
|
44
|
+
* that names NO operator (`{ a: {} }`, objectui#9164). In each, no operator was
|
|
45
|
+
* spelled and `field` is the only handle the author can act on. A renderer
|
|
46
|
+
* reads {@link filterRefusalSubject} rather than choosing between them itself.
|
|
47
|
+
*/
|
|
48
|
+
export interface FilterRefusalSubject {
|
|
49
|
+
/** The operator spelling the author wrote, when the refusal is about one. */
|
|
50
|
+
operator?: string;
|
|
51
|
+
/** The field the refused condition is on, when the refusal is about one. */
|
|
52
|
+
field?: string;
|
|
53
|
+
}
|
|
26
54
|
/**
|
|
27
55
|
* A filter operator this layer will not translate.
|
|
28
56
|
*
|
|
@@ -34,8 +62,22 @@ export type FilterNode = [string, string, any] | [string, ...FilterNode[]];
|
|
|
34
62
|
export declare class FilterOperatorError extends Error {
|
|
35
63
|
readonly code = "INVALID_FILTER";
|
|
36
64
|
readonly httpStatus = 400;
|
|
37
|
-
|
|
65
|
+
/** @see FilterRefusalSubject */
|
|
66
|
+
readonly operator: string | undefined;
|
|
67
|
+
/** @see FilterRefusalSubject */
|
|
68
|
+
readonly field: string | undefined;
|
|
69
|
+
constructor(message: string, subject?: FilterRefusalSubject);
|
|
38
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* The one token a "this view's filter is malformed" state names.
|
|
73
|
+
*
|
|
74
|
+
* Operator first, because that is what the ruling asks the state to name and
|
|
75
|
+
* what an author can act on — `$regex` is not supported, `$startswith` is
|
|
76
|
+
* retired. Field second, for the refusals that have no operator to name — the
|
|
77
|
+
* two comparand arms and the empty operator map. `undefined` for neither, which no arm produces today and which a
|
|
78
|
+
* renderer must still handle rather than print "undefined" at a user.
|
|
79
|
+
*/
|
|
80
|
+
export declare function filterRefusalSubject(error: FilterOperatorError): string | undefined;
|
|
39
81
|
export declare function convertOperatorToAST(operator: string): string | null;
|
|
40
82
|
/**
|
|
41
83
|
* Convert object-based filters to ObjectStack FilterNode AST format.
|
|
@@ -59,9 +101,67 @@ export declare function convertOperatorToAST(operator: string): string | null;
|
|
|
59
101
|
* convertFiltersToAST({ age: { $gte: 18, $lte: 65 }, status: 'active' })
|
|
60
102
|
* // => ['and', ['age', '>=', 18], ['age', '<=', 65], ['status', '=', 'active']]
|
|
61
103
|
*
|
|
62
|
-
* @
|
|
104
|
+
* @example
|
|
105
|
+
* // Logical combinators (objectui#6948) — children lower recursively
|
|
106
|
+
* convertFiltersToAST({ $or: [{ status: 'open' }, { status: 'blocked' }] })
|
|
107
|
+
* // => ['or', ['status', '=', 'open'], ['status', '=', 'blocked']]
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* // A Date is a comparand, not an operator map (objectui#8555). It lowers as
|
|
111
|
+
* // the Date INSTANCE — the spec accepts one, and the operator form already
|
|
112
|
+
* // emits one.
|
|
113
|
+
* convertFiltersToAST({ created: new Date('2026-01-01') })
|
|
114
|
+
* // => ['created', '=', Date(2026-01-01)]
|
|
115
|
+
*
|
|
116
|
+
* @throws {FilterOperatorError} If an unknown operator is encountered, if
|
|
117
|
+
* `$not` is used — see the `$not` arm for why the AST cannot carry it — if a
|
|
118
|
+
* field's value is a bare ARRAY (`{ tags: ['a', 'b'] }`) — see the array arm for
|
|
119
|
+
* why that is refused rather than read as `$in` — or if a field's value is an
|
|
120
|
+
* EXOTIC object the spec does not accept as a comparand (`{ name: /abc/ }`,
|
|
121
|
+
* a `Set`, a `Map`): see the exotic-comparand arm for why that is refused
|
|
122
|
+
* rather than dropped (objectui#8567), or if an `$icontains` comparand is not a
|
|
123
|
+
* NON-EMPTY STRING (`{ name: { $icontains: '' } }`, `{ name: { $icontains: 42 } }`)
|
|
124
|
+
* — two shapes `@objectstack/spec`'s `FILTER_TEXT_CASES` declares REFUSED and
|
|
125
|
+
* `ValueDataSource` has refused since objectui#8748; see
|
|
126
|
+
* {@link refuseTextComparand} (objectui#9001), or if a field is an EMPTY
|
|
127
|
+
* operator map (`{ a: {} }`) — alone (objectui#9164) or
|
|
128
|
+
* beside a key that lowers (objectui#10788): see {@link refuseEmptyOperatorMap},
|
|
129
|
+
* or if a `$empty` flag is not a boolean (`{ a: { $empty: 'yes' } }`,
|
|
130
|
+
* objectui#11094).
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* // A field with NO operator (objectui#9164)
|
|
134
|
+
* convertFiltersToAST({ a: {} })
|
|
135
|
+
* // => throws FilterOperatorError (INVALID_FILTER / 400), field 'a'
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* // … and beside a key that lowers, where it used to vanish and widen the
|
|
139
|
+
* // result to `['status', '=', 'a']` (objectui#10788)
|
|
140
|
+
* convertFiltersToAST({ status: 'a', created: {} })
|
|
141
|
+
* // => throws FilterOperatorError (INVALID_FILTER / 400), field 'created'
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* // A filter that is NOTHING BUT combinators reducing to the TRUE identity
|
|
145
|
+
* // constrains nothing, and says so (objectui#8770). Callers skip the slot.
|
|
146
|
+
* convertFiltersToAST({ $and: [] })
|
|
147
|
+
* // => undefined
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* // A filter whose EVERY key is skipped for a null/undefined value also
|
|
151
|
+
* // constrains nothing — the same answer this function already gives that key
|
|
152
|
+
* // when a sibling survives (objectui#9020). Callers skip the slot.
|
|
153
|
+
* convertFiltersToAST({ a: null })
|
|
154
|
+
* // => undefined
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* // … and a filter that MIXES the two constrains nothing either, because the
|
|
158
|
+
* // identity fold counts only the keys the loop actually PROCESSED
|
|
159
|
+
* // (objectui#9030). A skipped key used to be counted against that fold, so a
|
|
160
|
+
* // filter whose every key folds alone did not fold together.
|
|
161
|
+
* convertFiltersToAST({ $and: [], b: undefined })
|
|
162
|
+
* // => undefined
|
|
63
163
|
*/
|
|
64
|
-
export declare function convertFiltersToAST(filter: Record<string, any>): FilterNode | Record<string, any
|
|
164
|
+
export declare function convertFiltersToAST(filter: Record<string, any>): FilterNode | Record<string, any> | undefined;
|
|
65
165
|
/**
|
|
66
166
|
* Normalize ONE filter source into a single filter node.
|
|
67
167
|
*
|
|
@@ -108,9 +208,57 @@ export declare function convertFiltersToAST(filter: Record<string, any>): Filter
|
|
|
108
208
|
* untouched.
|
|
109
209
|
*
|
|
110
210
|
* Returns `undefined` for an absent or empty source, so callers can skip
|
|
111
|
-
* `$filter` rather than sending an empty array
|
|
211
|
+
* `$filter` rather than sending an empty array — and, since objectui#8770, for
|
|
212
|
+
* an object source that is nothing but TRUE-identity combinators
|
|
213
|
+
* (`{ $and: [] }`), and since objectui#9020 for one whose every key is skipped
|
|
214
|
+
* for a null/undefined value (`{ a: null }`). Both constrain nothing and so
|
|
215
|
+
* contribute nothing to the `and` {@link mergeFilterNodes} builds. Those answers
|
|
216
|
+
* are inherited from {@link convertFiltersToAST}, not decided a second time
|
|
217
|
+
* here — including the fact that they are two separate decisions there.
|
|
112
218
|
*/
|
|
113
219
|
export declare function toFilterNode(source: unknown): FilterNode | Record<string, any> | undefined;
|
|
220
|
+
/**
|
|
221
|
+
* {@link toFilterNode}'s answer for a caller that has no `catch` above it.
|
|
222
|
+
*
|
|
223
|
+
* ## Why this exists (objectui#9050, ruling C′ step 2)
|
|
224
|
+
*
|
|
225
|
+
* `toFilterNode` is documented as "the last stop before the wire", and the two
|
|
226
|
+
* callers that reach the wire — `plugin-list`'s `buildEffectiveFilter` and
|
|
227
|
+
* `plugin-view`'s `ObjectView` — do have a `catch`: they call it inside a load
|
|
228
|
+
* `try`, `classifyLoadError` reads this file's `INVALID_FILTER` / 400 envelope,
|
|
229
|
+
* and the author sees "this filter is malformed". Three OTHER callers reach it
|
|
230
|
+
* from a RENDER-time `useMemo` (`plugin-detail`'s `RelatedList`,
|
|
231
|
+
* `plugin-form`'s `LineItemsPanel`, `plugin-grid`'s `ObjectGrid`), where a
|
|
232
|
+
* throw is a render error and there is no `classifyLoadError` in the path.
|
|
233
|
+
* A fourth is an ADAPTER rather than a renderer: `ValueDataSource.find` lowers
|
|
234
|
+
* an array `$filter` through this before matching it in memory
|
|
235
|
+
* (objectui#10767), and a `find` that never threw on a bad filter must not
|
|
236
|
+
* start to — it re-seats `refusal` as its own excluded-and-logged refusal.
|
|
237
|
+
*
|
|
238
|
+
* ## Why the return type is a UNION and not `node | undefined`
|
|
239
|
+
*
|
|
240
|
+
* Because `undefined` is the refused answer. A `try`/`catch` that swallows the
|
|
241
|
+
* refusal and hands back `undefined` means NO FILTER — every row — which is a
|
|
242
|
+
* silently unconstrained query on a view whose whole purpose can be to hide
|
|
243
|
+
* rows, and is the failure objectui#9001 closed. So the refusal is not
|
|
244
|
+
* representable as a node: `ok: false` carries the error and has no `node` to
|
|
245
|
+
* read at all, and TypeScript makes a caller narrow before it can build a
|
|
246
|
+
* query. That is the whole difference between this and a bare `catch`.
|
|
247
|
+
*
|
|
248
|
+
* ⚠️ Only a {@link FilterOperatorError} is caught. Anything else is a defect in
|
|
249
|
+
* this file rather than a statement about the author's filter, and is rethrown
|
|
250
|
+
* so it keeps reaching whatever boundary would have seen it — a render-time
|
|
251
|
+
* `TypeError` swallowed into "your filter is malformed" would send the author
|
|
252
|
+
* to edit a filter that is fine.
|
|
253
|
+
*/
|
|
254
|
+
export type FilterNodeResult = {
|
|
255
|
+
ok: true;
|
|
256
|
+
node: FilterNode | Record<string, any> | undefined;
|
|
257
|
+
} | {
|
|
258
|
+
ok: false;
|
|
259
|
+
refusal: FilterOperatorError;
|
|
260
|
+
};
|
|
261
|
+
export declare function toFilterNodeSafely(source: unknown): FilterNodeResult;
|
|
114
262
|
/**
|
|
115
263
|
* Combine filter sources under a single `and`, each as its OWN child.
|
|
116
264
|
*
|