@object-ui/core 17.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 +526 -0
- package/dist/actions/ActionEngine.d.ts +11 -1
- package/dist/actions/ActionEngine.js +14 -3
- package/dist/actions/ActionRunner.d.ts +117 -10
- package/dist/actions/ActionRunner.js +25 -3
- package/dist/actions/actionKeys.d.ts +28 -11
- package/dist/actions/actionKeys.js +50 -10
- 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/WidgetRegistry.d.ts +7 -7
- package/dist/registry/WidgetRegistry.js +1 -1
- package/dist/styling/scoped-styles.d.ts +14 -8
- package/dist/utils/chart-series.d.ts +14 -2
- package/dist/utils/dashboard-filters.d.ts +9 -0
- 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/filter-tokens.d.ts +13 -6
- package/dist/utils/filter-tokens.js +13 -6
- package/dist/utils/freeze-schema.d.ts +14 -6
- package/dist/utils/freeze-schema.js +14 -6
- package/dist/utils/managedBy.d.ts +78 -50
- package/dist/utils/managedBy.js +75 -52
- package/dist/utils/normalize-list-view.d.ts +12 -2
- package/dist/validation/index.d.ts +1 -0
- package/dist/validation/index.js +1 -0
- 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/package.json +4 -4
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
|
+
import type { ActionInput as SpecActionInput } from '@objectstack/spec/ui';
|
|
8
9
|
import { ExpressionEvaluator } from '../evaluator/ExpressionEvaluator';
|
|
9
10
|
import { type UndoableOperation } from './UndoManager';
|
|
10
11
|
export interface ActionResult {
|
|
@@ -65,7 +66,12 @@ export interface ActionDef {
|
|
|
65
66
|
/** Action type identifier — a `RunnableActionType` (the spec's six plus the
|
|
66
67
|
* `navigation` alias of `url`) or a custom type with a registered handler. */
|
|
67
68
|
type?: string;
|
|
68
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* Legacy action type field.
|
|
71
|
+
*
|
|
72
|
+
* @deprecated objectui dialect — use the spec spelling `type`. Both are read,
|
|
73
|
+
* `type` first (objectstack#4075 step 2).
|
|
74
|
+
*/
|
|
69
75
|
actionType?: string;
|
|
70
76
|
/** Action name (from UIActionSchema) */
|
|
71
77
|
name?: string;
|
|
@@ -84,13 +90,36 @@ export interface ActionDef {
|
|
|
84
90
|
condition?: string;
|
|
85
91
|
/** Disabled expression — if truthy, skip action */
|
|
86
92
|
disabled?: string | boolean;
|
|
87
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* API endpoint (string URL or complex config).
|
|
95
|
+
*
|
|
96
|
+
* @deprecated objectui dialect — the spec spells an `api` action's endpoint
|
|
97
|
+
* `target` (with the verb in `method`). `executeAPI` resolves
|
|
98
|
+
* `api || endpoint || target`, so `target` alone is sufficient. The
|
|
99
|
+
* `ApiConfig` object form has no spec counterpart and is objectui-only
|
|
100
|
+
* (objectstack#4075 step 2).
|
|
101
|
+
*/
|
|
88
102
|
api?: string | ApiConfig;
|
|
89
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* API endpoint URL.
|
|
105
|
+
*
|
|
106
|
+
* @deprecated objectui dialect — this was the "spec v2.0.1 alias", but spec 17
|
|
107
|
+
* spells it `target`. `executeAPI` resolves `api || endpoint || target`
|
|
108
|
+
* (objectstack#4075 step 2).
|
|
109
|
+
*/
|
|
90
110
|
endpoint?: string;
|
|
91
111
|
/** HTTP method */
|
|
92
112
|
method?: string;
|
|
93
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* Navigation target — a nested envelope carrying the `navigation` alias's own
|
|
115
|
+
* spelling (`to` / `external` / `newTab` / `replace`).
|
|
116
|
+
*
|
|
117
|
+
* @deprecated objectui dialect — the spec has no nested navigation envelope;
|
|
118
|
+
* it spells a navigation action `{ type: 'url', target, openIn }`.
|
|
119
|
+
* `executeNavigation` reads `navigate.to || navigate.target || navigate.redirect`,
|
|
120
|
+
* falling back to the same keys on the action itself, so a flat `target` works
|
|
121
|
+
* today (objectstack#4075 step 2).
|
|
122
|
+
*/
|
|
94
123
|
navigate?: any;
|
|
95
124
|
/** onClick callback (legacy) */
|
|
96
125
|
onClick?: () => void | Promise<void>;
|
|
@@ -177,10 +206,82 @@ export interface ActionDef {
|
|
|
177
206
|
* must perform all auth/authz itself (e.g. the cloud `/sso-open` endpoint,
|
|
178
207
|
* which re-runs every check the POST half would have done). */
|
|
179
208
|
newTabUrl?: string;
|
|
209
|
+
/** Where this action renders (`record_header`, `list_toolbar`, …). Read by
|
|
210
|
+
* `ActionEngine.registerActions` to seed the location filter. */
|
|
211
|
+
locations?: SpecActionInput['locations'];
|
|
212
|
+
/**
|
|
213
|
+
* Visibility predicate, evaluated against the runner's context.
|
|
214
|
+
*
|
|
215
|
+
* The `boolean` arm is objectui's own, deliberately wider than the spec:
|
|
216
|
+
* `ActionSchema.visible` admits only a CEL string or a `{ dialect, source }`
|
|
217
|
+
* envelope, while `ActionEngine.getActionsForLocation` also honours a literal
|
|
218
|
+
* `visible: true` / `false` (pinned by `ActionEngine.visibility.test.ts`).
|
|
219
|
+
* Declared rather than left to the index signature so the tolerance is
|
|
220
|
+
* auditable instead of invisible — but it IS a dialect, and objectstack#4075
|
|
221
|
+
* step 3 has to decide whether the spec adopts the boolean or objectui drops
|
|
222
|
+
* it. Do not widen this further.
|
|
223
|
+
*/
|
|
224
|
+
visible?: SpecActionInput['visible'] | boolean;
|
|
225
|
+
/** System permissions the caller must ALL hold for the action to be offered
|
|
226
|
+
* (ADR-0066 D4 UI half — the server enforces the source of truth). */
|
|
227
|
+
requiredPermissions?: SpecActionInput['requiredPermissions'];
|
|
228
|
+
/** Icon name for the rendered control. */
|
|
229
|
+
icon?: SpecActionInput['icon'];
|
|
230
|
+
/** Visual emphasis of the rendered control (`primary`, `danger`, …). */
|
|
231
|
+
variant?: SpecActionInput['variant'];
|
|
232
|
+
/** Sort weight among sibling actions. */
|
|
233
|
+
order?: SpecActionInput['order'];
|
|
234
|
+
/** Which renderer surfaces the action (`action:button`, `action:menu`, …). */
|
|
235
|
+
component?: SpecActionInput['component'];
|
|
236
|
+
/** Object this action is declared against. */
|
|
237
|
+
objectName?: SpecActionInput['objectName'];
|
|
238
|
+
/** AI affordance metadata (tool exposure, prompts). */
|
|
239
|
+
ai?: SpecActionInput['ai'];
|
|
240
|
+
/** Accessibility overrides for the rendered control. */
|
|
241
|
+
aria?: SpecActionInput['aria'];
|
|
242
|
+
/** Extra properties merged into the request body alongside the collected params. */
|
|
243
|
+
bodyExtra?: SpecActionInput['bodyExtra'];
|
|
244
|
+
/** How collected params are shaped into the request body (`flat` or nested). */
|
|
245
|
+
bodyShape?: SpecActionInput['bodyShape'];
|
|
246
|
+
/** Execution mode of the action. */
|
|
247
|
+
mode?: SpecActionInput['mode'];
|
|
248
|
+
/** Field on the record supplying the record id sent to the endpoint. */
|
|
249
|
+
recordIdField?: SpecActionInput['recordIdField'];
|
|
250
|
+
/** Request-parameter name carrying the record id. */
|
|
251
|
+
recordIdParam?: SpecActionInput['recordIdParam'];
|
|
252
|
+
/** Auth/tenancy feature the action requires before it is offered. */
|
|
253
|
+
requiresFeature?: SpecActionInput['requiresFeature'];
|
|
254
|
+
/**
|
|
255
|
+
* @deprecated Retired in `@objectstack/spec` 17 as a `retiredKey()` tombstone —
|
|
256
|
+
* authoring it is a hard parse rejection, so this resolves to `undefined` and
|
|
257
|
+
* assigning a value is a compile error. A HOST may still pass a shortcut
|
|
258
|
+
* explicitly via `ActionEngine.registerAction(action, { shortcut })`; it is
|
|
259
|
+
* only no longer sourced from authored metadata. No replacement key.
|
|
260
|
+
*/
|
|
261
|
+
shortcut?: SpecActionInput['shortcut'];
|
|
262
|
+
/**
|
|
263
|
+
* @deprecated Retired in `@objectstack/spec` 17 as a `retiredKey()` tombstone —
|
|
264
|
+
* authoring it is a hard parse rejection, so this resolves to `undefined` and
|
|
265
|
+
* assigning a value is a compile error. Use the list view's `bulkActions` /
|
|
266
|
+
* `bulkActionDefs` instead; `ActionEngine.registerAction(action, { bulkEnabled })`
|
|
267
|
+
* remains available to a HOST passing it explicitly.
|
|
268
|
+
*/
|
|
269
|
+
bulkEnabled?: SpecActionInput['bulkEnabled'];
|
|
180
270
|
/** Any additional properties */
|
|
181
271
|
[key: string]: any;
|
|
182
272
|
}
|
|
183
|
-
|
|
273
|
+
/**
|
|
274
|
+
* A handler registered with {@link ActionRunner} — the client-side action
|
|
275
|
+
* dispatch seam: given an authored `ActionDef` and the invocation context,
|
|
276
|
+
* produce an `ActionResult`.
|
|
277
|
+
*
|
|
278
|
+
* NOT the spec's `ActionHandler` (`@objectstack/spec/ui`), whose name this type
|
|
279
|
+
* carried until objectstack#4115. That one is the SERVER-side objectql action
|
|
280
|
+
* handler — a different calling convention entirely (`(ctx) => unknown`, with
|
|
281
|
+
* validated params and a trusted engine facade on `ctx`) and a different
|
|
282
|
+
* execution site.
|
|
283
|
+
*/
|
|
284
|
+
export type ActionRunnerHandler = (action: ActionDef, context: ActionContext) => Promise<ActionResult> | ActionResult;
|
|
184
285
|
/**
|
|
185
286
|
* Confirmation handler — replaces window.confirm.
|
|
186
287
|
* Consumers can provide an async implementation (e.g., Shadcn AlertDialog).
|
|
@@ -353,7 +454,7 @@ export declare class ActionRunner {
|
|
|
353
454
|
* values the user must copy now (2FA codes, OAuth client_secret).
|
|
354
455
|
*/
|
|
355
456
|
setResultDialogHandler(handler: ResultDialogHandler): void;
|
|
356
|
-
registerHandler(actionName: string, handler:
|
|
457
|
+
registerHandler(actionName: string, handler: ActionRunnerHandler): void;
|
|
357
458
|
unregisterHandler(actionName: string): void;
|
|
358
459
|
/**
|
|
359
460
|
* Register a named script handler. When a `script` action's
|
|
@@ -361,7 +462,7 @@ export declare class ActionRunner {
|
|
|
361
462
|
* instead of the expression evaluator. Lets dashboards/views wire
|
|
362
463
|
* symbolic action names (e.g. 'export_dashboard_pdf') to JS callbacks.
|
|
363
464
|
*/
|
|
364
|
-
registerScript(scriptName: string, handler:
|
|
465
|
+
registerScript(scriptName: string, handler: ActionRunnerHandler): void;
|
|
365
466
|
unregisterScript(scriptName: string): void;
|
|
366
467
|
execute(action: ActionDef): Promise<ActionResult>;
|
|
367
468
|
/**
|
|
@@ -467,9 +568,15 @@ export declare class ActionRunner {
|
|
|
467
568
|
* fragment.
|
|
468
569
|
*
|
|
469
570
|
* `ctx.origin`, `ctx.user.*`, `ctx.org.*`, `ctx.recordId` are surfaced
|
|
470
|
-
* implicitly from the runner's ActionContext + window
|
|
471
|
-
*
|
|
472
|
-
*
|
|
571
|
+
* implicitly from the runner's ActionContext + window, and
|
|
572
|
+
* `ctx.selection.ids` / `ctx.selection.count` reflect the grid's current
|
|
573
|
+
* checkbox selection (`context.selectedRecords`) — `${ctx.selection.ids}`
|
|
574
|
+
* comma-joins the ids via the standard `String(array)` behaviour, so a
|
|
575
|
+
* list_toolbar url/api action can carry the selection without any bulk
|
|
576
|
+
* plumbing (objectui#3139). In an aggregate bulk dispatch,
|
|
577
|
+
* `${param._selectedIds}` interpolates the same ids from the injected
|
|
578
|
+
* param. Consumers can extend by stuffing extra keys under
|
|
579
|
+
* `context.ctx = {...}` before calling `runner.execute()`.
|
|
473
580
|
*/
|
|
474
581
|
private interpolateTarget;
|
|
475
582
|
/**
|
|
@@ -802,9 +802,15 @@ export class ActionRunner {
|
|
|
802
802
|
* fragment.
|
|
803
803
|
*
|
|
804
804
|
* `ctx.origin`, `ctx.user.*`, `ctx.org.*`, `ctx.recordId` are surfaced
|
|
805
|
-
* implicitly from the runner's ActionContext + window
|
|
806
|
-
*
|
|
807
|
-
*
|
|
805
|
+
* implicitly from the runner's ActionContext + window, and
|
|
806
|
+
* `ctx.selection.ids` / `ctx.selection.count` reflect the grid's current
|
|
807
|
+
* checkbox selection (`context.selectedRecords`) — `${ctx.selection.ids}`
|
|
808
|
+
* comma-joins the ids via the standard `String(array)` behaviour, so a
|
|
809
|
+
* list_toolbar url/api action can carry the selection without any bulk
|
|
810
|
+
* plumbing (objectui#3139). In an aggregate bulk dispatch,
|
|
811
|
+
* `${param._selectedIds}` interpolates the same ids from the injected
|
|
812
|
+
* param. Consumers can extend by stuffing extra keys under
|
|
813
|
+
* `context.ctx = {...}` before calling `runner.execute()`.
|
|
808
814
|
*/
|
|
809
815
|
interpolateTarget(target, action) {
|
|
810
816
|
if (typeof target !== 'string' || target.indexOf('${') === -1)
|
|
@@ -839,6 +845,22 @@ export class ActionRunner {
|
|
|
839
845
|
user: this.context.user ?? {},
|
|
840
846
|
org: this.context.org ?? this.context.organization ?? {},
|
|
841
847
|
recordId: this.context.record?.id ?? this.context.recordId,
|
|
848
|
+
// Current list selection (published by the grid as `selectedRecords`).
|
|
849
|
+
// `${ctx.selection.ids}` in a url/api target comma-joins the ids —
|
|
850
|
+
// String(array) — giving toolbar actions selection access without any
|
|
851
|
+
// bulk-executor involvement (objectui#3139). Empty when nothing is
|
|
852
|
+
// selected, so authors can treat "" as "no selection".
|
|
853
|
+
selection: {
|
|
854
|
+
ids: Array.isArray(this.context.selectedRecords)
|
|
855
|
+
? this.context.selectedRecords
|
|
856
|
+
.map((r) => r?.id)
|
|
857
|
+
.filter((v) => v != null)
|
|
858
|
+
.map(String)
|
|
859
|
+
: [],
|
|
860
|
+
count: Array.isArray(this.context.selectedRecords)
|
|
861
|
+
? this.context.selectedRecords.length
|
|
862
|
+
: 0,
|
|
863
|
+
},
|
|
842
864
|
};
|
|
843
865
|
if (this.context.ctx && typeof this.context.ctx === 'object') {
|
|
844
866
|
Object.assign(ctx, this.context.ctx);
|
|
@@ -32,25 +32,42 @@
|
|
|
32
32
|
* interface it mirrors would be the same "declared ≠ enforced" trap this whole
|
|
33
33
|
* thread is about.
|
|
34
34
|
*
|
|
35
|
-
* ── What the inventory found,
|
|
36
|
-
* `ActionDef`
|
|
37
|
-
*
|
|
35
|
+
* ── What the inventory found, and what step 2 did with it ────────────────────
|
|
36
|
+
* Step 1 found `ActionDef` declaring 34 keys against the spec `ActionSchema`'s
|
|
37
|
+
* 36, overlapping on 17. The two halves of the difference were different
|
|
38
|
+
* problems, and step 2 (objectstack#4075) treated them differently:
|
|
38
39
|
*
|
|
39
40
|
* 18 keys the SPEC owns that `ActionDef` never declared — `ai`, `aria`,
|
|
40
41
|
* `bodyExtra`, `bodyShape`, `bulkEnabled`, `component`, `icon`, `locations`,
|
|
41
42
|
* `mode`, `objectName`, `order`, `recordIdField`, `recordIdParam`,
|
|
42
43
|
* `requiredPermissions`, `requiresFeature`, `shortcut`, `variant`, `visible`.
|
|
43
|
-
* These are authored today and reach readers through the index
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
44
|
+
* These are authored today and used to reach readers through the index
|
|
45
|
+
* signature. **Step 2 promoted all 18 to explicit optional fields**, typed by
|
|
46
|
+
* DERIVATION from `@objectstack/spec`'s `ActionInput` rather than by hand-copied
|
|
47
|
+
* shapes. The `as any` casts `ActionEngine` needed to read `visible`,
|
|
48
|
+
* `locations` and `requiredPermissions` are gone with them — those casts existed
|
|
49
|
+
* only because the fields were undeclared.
|
|
50
|
+
*
|
|
51
|
+
* Two of the 18 landed as `undefined` rather than as usable types, which is the
|
|
52
|
+
* correct outcome: spec 17 retired `shortcut` and `bulkEnabled` as `retiredKey()`
|
|
53
|
+
* tombstones (`z.never()`), so deriving turns "authoring this is a parse
|
|
54
|
+
* rejection" into a compile error at no cost. Hand-copying would have quietly
|
|
55
|
+
* re-legitimized two dead keys — which is why the types are derived.
|
|
47
56
|
*
|
|
48
57
|
* 17 keys `ActionDef` declares that the spec does not own — `actionType`, `api`,
|
|
49
58
|
* `chain`, `chainMode`, `close`, `condition`, `confirm`, `endpoint`, `modal`,
|
|
50
59
|
* `navigate`, `onClick`, `onFailure`, `onSuccess`, `redirect`, `reload`, `toast`,
|
|
51
|
-
* `actionParams`.
|
|
52
|
-
*
|
|
53
|
-
*
|
|
60
|
+
* `actionParams`. Step 2 marked `@deprecated`, with the spec spelling to use
|
|
61
|
+
* instead, ONLY the four the runner itself proves are aliases: `actionType` (→
|
|
62
|
+
* `type`), `api` and `endpoint` (→ `target`; `executeAPI` resolves
|
|
63
|
+
* `api || endpoint || target`), and `navigate` (→ flat `target`/`openIn`;
|
|
64
|
+
* `executeNavigation` already falls back to them). The rest are runner mechanics
|
|
65
|
+
* with no spec counterpart — chaining, toasts, post-execution reload/close — and
|
|
66
|
+
* deprecating them toward a spelling that does not exist would be worse than
|
|
67
|
+
* leaving them declared.
|
|
68
|
+
*
|
|
69
|
+
* Step 3 remains: remove the index signature, at which point `tsc` catches both
|
|
70
|
+
* typos and retired keys and the dev-mode warning below can retire with it.
|
|
54
71
|
*/
|
|
55
72
|
/**
|
|
56
73
|
* Every property `ActionDef` declares, in declaration order.
|
|
@@ -59,7 +76,7 @@
|
|
|
59
76
|
* `keyof ActionDef` cannot substitute for this list: the index signature widens
|
|
60
77
|
* it to `string | number`, which is precisely the problem being worked around.
|
|
61
78
|
*/
|
|
62
|
-
export declare const ACTION_DEF_KEYS: readonly ["type", "actionType", "name", "label", "confirmText", "confirm", "condition", "disabled", "api", "endpoint", "method", "navigate", "onClick", "reload", "close", "redirect", "toast", "successMessage", "errorMessage", "refreshAfter", "undoable", "params", "actionParams", "resultDialog", "target", "body", "openIn", "modal", "chain", "chainMode", "onSuccess", "onFailure", "opensInNewTab", "newTabUrl"];
|
|
79
|
+
export declare const ACTION_DEF_KEYS: readonly ["type", "actionType", "name", "label", "confirmText", "confirm", "condition", "disabled", "api", "endpoint", "method", "navigate", "onClick", "reload", "close", "redirect", "toast", "successMessage", "errorMessage", "refreshAfter", "undoable", "params", "actionParams", "resultDialog", "target", "body", "openIn", "modal", "chain", "chainMode", "onSuccess", "onFailure", "opensInNewTab", "newTabUrl", "locations", "visible", "requiredPermissions", "icon", "variant", "order", "component", "objectName", "ai", "aria", "bodyExtra", "bodyShape", "mode", "recordIdField", "recordIdParam", "requiresFeature", "shortcut", "bulkEnabled"];
|
|
63
80
|
/**
|
|
64
81
|
* Every property `@objectstack/spec`'s `ActionSchema` declares.
|
|
65
82
|
*
|
|
@@ -32,25 +32,42 @@
|
|
|
32
32
|
* interface it mirrors would be the same "declared ≠ enforced" trap this whole
|
|
33
33
|
* thread is about.
|
|
34
34
|
*
|
|
35
|
-
* ── What the inventory found,
|
|
36
|
-
* `ActionDef`
|
|
37
|
-
*
|
|
35
|
+
* ── What the inventory found, and what step 2 did with it ────────────────────
|
|
36
|
+
* Step 1 found `ActionDef` declaring 34 keys against the spec `ActionSchema`'s
|
|
37
|
+
* 36, overlapping on 17. The two halves of the difference were different
|
|
38
|
+
* problems, and step 2 (objectstack#4075) treated them differently:
|
|
38
39
|
*
|
|
39
40
|
* 18 keys the SPEC owns that `ActionDef` never declared — `ai`, `aria`,
|
|
40
41
|
* `bodyExtra`, `bodyShape`, `bulkEnabled`, `component`, `icon`, `locations`,
|
|
41
42
|
* `mode`, `objectName`, `order`, `recordIdField`, `recordIdParam`,
|
|
42
43
|
* `requiredPermissions`, `requiresFeature`, `shortcut`, `variant`, `visible`.
|
|
43
|
-
* These are authored today and reach readers through the index
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
44
|
+
* These are authored today and used to reach readers through the index
|
|
45
|
+
* signature. **Step 2 promoted all 18 to explicit optional fields**, typed by
|
|
46
|
+
* DERIVATION from `@objectstack/spec`'s `ActionInput` rather than by hand-copied
|
|
47
|
+
* shapes. The `as any` casts `ActionEngine` needed to read `visible`,
|
|
48
|
+
* `locations` and `requiredPermissions` are gone with them — those casts existed
|
|
49
|
+
* only because the fields were undeclared.
|
|
50
|
+
*
|
|
51
|
+
* Two of the 18 landed as `undefined` rather than as usable types, which is the
|
|
52
|
+
* correct outcome: spec 17 retired `shortcut` and `bulkEnabled` as `retiredKey()`
|
|
53
|
+
* tombstones (`z.never()`), so deriving turns "authoring this is a parse
|
|
54
|
+
* rejection" into a compile error at no cost. Hand-copying would have quietly
|
|
55
|
+
* re-legitimized two dead keys — which is why the types are derived.
|
|
47
56
|
*
|
|
48
57
|
* 17 keys `ActionDef` declares that the spec does not own — `actionType`, `api`,
|
|
49
58
|
* `chain`, `chainMode`, `close`, `condition`, `confirm`, `endpoint`, `modal`,
|
|
50
59
|
* `navigate`, `onClick`, `onFailure`, `onSuccess`, `redirect`, `reload`, `toast`,
|
|
51
|
-
* `actionParams`.
|
|
52
|
-
*
|
|
53
|
-
*
|
|
60
|
+
* `actionParams`. Step 2 marked `@deprecated`, with the spec spelling to use
|
|
61
|
+
* instead, ONLY the four the runner itself proves are aliases: `actionType` (→
|
|
62
|
+
* `type`), `api` and `endpoint` (→ `target`; `executeAPI` resolves
|
|
63
|
+
* `api || endpoint || target`), and `navigate` (→ flat `target`/`openIn`;
|
|
64
|
+
* `executeNavigation` already falls back to them). The rest are runner mechanics
|
|
65
|
+
* with no spec counterpart — chaining, toasts, post-execution reload/close — and
|
|
66
|
+
* deprecating them toward a spelling that does not exist would be worse than
|
|
67
|
+
* leaving them declared.
|
|
68
|
+
*
|
|
69
|
+
* Step 3 remains: remove the index signature, at which point `tsc` catches both
|
|
70
|
+
* typos and retired keys and the dev-mode warning below can retire with it.
|
|
54
71
|
*/
|
|
55
72
|
/**
|
|
56
73
|
* Every property `ActionDef` declares, in declaration order.
|
|
@@ -94,6 +111,29 @@ export const ACTION_DEF_KEYS = [
|
|
|
94
111
|
'onFailure',
|
|
95
112
|
'opensInNewTab',
|
|
96
113
|
'newTabUrl',
|
|
114
|
+
// Promoted out of the index signature by objectstack#4075 step 2 — the 18 keys
|
|
115
|
+
// the spec owns that `ActionDef` had never declared. Their types are derived
|
|
116
|
+
// from `@objectstack/spec`'s `ActionInput`, so this list is the only
|
|
117
|
+
// hand-maintained half, and `actionKeys.pin.test.ts` re-derives it from the
|
|
118
|
+
// interface's AST.
|
|
119
|
+
'locations',
|
|
120
|
+
'visible',
|
|
121
|
+
'requiredPermissions',
|
|
122
|
+
'icon',
|
|
123
|
+
'variant',
|
|
124
|
+
'order',
|
|
125
|
+
'component',
|
|
126
|
+
'objectName',
|
|
127
|
+
'ai',
|
|
128
|
+
'aria',
|
|
129
|
+
'bodyExtra',
|
|
130
|
+
'bodyShape',
|
|
131
|
+
'mode',
|
|
132
|
+
'recordIdField',
|
|
133
|
+
'recordIdParam',
|
|
134
|
+
'requiresFeature',
|
|
135
|
+
'shortcut',
|
|
136
|
+
'bulkEnabled',
|
|
97
137
|
];
|
|
98
138
|
/**
|
|
99
139
|
* Every property `@objectstack/spec`'s `ActionSchema` declares.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ObjectUI - Query AST Builder
|
|
3
|
-
* Phase 3.3:
|
|
3
|
+
* Phase 3.3: DriverQueryConfig AST implementation
|
|
4
4
|
* ObjectStack Spec v2.0.1: Window functions support
|
|
5
5
|
*/
|
|
6
|
-
import type {
|
|
6
|
+
import type { SqlQueryAST, DriverQueryConfig } from '@object-ui/types';
|
|
7
7
|
/**
|
|
8
|
-
* Query AST Builder - Converts
|
|
8
|
+
* Query AST Builder - Converts DriverQueryConfig to AST
|
|
9
9
|
*/
|
|
10
10
|
export declare class QueryASTBuilder {
|
|
11
|
-
build(query:
|
|
11
|
+
build(query: DriverQueryConfig): SqlQueryAST;
|
|
12
12
|
private buildSelect;
|
|
13
13
|
private buildFrom;
|
|
14
14
|
private buildWhere;
|
|
@@ -26,7 +26,7 @@ export declare class QueryASTBuilder {
|
|
|
26
26
|
* Build window function node (ObjectStack Spec v2.0.1)
|
|
27
27
|
*/
|
|
28
28
|
private buildWindow;
|
|
29
|
-
optimize(ast:
|
|
29
|
+
optimize(ast: SqlQueryAST): SqlQueryAST;
|
|
30
30
|
}
|
|
31
31
|
export declare const defaultQueryASTBuilder: QueryASTBuilder;
|
|
32
|
-
export declare function buildQueryAST(query:
|
|
32
|
+
export declare function buildQueryAST(query: DriverQueryConfig): SqlQueryAST;
|
package/dist/query/query-ast.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ObjectUI - Query AST Builder
|
|
3
|
-
* Phase 3.3:
|
|
3
|
+
* Phase 3.3: DriverQueryConfig AST implementation
|
|
4
4
|
* ObjectStack Spec v2.0.1: Window functions support
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
7
|
-
* Query AST Builder - Converts
|
|
7
|
+
* Query AST Builder - Converts DriverQueryConfig to AST
|
|
8
8
|
*/
|
|
9
9
|
export class QueryASTBuilder {
|
|
10
10
|
build(query) {
|
|
@@ -7,7 +7,17 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { Registry } from './Registry.js';
|
|
9
9
|
import type { PluginScope, PluginScopeConfig, AppMetadataPlugin, AppPluginContext } from '@object-ui/types';
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* A plugin for objectui's component REGISTRY: it declares its name/version and
|
|
12
|
+
* a `register(registry | scope)` callback that contributes renderers.
|
|
13
|
+
*
|
|
14
|
+
* NOT the spec's `PluginDefinition` (`@objectstack/spec/kernel`), whose name
|
|
15
|
+
* this interface carried until objectstack#4115. That one is the platform
|
|
16
|
+
* PACKAGE manifest — `{ id?, type?, slug?, staticPath?, version?, author?,
|
|
17
|
+
* homepage?, onInstall?, onEnable?, … }` — a marketplace/install-time document
|
|
18
|
+
* with no `register` seam, and it shares no required member with this type.
|
|
19
|
+
*/
|
|
20
|
+
export interface RegistryPluginDefinition {
|
|
11
21
|
name: string;
|
|
12
22
|
version: string;
|
|
13
23
|
dependencies?: string[];
|
|
@@ -28,7 +38,7 @@ export declare class PluginSystem {
|
|
|
28
38
|
* @param useScope Whether to use scoped loading (default: true for better isolation)
|
|
29
39
|
* @throws Error if dependencies are missing
|
|
30
40
|
*/
|
|
31
|
-
loadPlugin(plugin:
|
|
41
|
+
loadPlugin(plugin: RegistryPluginDefinition, registry: Registry, useScope?: boolean): Promise<void>;
|
|
32
42
|
/**
|
|
33
43
|
* Unload a plugin from the system
|
|
34
44
|
* @param name The name of the plugin to unload
|
|
@@ -52,7 +62,7 @@ export declare class PluginSystem {
|
|
|
52
62
|
* @param name The name of the plugin
|
|
53
63
|
* @returns The plugin definition or undefined
|
|
54
64
|
*/
|
|
55
|
-
getPlugin(name: string):
|
|
65
|
+
getPlugin(name: string): RegistryPluginDefinition | undefined;
|
|
56
66
|
/**
|
|
57
67
|
* Get all loaded plugin names
|
|
58
68
|
* @returns Array of loaded plugin names
|
|
@@ -62,11 +72,11 @@ export declare class PluginSystem {
|
|
|
62
72
|
* Get all plugin definitions
|
|
63
73
|
* @returns Array of all plugin definitions
|
|
64
74
|
*/
|
|
65
|
-
getAllPlugins():
|
|
75
|
+
getAllPlugins(): RegistryPluginDefinition[];
|
|
66
76
|
/**
|
|
67
77
|
* Install an AppMetadataPlugin at runtime.
|
|
68
78
|
*
|
|
69
|
-
* Wraps the plugin as a
|
|
79
|
+
* Wraps the plugin as a RegistryPluginDefinition, calls its `init()` and `start()`
|
|
70
80
|
* lifecycle hooks, and loads it into the system.
|
|
71
81
|
*
|
|
72
82
|
* @param plugin - An AppMetadataPlugin instance
|
|
@@ -142,7 +142,7 @@ export class PluginSystem {
|
|
|
142
142
|
/**
|
|
143
143
|
* Install an AppMetadataPlugin at runtime.
|
|
144
144
|
*
|
|
145
|
-
* Wraps the plugin as a
|
|
145
|
+
* Wraps the plugin as a RegistryPluginDefinition, calls its `init()` and `start()`
|
|
146
146
|
* lifecycle hooks, and loads it into the system.
|
|
147
147
|
*
|
|
148
148
|
* @param plugin - An AppMetadataPlugin instance
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
* WidgetRegistry - Runtime widget management with auto-discovery.
|
|
10
10
|
*
|
|
11
11
|
* Provides registration, loading, and lookup of runtime widgets
|
|
12
|
-
* described by
|
|
12
|
+
* described by RuntimeWidgetManifest objects. Widgets can be loaded from
|
|
13
13
|
* ES module URLs, provided inline, or resolved from the component registry.
|
|
14
14
|
*
|
|
15
15
|
* @module
|
|
16
16
|
*/
|
|
17
|
-
import type {
|
|
17
|
+
import type { RuntimeWidgetManifest, ResolvedWidget, WidgetRegistryListener } from '@object-ui/types';
|
|
18
18
|
import type { Registry } from './Registry.js';
|
|
19
19
|
/**
|
|
20
20
|
* Options for creating a WidgetRegistry instance.
|
|
@@ -54,11 +54,11 @@ export declare class WidgetRegistry {
|
|
|
54
54
|
* Register a widget manifest.
|
|
55
55
|
* Does not load the widget; call `load()` to resolve it.
|
|
56
56
|
*/
|
|
57
|
-
register(manifest:
|
|
57
|
+
register(manifest: RuntimeWidgetManifest): void;
|
|
58
58
|
/**
|
|
59
59
|
* Register multiple widget manifests at once.
|
|
60
60
|
*/
|
|
61
|
-
registerAll(manifests:
|
|
61
|
+
registerAll(manifests: RuntimeWidgetManifest[]): void;
|
|
62
62
|
/**
|
|
63
63
|
* Unregister a widget by name.
|
|
64
64
|
*/
|
|
@@ -66,15 +66,15 @@ export declare class WidgetRegistry {
|
|
|
66
66
|
/**
|
|
67
67
|
* Get a widget manifest by name.
|
|
68
68
|
*/
|
|
69
|
-
getManifest(name: string):
|
|
69
|
+
getManifest(name: string): RuntimeWidgetManifest | undefined;
|
|
70
70
|
/**
|
|
71
71
|
* Get all registered widget manifests.
|
|
72
72
|
*/
|
|
73
|
-
getAllManifests():
|
|
73
|
+
getAllManifests(): RuntimeWidgetManifest[];
|
|
74
74
|
/**
|
|
75
75
|
* Get manifests filtered by category.
|
|
76
76
|
*/
|
|
77
|
-
getByCategory(category: string):
|
|
77
|
+
getByCategory(category: string): RuntimeWidgetManifest[];
|
|
78
78
|
/**
|
|
79
79
|
* Check if a widget is registered.
|
|
80
80
|
*/
|
|
@@ -244,7 +244,7 @@ export class WidgetRegistry {
|
|
|
244
244
|
// source.url is only known at runtime.
|
|
245
245
|
//
|
|
246
246
|
// Security: Widget URLs must be from trusted sources only. Never pass
|
|
247
|
-
// user-supplied URLs directly to
|
|
247
|
+
// user-supplied URLs directly to RuntimeWidgetManifest. URLs should be validated
|
|
248
248
|
// and controlled by the application developer.
|
|
249
249
|
//
|
|
250
250
|
// CSP Consideration: If your application uses strict Content Security Policy,
|
|
@@ -19,14 +19,20 @@
|
|
|
19
19
|
* `large` is the unconditional base; `medium`/`small`/`xsmall` are `max-width`
|
|
20
20
|
* overrides.
|
|
21
21
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
import type { ResponsiveStyles } from '@objectstack/spec/ui';
|
|
23
|
+
/**
|
|
24
|
+
* `StyleMap` / `ResponsiveStyles` are **owned by the spec** (ADR-0065,
|
|
25
|
+
* `@objectstack/spec/ui`) and re-exported here, not re-declared.
|
|
26
|
+
*
|
|
27
|
+
* They used to be hand-written copies under the spec's own names. Both were
|
|
28
|
+
* member-for-member identical to the spec's at the time of the burn-down
|
|
29
|
+
* (objectstack#4115), which is exactly what makes a copy dangerous: it passes
|
|
30
|
+
* every structural comparison right up until the spec adds a breakpoint or
|
|
31
|
+
* widens a value type, and the doc comment above claims spec canonicity the
|
|
32
|
+
* whole time. Binding the names to the spec at compile time is the only form
|
|
33
|
+
* that cannot drift.
|
|
34
|
+
*/
|
|
35
|
+
export type { StyleMap, ResponsiveStyles } from '@objectstack/spec/ui';
|
|
30
36
|
/** max-width breakpoints (px), mirroring Builder.io's default device sizes. */
|
|
31
37
|
export declare const STYLE_BREAKPOINTS: Record<'medium' | 'small' | 'xsmall', number>;
|
|
32
38
|
/** True when a node actually carries responsive styles worth compiling. */
|
|
@@ -26,14 +26,26 @@ export interface ChartResultField {
|
|
|
26
26
|
label?: string;
|
|
27
27
|
format?: string;
|
|
28
28
|
}
|
|
29
|
-
|
|
29
|
+
/**
|
|
30
|
+
* One renderer-internal series binding produced by {@link buildChartSeries}:
|
|
31
|
+
* WHICH result-set column to draw and what to call it.
|
|
32
|
+
*
|
|
33
|
+
* NOT the spec's `ChartSeries` (`@objectstack/spec/ui`), which this type was
|
|
34
|
+
* named after until objectstack#4115. That one is the AUTHORED dataset-binding
|
|
35
|
+
* descriptor — `{ name, label?, type?, color?, stack?, yAxis, variant?,
|
|
36
|
+
* dashArray?, opacity? }`, where `name` is a measure and no `data` is carried.
|
|
37
|
+
* A third shape, `ChartDataSeries` in `@object-ui/types` (renamed in the same
|
|
38
|
+
* burn-down), is the inline static-data series of an SDUI `ChartSchema` node.
|
|
39
|
+
* Three different concepts; this is the one the chart renderers consume.
|
|
40
|
+
*/
|
|
41
|
+
export interface ChartSeriesBinding {
|
|
30
42
|
dataKey: string;
|
|
31
43
|
label: string;
|
|
32
44
|
}
|
|
33
45
|
export interface ChartSeriesResult {
|
|
34
46
|
data: Array<Record<string, unknown>>;
|
|
35
47
|
xAxisKey: string | undefined;
|
|
36
|
-
series:
|
|
48
|
+
series: ChartSeriesBinding[];
|
|
37
49
|
}
|
|
38
50
|
export declare function buildChartSeries(rows: Array<Record<string, unknown>> | null | undefined, dimensions: string[] | null | undefined, values: string[] | null | undefined, fields?: ChartResultField[] | null): ChartSeriesResult;
|
|
39
51
|
/**
|
|
@@ -78,6 +78,15 @@ export declare function dashboardFilterVariableDefs(defs: DashboardFilterDef[]):
|
|
|
78
78
|
* Build the operator shape (the value side of a `FilterCondition` entry) for
|
|
79
79
|
* one filter's current value. Returns `undefined` when the value imposes no
|
|
80
80
|
* constraint. The caller keys the result by the bound field name.
|
|
81
|
+
*
|
|
82
|
+
* A `date`/`dateRange` value is held to three spellings (#3151): a known
|
|
83
|
+
* preset name → range bounds; a date-macro token or ISO date → equality on
|
|
84
|
+
* that day; **anything else → skipped with a console warning**, never
|
|
85
|
+
* silently downgraded to an equality nothing can match. That last branch is
|
|
86
|
+
* the same strictness `buildWidgetScopedFilter` applies to a default binding
|
|
87
|
+
* on an unknown field name, for the same reason: a query the backend answers
|
|
88
|
+
* `200 OK` with zero rows is indistinguishable from "this range has no data",
|
|
89
|
+
* so the typo has to be said out loud somewhere.
|
|
81
90
|
*/
|
|
82
91
|
export declare function buildFilterCondition(def: DashboardFilterDef, value: unknown): Record<string, unknown> | unknown | undefined;
|
|
83
92
|
/**
|