@object-ui/core 17.2.0 → 17.5.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 +1436 -0
- package/README.md +31 -12
- package/dist/actions/ActionEngine.d.ts +53 -31
- package/dist/actions/ActionEngine.js +87 -66
- package/dist/actions/ActionRunner.d.ts +215 -24
- package/dist/actions/ActionRunner.js +334 -17
- package/dist/actions/actionErrorDetail.d.ts +26 -0
- package/dist/actions/actionErrorDetail.js +37 -0
- package/dist/actions/actionKeys.d.ts +96 -20
- package/dist/actions/actionKeys.js +168 -18
- package/dist/actions/actionResponse.d.ts +42 -0
- package/dist/actions/actionResponse.js +104 -0
- package/dist/actions/index.d.ts +3 -0
- package/dist/actions/index.js +3 -0
- package/dist/actions/serverActionHandler.d.ts +143 -0
- package/dist/actions/serverActionHandler.js +137 -0
- package/dist/data-scope/ViewDataProvider.d.ts +37 -12
- package/dist/data-scope/ViewDataProvider.js +83 -5
- package/dist/data-scope/element-data-source.d.ts +113 -0
- package/dist/data-scope/element-data-source.js +216 -0
- package/dist/data-scope/index.d.ts +2 -1
- package/dist/data-scope/index.js +1 -0
- package/dist/evaluator/ExpressionEvaluator.js +4 -2
- package/dist/evaluator/declaredPredicate.d.ts +119 -0
- package/dist/evaluator/declaredPredicate.js +152 -0
- package/dist/evaluator/fieldRules.d.ts +42 -2
- package/dist/evaluator/fieldRules.js +101 -11
- package/dist/evaluator/index.d.ts +2 -0
- package/dist/evaluator/index.js +2 -0
- package/dist/evaluator/listConditional.d.ts +18 -3
- package/dist/evaluator/listConditional.js +0 -0
- package/dist/evaluator/optionRules.js +5 -1
- package/dist/evaluator/predicateInput.d.ts +132 -0
- package/dist/evaluator/predicateInput.js +129 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.js +26 -1
- package/dist/protocols/DndProtocol.d.ts +42 -1
- package/dist/protocols/KeyboardProtocol.d.ts +31 -1
- package/dist/protocols/SharingProtocol.d.ts +11 -1
- package/dist/protocols/index.d.ts +0 -1
- package/dist/protocols/index.js +8 -1
- package/dist/registry/Registry.d.ts +24 -0
- package/dist/theme/ThemeEngine.d.ts +0 -8
- package/dist/theme/ThemeEngine.js +22 -103
- package/dist/theme/index.d.ts +1 -1
- package/dist/theme/index.js +7 -1
- package/dist/types/index.d.ts +42 -8
- package/dist/utils/chart-series.d.ts +258 -5
- package/dist/utils/chart-series.js +423 -20
- package/dist/utils/compare-to.d.ts +40 -13
- package/dist/utils/compare-to.js +4 -32
- package/dist/utils/dashboard-filters.d.ts +54 -8
- package/dist/utils/dashboard-filters.js +261 -12
- package/dist/utils/dataset-format.d.ts +79 -15
- package/dist/utils/dataset-format.js +130 -9
- package/dist/utils/dataset-pivot.d.ts +78 -0
- package/dist/utils/dataset-pivot.js +78 -0
- package/dist/utils/dom-props.d.ts +137 -0
- package/dist/utils/dom-props.js +153 -0
- package/dist/utils/filter-converter.d.ts +39 -11
- package/dist/utils/filter-converter.js +87 -7
- package/dist/utils/normalize-list-view.d.ts +26 -6
- package/dist/utils/normalize-list-view.js +30 -8
- package/dist/utils/number-display.d.ts +151 -0
- package/dist/utils/number-display.js +71 -0
- package/dist/utils/predicate-fields.d.ts +96 -0
- package/dist/utils/predicate-fields.js +163 -0
- package/dist/utils/predicate-record.d.ts +32 -0
- package/dist/utils/predicate-record.js +120 -0
- package/dist/utils/record-title.js +0 -0
- package/dist/utils/resolve-view-id.d.ts +31 -0
- package/dist/utils/resolve-view-id.js +45 -0
- package/dist/utils/sort-query.d.ts +55 -0
- package/dist/utils/sort-query.js +35 -0
- package/package.json +5 -5
- package/dist/protocols/NotificationProtocol.d.ts +0 -71
- package/dist/protocols/NotificationProtocol.js +0 -89
- package/dist/utils/merge-views-into-objects.d.ts +0 -19
- package/dist/utils/merge-views-into-objects.js +0 -39
|
@@ -5,7 +5,22 @@
|
|
|
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
|
-
|
|
8
|
+
/**
|
|
9
|
+
* @object-ui/core - Action Runner
|
|
10
|
+
*
|
|
11
|
+
* Executes actions defined in ActionSchema and EventHandler.
|
|
12
|
+
*
|
|
13
|
+
* Dispatches every `@objectstack/spec` `ActionType` — `script`, `url`, `modal`,
|
|
14
|
+
* `flow`, `api`, `form` — plus the one declared renderer-local alias,
|
|
15
|
+
* `navigation` (see `ObjectUiLocalActionType`). The table that does it is typed
|
|
16
|
+
* against that vocabulary, so this list cannot go stale the way the old comment
|
|
17
|
+
* had (it still claimed five types after `form` shipped).
|
|
18
|
+
*
|
|
19
|
+
* Features: conditional execution, confirmation, toast notifications,
|
|
20
|
+
* redirect handling, action chaining, custom handler registration.
|
|
21
|
+
*/
|
|
22
|
+
import type { UIActionSchema } from '@object-ui/types';
|
|
23
|
+
import type { Action as SpecActionInput } from '@objectstack/spec/ui';
|
|
9
24
|
import { ExpressionEvaluator } from '../evaluator/ExpressionEvaluator';
|
|
10
25
|
import { type UndoableOperation } from './UndoManager';
|
|
11
26
|
export interface ActionResult {
|
|
@@ -61,6 +76,30 @@ export interface ApiConfig {
|
|
|
61
76
|
/**
|
|
62
77
|
* Action definition accepted by the runner.
|
|
63
78
|
* Compatible with both UIActionSchema (spec v2.0.1) and legacy crud.ts ActionSchema.
|
|
79
|
+
*
|
|
80
|
+
* ── CLOSED since objectstack#4075 step 3 ──────────────────────────────────────
|
|
81
|
+
*
|
|
82
|
+
* This interface used to end with `[key: string]: any`, so it accepted any key
|
|
83
|
+
* of any type: deleting `execute` from it produced ZERO compile errors, a typo
|
|
84
|
+
* (`targt`, `exectue`) type-checked, and a tombstoned key sailed through to a
|
|
85
|
+
* runner that then silently did nothing — the objectstack#2169 "Mark Done does
|
|
86
|
+
* nothing" shape. The index signature is gone. Every key this type accepts is
|
|
87
|
+
* now written down below, and `tsc` rejects the rest at any site that AUTHORS an
|
|
88
|
+
* action literal in code.
|
|
89
|
+
*
|
|
90
|
+
* What it does NOT reach, and what still covers that: stored `sys_metadata` rows
|
|
91
|
+
* are rehydrated UNPARSED (objectstack#3903), so authored metadata arrives at
|
|
92
|
+
* `runner.execute()` as a plain object the compiler never saw. The dev-mode
|
|
93
|
+
* `warnOnUnknownActionKeys` shim from step 1 therefore STAYS — it is not
|
|
94
|
+
* redundant with the closed type, it is the other half of the same surface, and
|
|
95
|
+
* the two halves catch disjoint populations (code-authored literals vs. stored
|
|
96
|
+
* rows).
|
|
97
|
+
*
|
|
98
|
+
* {@link ActionContext} keeps ITS index signature, deliberately. It is a runtime
|
|
99
|
+
* data bag whose keys are genuinely open (`data`, `record`, `pageVariables`,
|
|
100
|
+
* `user`, plus whatever a host passes); this is a declared metadata contract
|
|
101
|
+
* mirroring `@objectstack/spec`'s `ActionSchema`. Open key set on a data bag is
|
|
102
|
+
* correct; open key set on a contract is the bug above.
|
|
64
103
|
*/
|
|
65
104
|
export interface ActionDef {
|
|
66
105
|
/** Action type identifier — a `RunnableActionType` (the spec's six plus the
|
|
@@ -77,6 +116,24 @@ export interface ActionDef {
|
|
|
77
116
|
name?: string;
|
|
78
117
|
/** Display label */
|
|
79
118
|
label?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Human description of the action, shown as the param-collection dialog's
|
|
121
|
+
* subtitle (`useConsoleActionRuntime` reads it beside `label`).
|
|
122
|
+
*
|
|
123
|
+
* objectui vocabulary, not spec: `@objectstack/spec`'s `ActionSchema` has no
|
|
124
|
+
* `description`, so this derives from `@object-ui/types`' renderer view of an
|
|
125
|
+
* action (`UIActionSchema`, `ui-action.ts`) — the same "authorable for a
|
|
126
|
+
* declared surface" source `check:action-forward-parity` derives its owed set
|
|
127
|
+
* from, which is why that gate already requires all four action renderers to
|
|
128
|
+
* forward this key (objectui#4192: `action:menu`'s dialog titled itself
|
|
129
|
+
* "Action parameters" instead of naming the action).
|
|
130
|
+
*
|
|
131
|
+
* Promoted by step 3 (objectstack#4075): the key was authorable, forwarded
|
|
132
|
+
* and read, but `ActionDef` never declared it, so it reached its reader only
|
|
133
|
+
* through `[key: string]: any`. Deleting the index signature is what surfaced
|
|
134
|
+
* it — the two TS2353s the deletion produced repo-wide were both this key.
|
|
135
|
+
*/
|
|
136
|
+
description?: UIActionSchema['description'];
|
|
80
137
|
/** Confirmation text — shows a confirm dialog before executing */
|
|
81
138
|
confirmText?: string;
|
|
82
139
|
/** Structured confirmation (from crud.ts) */
|
|
@@ -86,10 +143,31 @@ export interface ActionDef {
|
|
|
86
143
|
confirmText?: string;
|
|
87
144
|
cancelText?: string;
|
|
88
145
|
};
|
|
89
|
-
/**
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
146
|
+
/**
|
|
147
|
+
* Condition predicate — the action executes only while it holds.
|
|
148
|
+
*
|
|
149
|
+
* A boolean, a bare CEL string, a `${…}` template, or the normalized
|
|
150
|
+
* `{ dialect, source }` envelope `objectstack build` emits. Declared and
|
|
151
|
+
* FALSE skips the action; not declared at all (absent / empty predicate)
|
|
152
|
+
* executes. `boolean` is spelled out here because the execution gate now
|
|
153
|
+
* honours `condition: false` as the verdict it plainly is (objectui#3872) —
|
|
154
|
+
* the same widening `disabled` already carries below.
|
|
155
|
+
*/
|
|
156
|
+
condition?: string | boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Disabled predicate — the control renders inert while it holds.
|
|
159
|
+
*
|
|
160
|
+
* Same three arms as {@link ActionDef.visible}, derived from the same spec
|
|
161
|
+
* field, because the 2026-08-06 maintainer ruling on objectstack#4075 gave
|
|
162
|
+
* both keys ONE shape: `boolean | string(CEL) | { dialect, source }` —
|
|
163
|
+
* "boolean = 条件的退化形字面量,string = CEL 简写,信封 = 完整形". The
|
|
164
|
+
* envelope arm arrived in `@objectstack/spec` 17.0.0-rc.6 (objectstack#5970,
|
|
165
|
+
* PR objectstack#6450); until then this was a hand-written `string | boolean`
|
|
166
|
+
* that could not describe the envelope, which is why `DeclaredActionsBar`
|
|
167
|
+
* read it through an `(action as any).disabled` cast. Derived, not restated,
|
|
168
|
+
* so the two keys cannot drift apart again.
|
|
169
|
+
*/
|
|
170
|
+
disabled?: SpecActionInput['disabled'];
|
|
93
171
|
/**
|
|
94
172
|
* API endpoint (string URL or complex config).
|
|
95
173
|
*
|
|
@@ -121,6 +199,19 @@ export interface ActionDef {
|
|
|
121
199
|
* today (objectstack#4075 step 2).
|
|
122
200
|
*/
|
|
123
201
|
navigate?: any;
|
|
202
|
+
/** `navigation` alias: the target URL. `executeNavigation` resolves
|
|
203
|
+
* `to || target || redirect`, so a flat spec-style `target` also works. */
|
|
204
|
+
to?: string;
|
|
205
|
+
/** `navigation` alias: force the external-URL treatment that the scheme
|
|
206
|
+
* heuristic would otherwise decide. */
|
|
207
|
+
external?: boolean;
|
|
208
|
+
/** `navigation` alias: open in a new tab. The first-class spec switch is
|
|
209
|
+
* `openIn: 'new-tab'`, which WINS over this one — prefer it in new metadata.
|
|
210
|
+
* Unrelated to the retired `params.newTab` read (objectui#4097). */
|
|
211
|
+
newTab?: boolean;
|
|
212
|
+
/** `navigation` alias: replace the current history entry instead of pushing
|
|
213
|
+
* a new one. No `ActionSchema` counterpart in any spelling. */
|
|
214
|
+
replace?: boolean;
|
|
124
215
|
/** onClick callback (legacy) */
|
|
125
216
|
onClick?: () => void | Promise<void>;
|
|
126
217
|
/** Whether to reload data after success */
|
|
@@ -176,8 +267,9 @@ export interface ActionDef {
|
|
|
176
267
|
* would diverge silently rather than fail.
|
|
177
268
|
*
|
|
178
269
|
* Consumers dispatch bodies by registering a `script` handler that POSTs to
|
|
179
|
-
* `/api/v1/actions/{object}/{action}
|
|
180
|
-
*
|
|
270
|
+
* `/api/v1/actions/{object}/{action}`; the server runs the body through its
|
|
271
|
+
* sandbox. Build that handler with `createServerActionHandler` (#2904) —
|
|
272
|
+
* app-shell's `useConsoleActionRuntime` and `RecordDetailView` both do.
|
|
181
273
|
*/
|
|
182
274
|
body?: unknown;
|
|
183
275
|
/** For type: 'url' — where to open `target`. `'new-tab'` forces a new
|
|
@@ -212,16 +304,23 @@ export interface ActionDef {
|
|
|
212
304
|
/**
|
|
213
305
|
* Visibility predicate, evaluated against the runner's context.
|
|
214
306
|
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* `
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
|
|
224
|
-
|
|
307
|
+
* Three arms — `boolean | string(CEL) | { dialect, source }` — and all three
|
|
308
|
+
* now come from the spec. Step 2 had to write `SpecActionInput['visible'] |
|
|
309
|
+
* boolean` because the literal `visible: true` / `false` that
|
|
310
|
+
* `ActionEngine.getActionsForLocation` honours (pinned by
|
|
311
|
+
* `ActionEngine.visibility.test.ts`) was objectui tolerance the spec did not
|
|
312
|
+
* share, and it left the open question step 3 was blocked on: does the spec
|
|
313
|
+
* adopt the boolean, or does objectui drop it?
|
|
314
|
+
*
|
|
315
|
+
* The maintainer ruled ADOPT on 2026-08-06 (objectstack#4075): "统一形状,
|
|
316
|
+
* spec 采纳 —— `visible` / `disabled` 两键在 spec 侧统一收敛为
|
|
317
|
+
* `boolean | string(CEL) | {dialect, source}`(boolean = 条件的退化形字面量,
|
|
318
|
+
* string = CEL 简写,信封 = 完整形)". `@objectstack/spec` 17.0.0-rc.6 carries
|
|
319
|
+
* it (objectstack#5970, PR objectstack#6450), so the local `| boolean` is no
|
|
320
|
+
* longer a tolerance to declare — it is part of the derived type, and adding
|
|
321
|
+
* it back would restate a spec arm rather than widen anything.
|
|
322
|
+
*/
|
|
323
|
+
visible?: SpecActionInput['visible'];
|
|
225
324
|
/** System permissions the caller must ALL hold for the action to be offered
|
|
226
325
|
* (ADR-0066 D4 UI half — the server enforces the source of truth). */
|
|
227
326
|
requiredPermissions?: SpecActionInput['requiredPermissions'];
|
|
@@ -267,8 +366,6 @@ export interface ActionDef {
|
|
|
267
366
|
* remains available to a HOST passing it explicitly.
|
|
268
367
|
*/
|
|
269
368
|
bulkEnabled?: SpecActionInput['bulkEnabled'];
|
|
270
|
-
/** Any additional properties */
|
|
271
|
-
[key: string]: any;
|
|
272
369
|
}
|
|
273
370
|
/**
|
|
274
371
|
* A handler registered with {@link ActionRunner} — the client-side action
|
|
@@ -350,23 +447,57 @@ export interface ResultDialogSpec {
|
|
|
350
447
|
* cleanup purposes (the action already succeeded).
|
|
351
448
|
*/
|
|
352
449
|
export type ResultDialogHandler = (spec: ResultDialogSpec, data: unknown, action?: ActionDef) => Promise<void>;
|
|
450
|
+
/**
|
|
451
|
+
* One entry of a param's option list, as the RESOLVED param carries it.
|
|
452
|
+
*
|
|
453
|
+
* `label` / `value` are the two keys this layer itself reads and rewrites (i18n
|
|
454
|
+
* translation of the label, value matching). Everything else an option declares
|
|
455
|
+
* rides along in the catch-all and reaches the widgets untouched: per-option
|
|
456
|
+
* `visibleWhen` (the CEL predicate `resolveVisibleOptions()` filters on —
|
|
457
|
+
* ADR-0058 / #2284), `color`, `icon`, `disabled`.
|
|
458
|
+
*
|
|
459
|
+
* The catch-all is deliberate rather than a closed key list (objectui#3559).
|
|
460
|
+
* A field's option vocabulary is owned by the field metadata (`@objectstack/spec`'s
|
|
461
|
+
* `SelectOptionSchema`) and read by the option widgets; a param's option list is
|
|
462
|
+
* only a CONDUIT between the two. When this type restated that vocabulary as
|
|
463
|
+
* `{ label, value }`, the resolver dutifully rebuilt every inherited option to
|
|
464
|
+
* match and a field's `visibleWhen` stopped narrowing the dialog's list — the
|
|
465
|
+
* same field metadata behaving two ways on two surfaces. Naming the two keys
|
|
466
|
+
* this layer uses and passing the rest through is what keeps that from
|
|
467
|
+
* recurring; it is NOT an invitation to author new resolved-only option keys
|
|
468
|
+
* (the spec's schema is the authoring gate, and it is `.strict()`).
|
|
469
|
+
*/
|
|
470
|
+
export type ActionParamOption = {
|
|
471
|
+
label: string;
|
|
472
|
+
value: string;
|
|
473
|
+
[key: string]: unknown;
|
|
474
|
+
};
|
|
353
475
|
/**
|
|
354
476
|
* ActionParam definition accepted by the runner.
|
|
355
477
|
* Compatible with @objectstack/spec ActionParam.
|
|
478
|
+
*
|
|
479
|
+
* The RESOLVED shape — what `resolveActionParams()` emits and `ActionParamDialog`
|
|
480
|
+
* reads, after a field-backed param's `{ field }` reference has been inlined.
|
|
481
|
+
* The AUTHORING counterpart is `@object-ui/types`' `ActionParam` (objectui#3174).
|
|
482
|
+
*
|
|
483
|
+
* `validation?: string` used to sit here too, and was removed by objectui#3201:
|
|
484
|
+
* no producer ever wrote it (it was never a key of `resolveActionParams()`'s
|
|
485
|
+
* `RawActionParam`, and the runtime field metadata a field-backed param inherits
|
|
486
|
+
* from carries no `validation` either) and no consumer ever read it —
|
|
487
|
+
* `paramToField()` did not map it, so it never reached the field widgets, whose
|
|
488
|
+
* rules `buildValidationRules()` builds from `required` / `minLength` /
|
|
489
|
+
* `maxLength` / `pattern`. Declaring it on the resolved side only invited the
|
|
490
|
+
* authoring side to declare it back.
|
|
356
491
|
*/
|
|
357
492
|
export interface ActionParamDef {
|
|
358
493
|
name: string;
|
|
359
494
|
label: string;
|
|
360
495
|
type: string;
|
|
361
496
|
required?: boolean;
|
|
362
|
-
options?:
|
|
363
|
-
label: string;
|
|
364
|
-
value: string;
|
|
365
|
-
}>;
|
|
497
|
+
options?: ActionParamOption[];
|
|
366
498
|
defaultValue?: unknown;
|
|
367
499
|
helpText?: string;
|
|
368
500
|
placeholder?: string;
|
|
369
|
-
validation?: string;
|
|
370
501
|
/**
|
|
371
502
|
* Visibility predicate (CEL) evaluated against the same scope as action
|
|
372
503
|
* `visible` (`current_user` / `app` / `data` / `features`). When it evaluates
|
|
@@ -530,6 +661,37 @@ export declare class ActionRunner {
|
|
|
530
661
|
* through to `executeActionSchema` and silently no-opped (the "Log Time does
|
|
531
662
|
* nothing" report). The current record id is forwarded as `?recordId=` for
|
|
532
663
|
* hosts that support it; the form route ignores unknown query params.
|
|
664
|
+
*
|
|
665
|
+
* ## An id never travels without its object (objectui#4292)
|
|
666
|
+
*
|
|
667
|
+
* `?recordId=` names an id and nothing else, so the consumer has to pick an
|
|
668
|
+
* object to resolve it against, and the only one it can pick is the FormView's
|
|
669
|
+
* own target object (`/forms/:name` does exactly that since objectui#4278).
|
|
670
|
+
* That is right whenever the action fired from a record OF that object, and
|
|
671
|
+
* nothing here used to check that it did: `target: 'showcase_task.edit'` on an
|
|
672
|
+
* Account record header is publishable metadata, and with per-table integer
|
|
673
|
+
* keys `GET /data/showcase_task/42` cheerfully answers for Account 42. Before
|
|
674
|
+
* #4278 the damage stopped at a duplicate insert; now that the route honours
|
|
675
|
+
* the param, the same mis-scoped action PATCHes a different object's record
|
|
676
|
+
* with no error anywhere. So the id is forwarded only when the two objects
|
|
677
|
+
* MATCH, and the object identity rides along as the consumer's second half of
|
|
678
|
+
* the check ({@link FORM_RECORD_OBJECT_PARAM}).
|
|
679
|
+
*
|
|
680
|
+
* The three outcomes, and why the third preserves rather than refuses:
|
|
681
|
+
*
|
|
682
|
+
* - **match** — forward `?recordId=&recordObject=`. The #4278 edit path,
|
|
683
|
+
* plus the identity the consumer re-checks against its own view metadata;
|
|
684
|
+
* - **mismatch** — forward NEITHER, i.e. the bare `/forms/:name`. A "log
|
|
685
|
+
* time" action fired from a Task at another object's create view is not a
|
|
686
|
+
* broken edit, it is a CREATE that happens to be launched from a record —
|
|
687
|
+
* which is exactly what this route did before #4278 taught it to read the
|
|
688
|
+
* param. Refusing here would break a shape that works;
|
|
689
|
+
* - **not comparable** — either end unknown ⇒ forward as before. A host that
|
|
690
|
+
* publishes no `objectName`, or an unqualified target name, gives this
|
|
691
|
+
* runner nothing to compare; tightening on absent information would turn
|
|
692
|
+
* working edit flows into creates on every such host. The guard only ever
|
|
693
|
+
* fires on information it actually has, and the consumer half applies the
|
|
694
|
+
* same rule to a missing `recordObject`.
|
|
533
695
|
*/
|
|
534
696
|
private executeForm;
|
|
535
697
|
/**
|
|
@@ -543,6 +705,35 @@ export declare class ActionRunner {
|
|
|
543
705
|
* drift apart again. Prefer `type: 'url'` + `openIn` in new metadata.
|
|
544
706
|
*/
|
|
545
707
|
private executeNavigation;
|
|
708
|
+
/**
|
|
709
|
+
* Assemble the request body for the runner's OWN `executeAPI` — the path taken
|
|
710
|
+
* when no host registered an `api` handler.
|
|
711
|
+
*
|
|
712
|
+
* `bodyExtra` is merged LAST, which is the spec's documented semantics for the
|
|
713
|
+
* key ("Static request-body fields for a `type:'api'` action, merged last
|
|
714
|
+
* (overrides user params)") and what the console's `apiHandler` already does on
|
|
715
|
+
* both of its branches. Before objectstack#6837 this path read `action.params`
|
|
716
|
+
* alone and never looked at `bodyExtra` at all, so an action whose payload lives
|
|
717
|
+
* entirely in `bodyExtra` — the shape the ADR-0087 conversion produces from an
|
|
718
|
+
* old object-form `params` page — POSTed an empty body here.
|
|
719
|
+
*
|
|
720
|
+
* `params` contributes only in its DEPRECATED non-array form (the compat window
|
|
721
|
+
* #5777 opened; see `warnOnDeprecatedObjectParams`). An ARRAY `params` is a
|
|
722
|
+
* parameter DEFINITION list, not a payload: it reaches this method unconsumed
|
|
723
|
+
* only when no `paramCollectionHandler` is mounted, and POSTing the definitions
|
|
724
|
+
* as the request body was never a payload any endpoint wanted. It now falls
|
|
725
|
+
* through to the context record like an absent `params` does.
|
|
726
|
+
*
|
|
727
|
+
* `bodyShape` then decides how that payload is WRAPPED, and the wrap covers the
|
|
728
|
+
* collected payload ONLY — `bodyExtra` stays at the top level. That is the
|
|
729
|
+
* spec's own wording for the key ("`{ wrap: 'data' }` nests the user-collected
|
|
730
|
+
* params under that key, while `recordIdParam` and other top-level keys stay
|
|
731
|
+
* flat") and what both console read-sites already do, so the key means one
|
|
732
|
+
* thing on every path that honours it. Until objectstack#6938 this path did not
|
|
733
|
+
* read it at all: the console `apiHandler` wrapped and the runner's own fallback
|
|
734
|
+
* did not, so the same action changed body shape with the host it ran under.
|
|
735
|
+
*/
|
|
736
|
+
private buildApiRequestBody;
|
|
546
737
|
/**
|
|
547
738
|
* Execute API action — supports both simple string endpoint and complex ApiConfig.
|
|
548
739
|
*/
|