@object-ui/core 17.3.0 → 17.6.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 +2018 -0
- package/README.md +38 -34
- package/dist/actions/ActionEngine.d.ts +43 -26
- package/dist/actions/ActionEngine.js +67 -54
- package/dist/actions/ActionRunner.d.ts +281 -31
- package/dist/actions/ActionRunner.js +458 -36
- package/dist/actions/actionKeys.d.ts +163 -27
- package/dist/actions/actionKeys.js +238 -27
- package/dist/actions/actionResponse.js +1 -1
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/actions/recordIdParam.d.ts +77 -0
- package/dist/actions/recordIdParam.js +37 -0
- package/dist/actions/serverActionHandler.d.ts +1 -1
- package/dist/actions/serverActionHandler.js +1 -1
- 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.d.ts +42 -1
- package/dist/evaluator/ExpressionEvaluator.js +42 -1
- package/dist/evaluator/SafeExpressionParser.js +0 -4
- package/dist/evaluator/declaredPredicate.d.ts +119 -0
- package/dist/evaluator/declaredPredicate.js +152 -0
- package/dist/evaluator/fieldRules.d.ts +35 -0
- package/dist/evaluator/fieldRules.js +79 -20
- package/dist/evaluator/index.d.ts +2 -0
- package/dist/evaluator/index.js +2 -0
- package/dist/evaluator/listConditional.d.ts +54 -4
- package/dist/evaluator/listConditional.js +125 -19
- package/dist/evaluator/optionRules.d.ts +55 -0
- package/dist/evaluator/optionRules.js +60 -0
- package/dist/evaluator/predicateInput.d.ts +51 -3
- package/dist/evaluator/predicateInput.js +62 -5
- package/dist/evaluator/rowPredicateCanon.d.ts +67 -0
- package/dist/evaluator/rowPredicateCanon.js +208 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +31 -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/registry/Registry.d.ts +62 -16
- 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 +125 -12
- package/dist/utils/chart-presentation.d.ts +205 -0
- package/dist/utils/chart-presentation.js +280 -0
- package/dist/utils/chart-series.d.ts +390 -23
- package/dist/utils/chart-series.js +776 -32
- package/dist/utils/column-identity.d.ts +43 -0
- package/dist/utils/column-identity.js +47 -1
- 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 +73 -14
- package/dist/utils/dataset-format.js +142 -9
- package/dist/utils/dataset-pivot.d.ts +28 -7
- package/dist/utils/dataset-pivot.js +27 -6
- package/dist/utils/debug.js +7 -0
- package/dist/utils/dom-props.d.ts +137 -0
- package/dist/utils/dom-props.js +153 -0
- package/dist/utils/expand-fields.d.ts +97 -7
- package/dist/utils/expand-fields.js +97 -7
- package/dist/utils/filter-tokens.js +0 -1
- package/dist/utils/freeze-schema.d.ts +38 -1
- package/dist/utils/freeze-schema.js +10 -0
- package/dist/utils/humanize-label.d.ts +60 -0
- package/dist/utils/humanize-label.js +62 -0
- package/dist/utils/managedBy.d.ts +27 -2
- package/dist/utils/normalize-list-view.d.ts +36 -6
- package/dist/utils/normalize-list-view.js +93 -9
- package/dist/utils/number-display.d.ts +155 -0
- package/dist/utils/number-display.js +71 -0
- package/dist/utils/predicate-fields.d.ts +29 -4
- package/dist/utils/predicate-fields.js +44 -4
- package/dist/utils/resolve-view-id.d.ts +31 -0
- package/dist/utils/resolve-view-id.js +45 -0
- package/dist/utils/retired-field-types.d.ts +90 -0
- package/dist/utils/retired-field-types.js +124 -0
- package/dist/utils/sort-query.d.ts +57 -0
- package/dist/utils/sort-query.js +35 -0
- package/dist/utils/unmaterialized-fields.d.ts +52 -0
- package/dist/utils/unmaterialized-fields.js +57 -0
- package/dist/validation/index.d.ts +1 -0
- package/dist/validation/index.js +1 -0
- package/dist/validation/schema-validator.js +105 -0
- package/dist/validation/server-owned-value.d.ts +62 -0
- package/dist/validation/server-owned-value.js +99 -0
- package/dist/validation/validators/object-validation-engine.js +0 -2
- package/package.json +5 -5
- package/dist/__benchmarks__/core.bench.d.ts +0 -8
- package/dist/__benchmarks__/core.bench.js +0 -53
- package/dist/utils/merge-views-into-objects.d.ts +0 -19
- package/dist/utils/merge-views-into-objects.js +0 -39
|
@@ -6,26 +6,46 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
|
-
* What an action is allowed to carry — objectstack#4075
|
|
9
|
+
* What an action is allowed to carry — objectstack#4075, all three steps.
|
|
10
10
|
*
|
|
11
|
-
* `ActionDef`
|
|
12
|
-
* Concretely (objectui#2990): deleting `ActionDef.execute` produced
|
|
13
|
-
* errors even though the field had just been removed, and stale
|
|
14
|
-
* authoring `execute: 'markDone'` type-
|
|
15
|
-
* `@object-ui/types`' `ActionSchema` — which has no index signature —
|
|
16
|
-
* produced `TS2353` at the authoring site. One of the two readers
|
|
17
|
-
* retired key; the other
|
|
11
|
+
* `ActionDef` used to end with `[key: string]: any`, so it accepted any key of
|
|
12
|
+
* any type. Concretely (objectui#2990): deleting `ActionDef.execute` produced
|
|
13
|
+
* ZERO compile errors even though the field had just been removed, and stale
|
|
14
|
+
* metadata authoring `execute: 'markDone'` type-checked. The same deletion
|
|
15
|
+
* against `@object-ui/types`' `ActionSchema` — which has no index signature —
|
|
16
|
+
* correctly produced `TS2353` at the authoring site. One of the two readers
|
|
17
|
+
* could catch a retired key; the other was structurally incapable.
|
|
18
18
|
*
|
|
19
|
-
* That asymmetry
|
|
19
|
+
* That asymmetry was the issue. An open key set on a DECLARED METADATA CONTRACT
|
|
20
20
|
* is what lets a typo (`targt`, `exectue`) and a tombstoned key (`execute`) both
|
|
21
21
|
* sail through to a runner that then silently does nothing — the #2169 "Mark
|
|
22
22
|
* Done does nothing" shape.
|
|
23
23
|
*
|
|
24
|
-
* This module
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
24
|
+
* This module was step 1 of the staged narrowing: make the key set VISIBLE and
|
|
25
|
+
* warn on anything outside it, without changing a single type. Step 2 promoted
|
|
26
|
+
* the legitimate keys to explicit optional fields; **step 3 removed the index
|
|
27
|
+
* signature**, so `tsc` now rejects a typo or a retired key outright.
|
|
28
|
+
*
|
|
29
|
+
* ── Why this module SURVIVES step 3 ──────────────────────────────────────────
|
|
30
|
+
* Step 1 wrote that the dev-mode warning "can retire" once the index signature
|
|
31
|
+
* came down. Step 3 measured that and kept it, because the two mechanisms cover
|
|
32
|
+
* DISJOINT populations rather than the same one twice:
|
|
33
|
+
*
|
|
34
|
+
* - `tsc` sees action literals AUTHORED IN CODE. It rejects an unknown key at
|
|
35
|
+
* the construction site, which is the strongest possible signal — but only
|
|
36
|
+
* for actions that exist as TypeScript.
|
|
37
|
+
* - the warning below sees actions that arrive as DATA. objectstack#3903
|
|
38
|
+
* established that stored `sys_metadata` rows are rehydrated UNPARSED, so
|
|
39
|
+
* authored metadata reaches `runner.execute()` as a plain object no
|
|
40
|
+
* compiler ever looked at. That is the population `execute: 'markDone'`
|
|
41
|
+
* actually lives in, and no type can reach it.
|
|
42
|
+
*
|
|
43
|
+
* Retiring the warning would therefore have re-opened the runtime half of the
|
|
44
|
+
* gap while closing the compile-time half — which is why `executeScript`'s
|
|
45
|
+
* rename-prescription branch also survives, for the same rows and the same
|
|
46
|
+
* reason. What DID retire with the index signature is the inverted pin in
|
|
47
|
+
* `actionKeys.pin.test.ts` that asserted the signature was still there; it now
|
|
48
|
+
* asserts the opposite, which was always its stated completion condition.
|
|
29
49
|
*
|
|
30
50
|
* The lists are pinned by `__tests__/actionKeys.pin.test.ts`, which re-derives
|
|
31
51
|
* each one from its actual source. A hand-maintained list that drifts from the
|
|
@@ -66,17 +86,32 @@
|
|
|
66
86
|
* deprecating them toward a spelling that does not exist would be worse than
|
|
67
87
|
* leaving them declared.
|
|
68
88
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
89
|
+
* ── What step 3 found the first two steps had missed ─────────────────────────
|
|
90
|
+
* Deleting the index signature is the only thing that can name the keys still
|
|
91
|
+
* hiding behind it, and it named five, in two groups:
|
|
92
|
+
*
|
|
93
|
+
* `to` / `external` / `newTab` / `replace` — the `navigation` alias's own
|
|
94
|
+
* spelling. Step 1 had already ruled these legitimate and listed them below in
|
|
95
|
+
* {@link NAVIGATION_ALIAS_KEYS}, but step 2's scope was the SPEC-owned keys, so
|
|
96
|
+
* they were declared as data and never as fields; `executeNavigation` read them
|
|
97
|
+
* through the index signature. Promoted, and deliberately not `@deprecated` —
|
|
98
|
+
* step 2's acceptance ruled on exactly that point.
|
|
99
|
+
*
|
|
100
|
+
* `description` — objectui vocabulary from `@object-ui/types`' renderer view of
|
|
101
|
+
* an action, forwarded by all four action renderers (`check:action-forward-parity`
|
|
102
|
+
* requires it) and read by the param-collection dialog for its subtitle
|
|
103
|
+
* (objectui#4192). Authorable, forwarded, read — and undeclared. These were the
|
|
104
|
+
* only two `TS2353`s the deletion produced across the whole workspace.
|
|
71
105
|
*/
|
|
72
106
|
/**
|
|
73
107
|
* Every property `ActionDef` declares, in declaration order.
|
|
74
108
|
*
|
|
75
|
-
* Kept as data because TypeScript types do not survive to runtime —
|
|
76
|
-
*
|
|
77
|
-
*
|
|
109
|
+
* Kept as data because TypeScript types do not survive to runtime — `keyof
|
|
110
|
+
* ActionDef` is erased along with the interface, so it cannot hand a runtime
|
|
111
|
+
* classifier a list of anything. `actionKeys.pin.test.ts` re-derives this one
|
|
112
|
+
* from the interface's AST, which is what keeps the data true.
|
|
78
113
|
*/
|
|
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"];
|
|
114
|
+
export declare const ACTION_DEF_KEYS: readonly ["type", "actionType", "name", "label", "description", "confirmText", "confirm", "condition", "disabled", "api", "endpoint", "method", "navigate", "to", "external", "newTab", "replace", "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"];
|
|
80
115
|
/**
|
|
81
116
|
* Every property `@objectstack/spec`'s `ActionSchema` declares.
|
|
82
117
|
*
|
|
@@ -91,7 +126,7 @@ export declare const ACTION_DEF_KEYS: readonly ["type", "actionType", "name", "l
|
|
|
91
126
|
* test and wrong in shipped code — `@object-ui/types` made the same call for
|
|
92
127
|
* `ActionComponent`. The pin test does the walk and fails the day this drifts.
|
|
93
128
|
*/
|
|
94
|
-
export declare const SPEC_ACTION_KEYS: readonly ["_lock", "_lockDocsUrl", "_lockReason", "_lockSource", "_packageId", "_packageVersion", "_provenance", "ai", "aria", "body", "bodyExtra", "bodyShape", "bulkEnabled", "component", "confirmText", "disabled", "errorMessage", "execute", "icon", "label", "locations", "method", "mode", "name", "newTabUrl", "objectName", "openIn", "opensInNewTab", "order", "params", "recordIdField", "recordIdParam", "refreshAfter", "requiredPermissions", "requiresFeature", "resultDialog", "shortcut", "successMessage", "target", "type", "undoable", "variant", "visible"];
|
|
129
|
+
export declare const SPEC_ACTION_KEYS: readonly ["_lock", "_lockDocsUrl", "_lockReason", "_lockSource", "_packageId", "_packageVersion", "_provenance", "ai", "aria", "body", "bodyExtra", "bodyShape", "bulkEnabled", "component", "confirmText", "description", "disabled", "errorMessage", "execute", "icon", "label", "locations", "method", "mode", "name", "newTabUrl", "objectName", "onSuccess", "openIn", "opensInNewTab", "order", "params", "recordIdField", "recordIdParam", "refreshAfter", "requiredPermissions", "requiresFeature", "resultDialog", "shortcut", "successMessage", "target", "type", "undoable", "variant", "visible"];
|
|
95
130
|
/**
|
|
96
131
|
* The `navigation` alias's own spelling of a target, read off the action itself
|
|
97
132
|
* when no nested `navigate` object is present (`ActionRunner.executeNavigation`).
|
|
@@ -103,6 +138,54 @@ export declare const SPEC_ACTION_KEYS: readonly ["_lock", "_lockDocsUrl", "_lock
|
|
|
103
138
|
* runner itself supports.
|
|
104
139
|
*/
|
|
105
140
|
export declare const NAVIGATION_ALIAS_KEYS: readonly ["to", "external", "newTab", "replace"];
|
|
141
|
+
/**
|
|
142
|
+
* Keys a HOST composes on the DISPATCH OBJECT at dispatch time — chrome the
|
|
143
|
+
* runtime reads once on its way to the dialog, that no author ever writes and
|
|
144
|
+
* no store ever holds.
|
|
145
|
+
*
|
|
146
|
+
* Distinct from every other list in this module, and the distinction is the
|
|
147
|
+
* whole point: each of the three lists above restates one AUTHORED surface —
|
|
148
|
+
* what `ActionDef` itself declares, what the spec's `ActionSchema` declares,
|
|
149
|
+
* and the `navigation` alias's objectui dialect — so a key joining one of them
|
|
150
|
+
* is a key an author may legally write. This list claims no such derivation and
|
|
151
|
+
* must not acquire one: a key here is the opposite, and writing it in metadata
|
|
152
|
+
* is still a compile error that must stay one. Maintainer ruling
|
|
153
|
+
* 2026-08-22 fixes both halves of that: ⛔ the key is NOT declared on
|
|
154
|
+
* `ActionDef` and ⛔ NOT added to {@link ACTION_DEF_KEYS}; it is declared at the
|
|
155
|
+
* seam, on `packages/app-shell/src/consoleActionDispatch.ts`'s
|
|
156
|
+
* `ConsoleActionDispatch`, and appears HERE only so the dev-mode warning below
|
|
157
|
+
* stops calling it unknown.
|
|
158
|
+
*
|
|
159
|
+
* Why the warning has to know: `classifyActionKeys` sees the object the runner
|
|
160
|
+
* was handed, which is the DISPATCH, not the stored metadata row. With the key
|
|
161
|
+
* absent from the inventory, `warnOnUnknownActionKeys` told the author that a
|
|
162
|
+
* key TWO files read is one "no reader recognizes", and prescribed promoting it
|
|
163
|
+
* to `ActionDef` — the one shape the ruling forbids for it. A diagnostic that
|
|
164
|
+
* fires on the product's own privileged path is how a console gets muted.
|
|
165
|
+
*
|
|
166
|
+
* {@link HOST_STASHED_PARAM_KEYS} below is the same category one level down —
|
|
167
|
+
* host-composed keys inside `params` rather than on the action itself — and
|
|
168
|
+
* cites `DeclaredActionsBar` by name for the same reason this does. Two lists
|
|
169
|
+
* because the two warnings ask different questions of different objects, not
|
|
170
|
+
* because the categories differ.
|
|
171
|
+
*
|
|
172
|
+
* `overrideNotice` — the privileged-override safety copy (objectui#5178),
|
|
173
|
+
* naming the approvers about to be bypassed.
|
|
174
|
+
* - producer: `packages/app-shell/src/views/DeclaredActionsBar.tsx`, on the
|
|
175
|
+
* `can_act:false && can_override:true` branch.
|
|
176
|
+
* - readers: `packages/app-shell/src/hooks/useConsoleActionRuntime.tsx` and
|
|
177
|
+
* `packages/app-shell/src/views/RecordDetailView.tsx`, the console's two
|
|
178
|
+
* param-collection handlers, which render it ahead of the declared
|
|
179
|
+
* description in the dialog's subtitle.
|
|
180
|
+
*
|
|
181
|
+
* Anything added here must satisfy all three of: composed by a host in code,
|
|
182
|
+
* never read back out of stored metadata, and read by the runtime. A key an
|
|
183
|
+
* AUTHOR is meant to write belongs on `ActionDef` — or, when the spec owns it,
|
|
184
|
+
* in `@objectstack/spec` first — and not in this list. `actionKeys.pin.test.ts`
|
|
185
|
+
* pins the contents exactly, so growing the set is a deliberate, reviewed edit
|
|
186
|
+
* rather than a quiet one.
|
|
187
|
+
*/
|
|
188
|
+
export declare const HOST_DISPATCH_ACTION_KEYS: readonly ["overrideNotice"];
|
|
106
189
|
/**
|
|
107
190
|
* Keys the spec has TOMBSTONED: still present in `ActionSchema` so the parser can
|
|
108
191
|
* reject them BY NAME with a rename prescription, rather than fail with a bare
|
|
@@ -111,11 +194,27 @@ export declare const NAVIGATION_ALIAS_KEYS: readonly ["to", "external", "newTab"
|
|
|
111
194
|
* Warned about separately from unknown keys, and more loudly: an unknown key is
|
|
112
195
|
* probably a typo, while a retired key is metadata that used to work. That
|
|
113
196
|
* distinction is why `executeScript` carries a runtime branch returning the
|
|
114
|
-
* rename prescription
|
|
115
|
-
*
|
|
197
|
+
* rename prescription.
|
|
198
|
+
*
|
|
199
|
+
* Step 1 expected that branch to retire with the index signature. It does not,
|
|
200
|
+
* and the reason is the one in this module's header: `tsc` closed the
|
|
201
|
+
* code-authored half of the gap, while `execute: 'markDone'` lives in stored
|
|
202
|
+
* rows that reach the runner UNPARSED (objectstack#3903). The branch reads the
|
|
203
|
+
* key off an untyped view of the action precisely so that `ActionDef` can go on
|
|
204
|
+
* NOT declaring it — declaring it to make the read compile would re-legitimize
|
|
205
|
+
* a tombstone the spec keeps only in order to reject it by name.
|
|
116
206
|
*/
|
|
117
207
|
export declare const RETIRED_ACTION_KEYS: Readonly<Record<string, string>>;
|
|
118
|
-
/**
|
|
208
|
+
/**
|
|
209
|
+
* Every key an action may legitimately carry today — authored or host-composed.
|
|
210
|
+
*
|
|
211
|
+
* Four inputs, three of them mirrors of an authored surface and the fourth
|
|
212
|
+
* ({@link HOST_DISPATCH_ACTION_KEYS}) the host-composed dispatch chrome. The
|
|
213
|
+
* union is what `classifyActionKeys` consults, and it is deliberately wider
|
|
214
|
+
* than the authored surface: the runner classifies the object it was HANDED,
|
|
215
|
+
* and a host hands it a dispatch. Membership here grants nothing to an author —
|
|
216
|
+
* `ActionDef` is what decides that, and it is closed.
|
|
217
|
+
*/
|
|
119
218
|
export declare const KNOWN_ACTION_KEYS: ReadonlySet<string>;
|
|
120
219
|
/** Split an action's own keys into the two things worth saying out loud. */
|
|
121
220
|
export declare function classifyActionKeys(action: object | null | undefined): {
|
|
@@ -128,8 +227,45 @@ export declare function resetActionKeyWarnings(): void;
|
|
|
128
227
|
* Dev-mode only: name the keys an action carries that no reader will ever look
|
|
129
228
|
* at. Non-breaking by construction — it changes no types and rejects nothing.
|
|
130
229
|
*
|
|
131
|
-
* Silently binding no handler is the #2169 "Mark Done does nothing" shape
|
|
132
|
-
*
|
|
133
|
-
*
|
|
230
|
+
* Silently binding no handler is the #2169 "Mark Done does nothing" shape. The
|
|
231
|
+
* compiler now catches it in action literals AUTHORED IN CODE — objectstack#4075
|
|
232
|
+
* step 3 closed `ActionDef` — but not in the actions that arrive as DATA, which
|
|
233
|
+
* reach the runner unparsed and which no compiler ever looked at. This is the
|
|
234
|
+
* audible half for that population; see this module's header.
|
|
134
235
|
*/
|
|
135
236
|
export declare function warnOnUnknownActionKeys(action: object | null | undefined, where?: string): void;
|
|
237
|
+
/**
|
|
238
|
+
* Does this action carry the DEPRECATED object-form `params` — a static request
|
|
239
|
+
* payload written under the key that means "parameter definitions"?
|
|
240
|
+
*
|
|
241
|
+
* The discriminator is `Array.isArray` and the type guard is `api`, mirroring
|
|
242
|
+
* `@objectstack/spec`'s `inline-action-api-params-to-body-extra` conversion
|
|
243
|
+
* (ADR-0087 D2) key for key. Contract parity with the producer is the point: the
|
|
244
|
+
* conversion rewrites exactly this shape to `bodyExtra` at load, so the runner
|
|
245
|
+
* must recognize exactly the same shape as "the thing that got rewritten".
|
|
246
|
+
*
|
|
247
|
+
* The `api` guard is also what keeps the deprecation out of objectstack#6828's
|
|
248
|
+
* territory — object-form `params` on a `type: 'url'` action is a THIRD meaning
|
|
249
|
+
* (`interpolateTarget`'s `${param.X}` scope, `executeUrl`'s `params.newTab`) and
|
|
250
|
+
* `bodyExtra` is NOT its replacement. Do not widen this guard without that
|
|
251
|
+
* ruling.
|
|
252
|
+
*/
|
|
253
|
+
export declare function hasDeprecatedObjectParams(action: object | null | undefined): boolean;
|
|
254
|
+
/**
|
|
255
|
+
* Dev-mode only: name the object-form `params` that `@objectstack/spec` 17 already
|
|
256
|
+
* refuses at the authoring door, and prescribe `bodyExtra`.
|
|
257
|
+
*
|
|
258
|
+
* This is the audible half of the compat window the maintainer's 2026-08-06
|
|
259
|
+
* ruling on objectstack#5777 ordered (direction A — a separate key, no same-name
|
|
260
|
+
* union): the runner keeps READING a non-array `params` as the static payload for
|
|
261
|
+
* one version window, says so, and the arm is deleted at 18. The loud half lives
|
|
262
|
+
* at the producer, where it belongs — spec's `params` field refuses the object
|
|
263
|
+
* form outright with a message naming `bodyExtra`, and the ADR-0087 conversion
|
|
264
|
+
* rewrites sources that still carry it. So a warning is the correct severity
|
|
265
|
+
* HERE: by the time metadata reaches this runner the producer has already had its
|
|
266
|
+
* say, and what is left to catch is a host composing an ActionDef in code.
|
|
267
|
+
*
|
|
268
|
+
* Dev-only and warn-once, matching {@link warnOnUnknownActionKeys} — a warning
|
|
269
|
+
* that floods a production console is a warning that gets muted.
|
|
270
|
+
*/
|
|
271
|
+
export declare function warnOnDeprecatedObjectParams(action: object | null | undefined, where?: string): void;
|
|
@@ -6,26 +6,46 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
|
-
* What an action is allowed to carry — objectstack#4075
|
|
9
|
+
* What an action is allowed to carry — objectstack#4075, all three steps.
|
|
10
10
|
*
|
|
11
|
-
* `ActionDef`
|
|
12
|
-
* Concretely (objectui#2990): deleting `ActionDef.execute` produced
|
|
13
|
-
* errors even though the field had just been removed, and stale
|
|
14
|
-
* authoring `execute: 'markDone'` type-
|
|
15
|
-
* `@object-ui/types`' `ActionSchema` — which has no index signature —
|
|
16
|
-
* produced `TS2353` at the authoring site. One of the two readers
|
|
17
|
-
* retired key; the other
|
|
11
|
+
* `ActionDef` used to end with `[key: string]: any`, so it accepted any key of
|
|
12
|
+
* any type. Concretely (objectui#2990): deleting `ActionDef.execute` produced
|
|
13
|
+
* ZERO compile errors even though the field had just been removed, and stale
|
|
14
|
+
* metadata authoring `execute: 'markDone'` type-checked. The same deletion
|
|
15
|
+
* against `@object-ui/types`' `ActionSchema` — which has no index signature —
|
|
16
|
+
* correctly produced `TS2353` at the authoring site. One of the two readers
|
|
17
|
+
* could catch a retired key; the other was structurally incapable.
|
|
18
18
|
*
|
|
19
|
-
* That asymmetry
|
|
19
|
+
* That asymmetry was the issue. An open key set on a DECLARED METADATA CONTRACT
|
|
20
20
|
* is what lets a typo (`targt`, `exectue`) and a tombstoned key (`execute`) both
|
|
21
21
|
* sail through to a runner that then silently does nothing — the #2169 "Mark
|
|
22
22
|
* Done does nothing" shape.
|
|
23
23
|
*
|
|
24
|
-
* This module
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
24
|
+
* This module was step 1 of the staged narrowing: make the key set VISIBLE and
|
|
25
|
+
* warn on anything outside it, without changing a single type. Step 2 promoted
|
|
26
|
+
* the legitimate keys to explicit optional fields; **step 3 removed the index
|
|
27
|
+
* signature**, so `tsc` now rejects a typo or a retired key outright.
|
|
28
|
+
*
|
|
29
|
+
* ── Why this module SURVIVES step 3 ──────────────────────────────────────────
|
|
30
|
+
* Step 1 wrote that the dev-mode warning "can retire" once the index signature
|
|
31
|
+
* came down. Step 3 measured that and kept it, because the two mechanisms cover
|
|
32
|
+
* DISJOINT populations rather than the same one twice:
|
|
33
|
+
*
|
|
34
|
+
* - `tsc` sees action literals AUTHORED IN CODE. It rejects an unknown key at
|
|
35
|
+
* the construction site, which is the strongest possible signal — but only
|
|
36
|
+
* for actions that exist as TypeScript.
|
|
37
|
+
* - the warning below sees actions that arrive as DATA. objectstack#3903
|
|
38
|
+
* established that stored `sys_metadata` rows are rehydrated UNPARSED, so
|
|
39
|
+
* authored metadata reaches `runner.execute()` as a plain object no
|
|
40
|
+
* compiler ever looked at. That is the population `execute: 'markDone'`
|
|
41
|
+
* actually lives in, and no type can reach it.
|
|
42
|
+
*
|
|
43
|
+
* Retiring the warning would therefore have re-opened the runtime half of the
|
|
44
|
+
* gap while closing the compile-time half — which is why `executeScript`'s
|
|
45
|
+
* rename-prescription branch also survives, for the same rows and the same
|
|
46
|
+
* reason. What DID retire with the index signature is the inverted pin in
|
|
47
|
+
* `actionKeys.pin.test.ts` that asserted the signature was still there; it now
|
|
48
|
+
* asserts the opposite, which was always its stated completion condition.
|
|
29
49
|
*
|
|
30
50
|
* The lists are pinned by `__tests__/actionKeys.pin.test.ts`, which re-derives
|
|
31
51
|
* each one from its actual source. A hand-maintained list that drifts from the
|
|
@@ -66,21 +86,40 @@
|
|
|
66
86
|
* deprecating them toward a spelling that does not exist would be worse than
|
|
67
87
|
* leaving them declared.
|
|
68
88
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
89
|
+
* ── What step 3 found the first two steps had missed ─────────────────────────
|
|
90
|
+
* Deleting the index signature is the only thing that can name the keys still
|
|
91
|
+
* hiding behind it, and it named five, in two groups:
|
|
92
|
+
*
|
|
93
|
+
* `to` / `external` / `newTab` / `replace` — the `navigation` alias's own
|
|
94
|
+
* spelling. Step 1 had already ruled these legitimate and listed them below in
|
|
95
|
+
* {@link NAVIGATION_ALIAS_KEYS}, but step 2's scope was the SPEC-owned keys, so
|
|
96
|
+
* they were declared as data and never as fields; `executeNavigation` read them
|
|
97
|
+
* through the index signature. Promoted, and deliberately not `@deprecated` —
|
|
98
|
+
* step 2's acceptance ruled on exactly that point.
|
|
99
|
+
*
|
|
100
|
+
* `description` — objectui vocabulary from `@object-ui/types`' renderer view of
|
|
101
|
+
* an action, forwarded by all four action renderers (`check:action-forward-parity`
|
|
102
|
+
* requires it) and read by the param-collection dialog for its subtitle
|
|
103
|
+
* (objectui#4192). Authorable, forwarded, read — and undeclared. These were the
|
|
104
|
+
* only two `TS2353`s the deletion produced across the whole workspace.
|
|
71
105
|
*/
|
|
72
106
|
/**
|
|
73
107
|
* Every property `ActionDef` declares, in declaration order.
|
|
74
108
|
*
|
|
75
|
-
* Kept as data because TypeScript types do not survive to runtime —
|
|
76
|
-
*
|
|
77
|
-
*
|
|
109
|
+
* Kept as data because TypeScript types do not survive to runtime — `keyof
|
|
110
|
+
* ActionDef` is erased along with the interface, so it cannot hand a runtime
|
|
111
|
+
* classifier a list of anything. `actionKeys.pin.test.ts` re-derives this one
|
|
112
|
+
* from the interface's AST, which is what keeps the data true.
|
|
78
113
|
*/
|
|
79
114
|
export const ACTION_DEF_KEYS = [
|
|
80
115
|
'type',
|
|
81
116
|
'actionType',
|
|
82
117
|
'name',
|
|
83
118
|
'label',
|
|
119
|
+
// Promoted by step 3 — objectui vocabulary (`@object-ui/types`' renderer view
|
|
120
|
+
// of an action), forwarded by all four action renderers and read by the
|
|
121
|
+
// param-collection dialog, but never declared on `ActionDef`.
|
|
122
|
+
'description',
|
|
84
123
|
'confirmText',
|
|
85
124
|
'confirm',
|
|
86
125
|
'condition',
|
|
@@ -89,6 +128,14 @@ export const ACTION_DEF_KEYS = [
|
|
|
89
128
|
'endpoint',
|
|
90
129
|
'method',
|
|
91
130
|
'navigate',
|
|
131
|
+
// The `navigation` alias's own spelling, promoted to real fields by step 3.
|
|
132
|
+
// Listed a second time in `NAVIGATION_ALIAS_KEYS` below, which keeps the
|
|
133
|
+
// separate fact that these four are objectui dialect with a spec-adoption
|
|
134
|
+
// tripwire; this list is only "what the interface declares".
|
|
135
|
+
'to',
|
|
136
|
+
'external',
|
|
137
|
+
'newTab',
|
|
138
|
+
'replace',
|
|
92
139
|
'onClick',
|
|
93
140
|
'reload',
|
|
94
141
|
'close',
|
|
@@ -169,6 +216,15 @@ export const SPEC_ACTION_KEYS = [
|
|
|
169
216
|
'bulkEnabled',
|
|
170
217
|
'component',
|
|
171
218
|
'confirmText',
|
|
219
|
+
// Added to `ActionSchema` in @objectstack/spec 17.0.0-rc.6. Listed here purely
|
|
220
|
+
// because this array's contract is "every property the spec's `ActionSchema`
|
|
221
|
+
// declares" — restating the spec, not adopting a feature. `ActionDef` does NOT
|
|
222
|
+
// declare `description` and is not changed: whether the runner or any renderer
|
|
223
|
+
// should READ it is a separate question, and `actionKeys.pin.test.ts`'s
|
|
224
|
+
// `ActionDef` half stays green without it. What this entry buys is that an
|
|
225
|
+
// action carrying a `description` is no longer reported as having an unknown
|
|
226
|
+
// key, which is the only thing the inventory is consulted for.
|
|
227
|
+
'description',
|
|
172
228
|
'disabled',
|
|
173
229
|
'errorMessage',
|
|
174
230
|
'execute',
|
|
@@ -180,6 +236,14 @@ export const SPEC_ACTION_KEYS = [
|
|
|
180
236
|
'name',
|
|
181
237
|
'newTabUrl',
|
|
182
238
|
'objectName',
|
|
239
|
+
// Declared by `ActionSchema` as of @objectstack/spec 17.1.0 (objectui#5328).
|
|
240
|
+
// Listing it here is a DIAGNOSTIC statement only — `KNOWN_ACTION_KEYS` feeds
|
|
241
|
+
// `warnOnUnknownActionKeys`, so without this row an author writing the key the
|
|
242
|
+
// spec now accepts would be warned it is unknown. It says nothing about the
|
|
243
|
+
// key being forwarded: the four declared action surfaces still drop it before
|
|
244
|
+
// the runner, tracked as KNOWN_GAPS in check-action-forward-parity.mjs and
|
|
245
|
+
// filed as objectui#5493.
|
|
246
|
+
'onSuccess',
|
|
183
247
|
'openIn',
|
|
184
248
|
'opensInNewTab',
|
|
185
249
|
'order',
|
|
@@ -209,6 +273,54 @@ export const SPEC_ACTION_KEYS = [
|
|
|
209
273
|
* runner itself supports.
|
|
210
274
|
*/
|
|
211
275
|
export const NAVIGATION_ALIAS_KEYS = ['to', 'external', 'newTab', 'replace'];
|
|
276
|
+
/**
|
|
277
|
+
* Keys a HOST composes on the DISPATCH OBJECT at dispatch time — chrome the
|
|
278
|
+
* runtime reads once on its way to the dialog, that no author ever writes and
|
|
279
|
+
* no store ever holds.
|
|
280
|
+
*
|
|
281
|
+
* Distinct from every other list in this module, and the distinction is the
|
|
282
|
+
* whole point: each of the three lists above restates one AUTHORED surface —
|
|
283
|
+
* what `ActionDef` itself declares, what the spec's `ActionSchema` declares,
|
|
284
|
+
* and the `navigation` alias's objectui dialect — so a key joining one of them
|
|
285
|
+
* is a key an author may legally write. This list claims no such derivation and
|
|
286
|
+
* must not acquire one: a key here is the opposite, and writing it in metadata
|
|
287
|
+
* is still a compile error that must stay one. Maintainer ruling
|
|
288
|
+
* 2026-08-22 fixes both halves of that: ⛔ the key is NOT declared on
|
|
289
|
+
* `ActionDef` and ⛔ NOT added to {@link ACTION_DEF_KEYS}; it is declared at the
|
|
290
|
+
* seam, on `packages/app-shell/src/consoleActionDispatch.ts`'s
|
|
291
|
+
* `ConsoleActionDispatch`, and appears HERE only so the dev-mode warning below
|
|
292
|
+
* stops calling it unknown.
|
|
293
|
+
*
|
|
294
|
+
* Why the warning has to know: `classifyActionKeys` sees the object the runner
|
|
295
|
+
* was handed, which is the DISPATCH, not the stored metadata row. With the key
|
|
296
|
+
* absent from the inventory, `warnOnUnknownActionKeys` told the author that a
|
|
297
|
+
* key TWO files read is one "no reader recognizes", and prescribed promoting it
|
|
298
|
+
* to `ActionDef` — the one shape the ruling forbids for it. A diagnostic that
|
|
299
|
+
* fires on the product's own privileged path is how a console gets muted.
|
|
300
|
+
*
|
|
301
|
+
* {@link HOST_STASHED_PARAM_KEYS} below is the same category one level down —
|
|
302
|
+
* host-composed keys inside `params` rather than on the action itself — and
|
|
303
|
+
* cites `DeclaredActionsBar` by name for the same reason this does. Two lists
|
|
304
|
+
* because the two warnings ask different questions of different objects, not
|
|
305
|
+
* because the categories differ.
|
|
306
|
+
*
|
|
307
|
+
* `overrideNotice` — the privileged-override safety copy (objectui#5178),
|
|
308
|
+
* naming the approvers about to be bypassed.
|
|
309
|
+
* - producer: `packages/app-shell/src/views/DeclaredActionsBar.tsx`, on the
|
|
310
|
+
* `can_act:false && can_override:true` branch.
|
|
311
|
+
* - readers: `packages/app-shell/src/hooks/useConsoleActionRuntime.tsx` and
|
|
312
|
+
* `packages/app-shell/src/views/RecordDetailView.tsx`, the console's two
|
|
313
|
+
* param-collection handlers, which render it ahead of the declared
|
|
314
|
+
* description in the dialog's subtitle.
|
|
315
|
+
*
|
|
316
|
+
* Anything added here must satisfy all three of: composed by a host in code,
|
|
317
|
+
* never read back out of stored metadata, and read by the runtime. A key an
|
|
318
|
+
* AUTHOR is meant to write belongs on `ActionDef` — or, when the spec owns it,
|
|
319
|
+
* in `@objectstack/spec` first — and not in this list. `actionKeys.pin.test.ts`
|
|
320
|
+
* pins the contents exactly, so growing the set is a deliberate, reviewed edit
|
|
321
|
+
* rather than a quiet one.
|
|
322
|
+
*/
|
|
323
|
+
export const HOST_DISPATCH_ACTION_KEYS = ['overrideNotice'];
|
|
212
324
|
/**
|
|
213
325
|
* Keys the spec has TOMBSTONED: still present in `ActionSchema` so the parser can
|
|
214
326
|
* reject them BY NAME with a rename prescription, rather than fail with a bare
|
|
@@ -217,19 +329,36 @@ export const NAVIGATION_ALIAS_KEYS = ['to', 'external', 'newTab', 'replace'];
|
|
|
217
329
|
* Warned about separately from unknown keys, and more loudly: an unknown key is
|
|
218
330
|
* probably a typo, while a retired key is metadata that used to work. That
|
|
219
331
|
* distinction is why `executeScript` carries a runtime branch returning the
|
|
220
|
-
* rename prescription
|
|
221
|
-
*
|
|
332
|
+
* rename prescription.
|
|
333
|
+
*
|
|
334
|
+
* Step 1 expected that branch to retire with the index signature. It does not,
|
|
335
|
+
* and the reason is the one in this module's header: `tsc` closed the
|
|
336
|
+
* code-authored half of the gap, while `execute: 'markDone'` lives in stored
|
|
337
|
+
* rows that reach the runner UNPARSED (objectstack#3903). The branch reads the
|
|
338
|
+
* key off an untyped view of the action precisely so that `ActionDef` can go on
|
|
339
|
+
* NOT declaring it — declaring it to make the read compile would re-legitimize
|
|
340
|
+
* a tombstone the spec keeps only in order to reject it by name.
|
|
222
341
|
*/
|
|
223
342
|
export const RETIRED_ACTION_KEYS = {
|
|
224
343
|
execute: '`execute` was removed in @objectstack/spec 17 (#3855) — rename the key to `target`. ' +
|
|
225
344
|
'The value (a script name or expression) is unchanged. ' +
|
|
226
345
|
'Run `os migrate meta --from 16` to rewrite it automatically.',
|
|
227
346
|
};
|
|
228
|
-
/**
|
|
347
|
+
/**
|
|
348
|
+
* Every key an action may legitimately carry today — authored or host-composed.
|
|
349
|
+
*
|
|
350
|
+
* Four inputs, three of them mirrors of an authored surface and the fourth
|
|
351
|
+
* ({@link HOST_DISPATCH_ACTION_KEYS}) the host-composed dispatch chrome. The
|
|
352
|
+
* union is what `classifyActionKeys` consults, and it is deliberately wider
|
|
353
|
+
* than the authored surface: the runner classifies the object it was HANDED,
|
|
354
|
+
* and a host hands it a dispatch. Membership here grants nothing to an author —
|
|
355
|
+
* `ActionDef` is what decides that, and it is closed.
|
|
356
|
+
*/
|
|
229
357
|
export const KNOWN_ACTION_KEYS = new Set([
|
|
230
358
|
...ACTION_DEF_KEYS,
|
|
231
359
|
...SPEC_ACTION_KEYS,
|
|
232
360
|
...NAVIGATION_ALIAS_KEYS,
|
|
361
|
+
...HOST_DISPATCH_ACTION_KEYS,
|
|
233
362
|
].filter((key) => !(key in RETIRED_ACTION_KEYS)));
|
|
234
363
|
/** Split an action's own keys into the two things worth saying out loud. */
|
|
235
364
|
export function classifyActionKeys(action) {
|
|
@@ -264,9 +393,11 @@ const isDev = () => globalThis.process?.env?.NODE_ENV !==
|
|
|
264
393
|
* Dev-mode only: name the keys an action carries that no reader will ever look
|
|
265
394
|
* at. Non-breaking by construction — it changes no types and rejects nothing.
|
|
266
395
|
*
|
|
267
|
-
* Silently binding no handler is the #2169 "Mark Done does nothing" shape
|
|
268
|
-
*
|
|
269
|
-
*
|
|
396
|
+
* Silently binding no handler is the #2169 "Mark Done does nothing" shape. The
|
|
397
|
+
* compiler now catches it in action literals AUTHORED IN CODE — objectstack#4075
|
|
398
|
+
* step 3 closed `ActionDef` — but not in the actions that arrive as DATA, which
|
|
399
|
+
* reach the runner unparsed and which no compiler ever looked at. This is the
|
|
400
|
+
* audible half for that population; see this module's header.
|
|
270
401
|
*/
|
|
271
402
|
export function warnOnUnknownActionKeys(action, where = 'ActionRunner') {
|
|
272
403
|
if (!isDev())
|
|
@@ -289,6 +420,86 @@ export function warnOnUnknownActionKeys(action, where = 'ActionRunner') {
|
|
|
289
420
|
console.warn(`[${where}] action "${String(name)}" carries ${unknown.length === 1 ? 'a key' : 'keys'} no reader ` +
|
|
290
421
|
`recognizes: \`${unknown.join('`, `')}\`. Nothing will read ${unknown.length === 1 ? 'it' : 'them'} — ` +
|
|
291
422
|
'check for a typo, or promote the key to an explicit field on `ActionDef` ' +
|
|
292
|
-
'(packages/core/src/actions/
|
|
293
|
-
'
|
|
423
|
+
'(packages/core/src/actions/ActionRunner.ts), adding it to `ACTION_DEF_KEYS` ' +
|
|
424
|
+
'(packages/core/src/actions/actionKeys.ts) in the SAME commit — the pin test derives one ' +
|
|
425
|
+
'from the other, so either edit alone goes red. Warned rather than rejected because `tsc` ' +
|
|
426
|
+
'only sees actions authored in code: this one may have arrived as DATA, and stored ' +
|
|
427
|
+
'`sys_metadata` rows reach the runner unparsed (objectstack#3903).');
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Keys a HOST stashes into an action's `params` for the runner's own plumbing,
|
|
431
|
+
* rather than an author writing them there as a request payload.
|
|
432
|
+
*
|
|
433
|
+
* {@link warnOnDeprecatedObjectParams} has to tell "the author put the payload in
|
|
434
|
+
* `params`" (the shape objectstack#5777 retires) apart from "a host stashed row
|
|
435
|
+
* context there" (a shape the runner itself asks for, and that is not going
|
|
436
|
+
* away). `DeclaredActionsBar` dispatches `params: { _rowRecord: record }`,
|
|
437
|
+
* `RelatedRecordActionsBridge` does the same, and `ObjectGrid` adds
|
|
438
|
+
* `_selectedIds`; the api handler lifts `recordId` out of the field values
|
|
439
|
+
* before it updates. Warning on those would fire on nearly every declared-action
|
|
440
|
+
* click and prescribe `bodyExtra`, which is the wrong home for all of them.
|
|
441
|
+
*
|
|
442
|
+
* The `_` prefix is the existing convention for the stash — `recordId` is its one
|
|
443
|
+
* unprefixed member, so it is listed rather than inferred.
|
|
444
|
+
*/
|
|
445
|
+
const HOST_STASHED_PARAM_KEYS = new Set(['recordId']);
|
|
446
|
+
const isAuthoredParamKey = (key) => !key.startsWith('_') && !HOST_STASHED_PARAM_KEYS.has(key);
|
|
447
|
+
/**
|
|
448
|
+
* Does this action carry the DEPRECATED object-form `params` — a static request
|
|
449
|
+
* payload written under the key that means "parameter definitions"?
|
|
450
|
+
*
|
|
451
|
+
* The discriminator is `Array.isArray` and the type guard is `api`, mirroring
|
|
452
|
+
* `@objectstack/spec`'s `inline-action-api-params-to-body-extra` conversion
|
|
453
|
+
* (ADR-0087 D2) key for key. Contract parity with the producer is the point: the
|
|
454
|
+
* conversion rewrites exactly this shape to `bodyExtra` at load, so the runner
|
|
455
|
+
* must recognize exactly the same shape as "the thing that got rewritten".
|
|
456
|
+
*
|
|
457
|
+
* The `api` guard is also what keeps the deprecation out of objectstack#6828's
|
|
458
|
+
* territory — object-form `params` on a `type: 'url'` action is a THIRD meaning
|
|
459
|
+
* (`interpolateTarget`'s `${param.X}` scope, `executeUrl`'s `params.newTab`) and
|
|
460
|
+
* `bodyExtra` is NOT its replacement. Do not widen this guard without that
|
|
461
|
+
* ruling.
|
|
462
|
+
*/
|
|
463
|
+
export function hasDeprecatedObjectParams(action) {
|
|
464
|
+
if (!action || typeof action !== 'object')
|
|
465
|
+
return false;
|
|
466
|
+
const { type, actionType, params } = action;
|
|
467
|
+
if ((type ?? actionType) !== 'api')
|
|
468
|
+
return false;
|
|
469
|
+
if (!params || typeof params !== 'object' || Array.isArray(params))
|
|
470
|
+
return false;
|
|
471
|
+
return Object.keys(params).some(isAuthoredParamKey);
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Dev-mode only: name the object-form `params` that `@objectstack/spec` 17 already
|
|
475
|
+
* refuses at the authoring door, and prescribe `bodyExtra`.
|
|
476
|
+
*
|
|
477
|
+
* This is the audible half of the compat window the maintainer's 2026-08-06
|
|
478
|
+
* ruling on objectstack#5777 ordered (direction A — a separate key, no same-name
|
|
479
|
+
* union): the runner keeps READING a non-array `params` as the static payload for
|
|
480
|
+
* one version window, says so, and the arm is deleted at 18. The loud half lives
|
|
481
|
+
* at the producer, where it belongs — spec's `params` field refuses the object
|
|
482
|
+
* form outright with a message naming `bodyExtra`, and the ADR-0087 conversion
|
|
483
|
+
* rewrites sources that still carry it. So a warning is the correct severity
|
|
484
|
+
* HERE: by the time metadata reaches this runner the producer has already had its
|
|
485
|
+
* say, and what is left to catch is a host composing an ActionDef in code.
|
|
486
|
+
*
|
|
487
|
+
* Dev-only and warn-once, matching {@link warnOnUnknownActionKeys} — a warning
|
|
488
|
+
* that floods a production console is a warning that gets muted.
|
|
489
|
+
*/
|
|
490
|
+
export function warnOnDeprecatedObjectParams(action, where = 'ActionRunner') {
|
|
491
|
+
if (!isDev())
|
|
492
|
+
return;
|
|
493
|
+
if (!hasDeprecatedObjectParams(action))
|
|
494
|
+
return;
|
|
495
|
+
const name = action?.name ?? '(unnamed)';
|
|
496
|
+
const memo = `deprecated-object-params:${String(name)}`;
|
|
497
|
+
if (warned.has(memo))
|
|
498
|
+
return;
|
|
499
|
+
warned.add(memo);
|
|
500
|
+
console.warn(`[${where}] action "${String(name)}" carries a static request payload in \`params\`. ` +
|
|
501
|
+
'`params` is the parameter DEFINITION array (fields collected from the user before the ' +
|
|
502
|
+
'action runs), never a payload map — put the payload in `bodyExtra` instead ' +
|
|
503
|
+
'(objectstack#5777). Still read as the payload for one version window; the arm is ' +
|
|
504
|
+
'removed at 18. `bodyExtra` is merged LAST, so it overrides anything left here.');
|
|
294
505
|
}
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
* - **transport-level `success: false`** — the outer envelope reporting a
|
|
48
48
|
* failure directly.
|
|
49
49
|
*/
|
|
50
|
-
import { actionErrorDetail } from './actionErrorDetail';
|
|
50
|
+
import { actionErrorDetail } from './actionErrorDetail.js';
|
|
51
51
|
/**
|
|
52
52
|
* The handler's own return value — one level deeper than the action envelope.
|
|
53
53
|
*
|
package/dist/actions/index.d.ts
CHANGED
package/dist/actions/index.js
CHANGED