@object-ui/core 17.6.0 → 18.0.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 +7260 -0
- package/README.md +228 -14
- package/dist/actions/ActionEngine.d.ts +4 -2
- package/dist/actions/ActionEngine.js +13 -8
- package/dist/actions/ActionRunner.d.ts +473 -69
- package/dist/actions/ActionRunner.js +792 -125
- package/dist/actions/TransactionManager.d.ts +7 -2
- package/dist/actions/UndoManager.d.ts +8 -13
- package/dist/actions/actionKeys.d.ts +9 -7
- package/dist/actions/actionKeys.js +67 -14
- package/dist/actions/actionResponse.js +2 -2
- package/dist/actions/index.d.ts +2 -0
- package/dist/actions/index.js +2 -0
- package/dist/actions/navigationTarget.d.ts +41 -0
- package/dist/actions/navigationTarget.js +20 -0
- package/dist/actions/recordDelete.d.ts +154 -0
- package/dist/actions/recordDelete.js +110 -0
- package/dist/adapters/ApiDataSource.d.ts +8 -4
- package/dist/adapters/ApiDataSource.js +19 -7
- package/dist/adapters/ValueDataSource.d.ts +6 -1
- package/dist/adapters/ValueDataSource.js +1090 -98
- package/dist/adapters/batchTransaction.d.ts +1 -1
- package/dist/adapters/batchTransaction.js +1 -1
- package/dist/adapters/resolveDataSource.d.ts +9 -6
- package/dist/adapters/resolveDataSource.js +9 -12
- package/dist/builder/schema-builder.d.ts +38 -81
- package/dist/builder/schema-builder.js +33 -152
- package/dist/data-scope/ViewDataProvider.d.ts +8 -25
- package/dist/data-scope/ViewDataProvider.js +27 -54
- package/dist/data-scope/element-data-source.d.ts +261 -7
- package/dist/data-scope/element-data-source.js +342 -52
- package/dist/data-scope/index.d.ts +9 -4
- package/dist/data-scope/index.js +9 -4
- package/dist/evaluator/ExpressionEvaluator.d.ts +86 -0
- package/dist/evaluator/ExpressionEvaluator.js +184 -12
- package/dist/evaluator/FormulaFunctions.d.ts +0 -10
- package/dist/evaluator/FormulaFunctions.js +166 -27
- package/dist/evaluator/deadlineSettled.d.ts +40 -0
- package/dist/evaluator/deadlineSettled.js +45 -0
- package/dist/evaluator/declaredPredicate.d.ts +93 -9
- package/dist/evaluator/declaredPredicate.js +117 -16
- package/dist/evaluator/fieldRules.d.ts +88 -4
- package/dist/evaluator/fieldRules.js +208 -31
- package/dist/evaluator/index.d.ts +2 -0
- package/dist/evaluator/index.js +2 -0
- package/dist/evaluator/listConditional.d.ts +103 -34
- package/dist/evaluator/listConditional.js +127 -50
- package/dist/evaluator/optionRules.d.ts +77 -6
- package/dist/evaluator/optionRules.js +87 -10
- package/dist/evaluator/predicateInput.d.ts +15 -4
- package/dist/evaluator/predicateInput.js +35 -2
- package/dist/evaluator/rowPredicateCanon.d.ts +7 -18
- package/dist/evaluator/rowPredicateCanon.js +65 -115
- package/dist/evaluator/subjectPermissions.d.ts +105 -0
- package/dist/evaluator/subjectPermissions.js +86 -0
- package/dist/evaluator/unevaluablePredicate.d.ts +57 -0
- package/dist/evaluator/unevaluablePredicate.js +70 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +83 -2
- package/dist/protocols/index.d.ts +0 -1
- package/dist/protocols/index.js +9 -1
- package/dist/registry/Registry.d.ts +382 -34
- package/dist/registry/Registry.js +247 -12
- package/dist/registry/WidgetRegistry.js +7 -3
- package/dist/registry/html-tier-intrinsics.d.ts +90 -0
- package/dist/registry/html-tier-intrinsics.js +110 -0
- package/dist/registry/public-blocks.d.ts +8 -0
- package/dist/registry/public-blocks.js +57 -0
- package/dist/theme/ThemeEngine.js +1 -1
- package/dist/utils/affordanceGrants.d.ts +371 -0
- package/dist/utils/affordanceGrants.js +252 -0
- package/dist/utils/chart-category-key.d.ts +82 -0
- package/dist/utils/chart-category-key.js +84 -0
- package/dist/utils/chart-measure-key.d.ts +64 -0
- package/dist/utils/chart-measure-key.js +65 -0
- package/dist/utils/chart-presentation.d.ts +95 -112
- package/dist/utils/chart-presentation.js +169 -104
- package/dist/utils/chart-series.d.ts +165 -5
- package/dist/utils/chart-series.js +123 -18
- package/dist/utils/column-sortability.d.ts +157 -0
- package/dist/utils/column-sortability.js +217 -0
- package/dist/utils/dashboard-filters.d.ts +38 -6
- package/dist/utils/dashboard-filters.js +107 -61
- package/dist/utils/dataset-format.d.ts +211 -30
- package/dist/utils/dataset-format.js +389 -46
- package/dist/utils/date-display.d.ts +346 -0
- package/dist/utils/date-display.js +644 -0
- package/dist/utils/date-macros.js +7 -0
- package/dist/utils/drill-down.d.ts +78 -0
- package/dist/utils/drill-down.js +93 -0
- package/dist/utils/emptiness.d.ts +96 -0
- package/dist/utils/emptiness.js +101 -0
- package/dist/utils/expand-fields.d.ts +81 -9
- package/dist/utils/expand-fields.js +81 -9
- package/dist/utils/extract-records.d.ts +65 -5
- package/dist/utils/extract-records.js +65 -8
- package/dist/utils/filter-converter.d.ts +158 -6
- package/dist/utils/filter-converter.js +1098 -24
- package/dist/utils/filter-tokens.d.ts +49 -5
- package/dist/utils/filter-tokens.js +105 -33
- package/dist/utils/grouping-fields.d.ts +61 -0
- package/dist/utils/grouping-fields.js +84 -0
- package/dist/utils/managedBy.d.ts +3 -3
- package/dist/utils/managedBy.js +5 -5
- package/dist/utils/native-date-value.d.ts +48 -0
- package/dist/utils/native-date-value.js +167 -0
- package/dist/utils/non-grid-row-ceiling.d.ts +143 -0
- package/dist/utils/non-grid-row-ceiling.js +141 -0
- package/dist/utils/normalize-list-view.d.ts +135 -11
- package/dist/utils/normalize-list-view.js +243 -64
- package/dist/utils/number-display.d.ts +63 -14
- package/dist/utils/number-display.js +34 -12
- package/dist/utils/object-aggregate-query.d.ts +113 -0
- package/dist/utils/object-aggregate-query.js +50 -0
- package/dist/utils/parent-scope.d.ts +123 -0
- package/dist/utils/parent-scope.js +140 -0
- package/dist/utils/predicate-fields.d.ts +45 -12
- package/dist/utils/predicate-fields.js +141 -12
- package/dist/utils/record-color.d.ts +75 -0
- package/dist/utils/record-color.js +65 -0
- package/dist/utils/record-source.d.ts +298 -0
- package/dist/utils/record-source.js +331 -0
- package/dist/utils/record-title.d.ts +148 -8
- package/dist/utils/record-title.js +220 -26
- package/dist/utils/reference-keys.d.ts +21 -22
- package/dist/utils/reference-keys.js +532 -29
- package/dist/utils/sort-query.d.ts +115 -15
- package/dist/utils/sort-query.js +240 -13
- package/dist/utils/text-comparand.d.ts +92 -0
- package/dist/utils/text-comparand.js +99 -0
- package/dist/utils/without-denied-fields.d.ts +49 -0
- package/dist/utils/without-denied-fields.js +52 -0
- package/dist/validation/index.d.ts +8 -4
- package/dist/validation/index.js +8 -4
- package/dist/validation/schema-validator.d.ts +1 -1
- package/dist/validation/schema-validator.js +225 -83
- package/dist/validation/server-owned-value.d.ts +5 -1
- package/dist/validation/server-owned-value.js +5 -1
- package/dist/validation/validators/object-validation-engine.d.ts +1 -1
- package/dist/validation/validators/object-validation-engine.js +14 -3
- package/package.json +8 -9
- package/dist/data-scope/DataScopeManager.d.ts +0 -127
- package/dist/data-scope/DataScopeManager.js +0 -229
- package/dist/protocols/ResponsiveProtocol.d.ts +0 -73
- package/dist/protocols/ResponsiveProtocol.js +0 -158
- package/dist/validation/validation-engine.d.ts +0 -88
- package/dist/validation/validation-engine.js +0 -434
|
@@ -24,8 +24,13 @@ export interface TransactionOperation {
|
|
|
24
24
|
type: 'create' | 'update' | 'delete';
|
|
25
25
|
/** Target resource name */
|
|
26
26
|
resource: string;
|
|
27
|
-
/**
|
|
28
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Record ID (for update/delete). A `string`, as `@objectstack/spec` declares
|
|
29
|
+
* every record door and as this type's own sibling `BatchTransactionOperation.id`
|
|
30
|
+
* already did; the rollback path hands it straight to `DataSource.update`
|
|
31
|
+
* (objectui#9333).
|
|
32
|
+
*/
|
|
33
|
+
id?: string;
|
|
29
34
|
/** Data payload */
|
|
30
35
|
data?: Record<string, any>;
|
|
31
36
|
/** Previous state (for rollback) */
|
|
@@ -12,19 +12,14 @@
|
|
|
12
12
|
* pattern for use from ActionRunner, React hooks, and standalone contexts.
|
|
13
13
|
* Maintains bounded history stacks with subscriber notifications.
|
|
14
14
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
/** Data needed to undo: for create=recordId, for update=previousData, for delete=fullRecord */
|
|
24
|
-
undoData: Record<string, unknown>;
|
|
25
|
-
/** Data needed to redo: for create=newData, for update=newData, for delete=recordId */
|
|
26
|
-
redoData: Record<string, unknown>;
|
|
27
|
-
}
|
|
15
|
+
import type { UndoableOperation } from '@object-ui/types';
|
|
16
|
+
/**
|
|
17
|
+
* A single undoable CRUD operation — declared once, in `@object-ui/types`
|
|
18
|
+
* (objectui#6349, batch 4), beside the `ActionResult` whose `undo` member it
|
|
19
|
+
* types, and re-exported here so an import from `@object-ui/core` keeps
|
|
20
|
+
* resolving to the same type.
|
|
21
|
+
*/
|
|
22
|
+
export type { UndoableOperation } from '@object-ui/types';
|
|
28
23
|
export interface UndoManagerOptions {
|
|
29
24
|
/** Maximum number of operations to retain in history. @default 50 */
|
|
30
25
|
maxHistory?: number;
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*
|
|
19
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
|
-
* sail through to a runner that then silently does nothing — the #2169 "Mark
|
|
21
|
+
* sail through to a runner that then silently does nothing — the objectstack-ai/objectstack#2169 "Mark
|
|
22
22
|
* Done does nothing" shape.
|
|
23
23
|
*
|
|
24
24
|
* This module was step 1 of the staged narrowing: make the key set VISIBLE and
|
|
@@ -74,10 +74,12 @@
|
|
|
74
74
|
* rejection" into a compile error at no cost. Hand-copying would have quietly
|
|
75
75
|
* re-legitimized two dead keys — which is why the types are derived.
|
|
76
76
|
*
|
|
77
|
-
*
|
|
77
|
+
* 16 keys `ActionDef` declares that the spec does not own — `actionType`, `api`,
|
|
78
78
|
* `chain`, `chainMode`, `close`, `condition`, `confirm`, `endpoint`, `modal`,
|
|
79
|
-
* `navigate`, `onClick`, `onFailure`, `
|
|
80
|
-
* `actionParams`.
|
|
79
|
+
* `navigate`, `onClick`, `onFailure`, `redirect`, `reload`, `toast`,
|
|
80
|
+
* `actionParams`. (`onSuccess` was the 17th until objectui#5934 retired the
|
|
81
|
+
* runner's chained-callback meaning; the key is now spec-owned and derived,
|
|
82
|
+
* like the 18 below.) Step 2 marked `@deprecated`, with the spec spelling to use
|
|
81
83
|
* instead, ONLY the four the runner itself proves are aliases: `actionType` (→
|
|
82
84
|
* `type`), `api` and `endpoint` (→ `target`; `executeAPI` resolves
|
|
83
85
|
* `api || endpoint || target`), and `navigate` (→ flat `target`/`openIn`;
|
|
@@ -111,7 +113,7 @@
|
|
|
111
113
|
* classifier a list of anything. `actionKeys.pin.test.ts` re-derives this one
|
|
112
114
|
* from the interface's AST, which is what keeps the data true.
|
|
113
115
|
*/
|
|
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", "
|
|
116
|
+
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", "onFailure", "opensInNewTab", "newTabUrl", "locations", "visible", "requiredPermissions", "icon", "variant", "order", "component", "objectName", "ai", "bodyExtra", "bodyShape", "operation", "patch", "mode", "recordIdField", "recordIdParam", "requiresFeature", "onSuccess", "outcomeMessages", "shortcut", "bulkEnabled"];
|
|
115
117
|
/**
|
|
116
118
|
* Every property `@objectstack/spec`'s `ActionSchema` declares.
|
|
117
119
|
*
|
|
@@ -126,7 +128,7 @@ export declare const ACTION_DEF_KEYS: readonly ["type", "actionType", "name", "l
|
|
|
126
128
|
* test and wrong in shipped code — `@object-ui/types` made the same call for
|
|
127
129
|
* `ActionComponent`. The pin test does the walk and fails the day this drifts.
|
|
128
130
|
*/
|
|
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"];
|
|
131
|
+
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", "execution", "icon", "label", "locations", "method", "mode", "name", "newTabUrl", "objectName", "onSuccess", "openIn", "opensInNewTab", "operation", "order", "outcomeMessages", "params", "patch", "recordIdField", "recordIdParam", "refreshAfter", "requiredPermissions", "requiresFeature", "requiresMembershipReach", "resultDialog", "shortcut", "successMessage", "target", "type", "undoable", "variant", "visible"];
|
|
130
132
|
/**
|
|
131
133
|
* The `navigation` alias's own spelling of a target, read off the action itself
|
|
132
134
|
* when no nested `navigate` object is present (`ActionRunner.executeNavigation`).
|
|
@@ -227,7 +229,7 @@ export declare function resetActionKeyWarnings(): void;
|
|
|
227
229
|
* Dev-mode only: name the keys an action carries that no reader will ever look
|
|
228
230
|
* at. Non-breaking by construction — it changes no types and rejects nothing.
|
|
229
231
|
*
|
|
230
|
-
* Silently binding no handler is the #2169 "Mark Done does nothing" shape. The
|
|
232
|
+
* Silently binding no handler is the objectstack-ai/objectstack#2169 "Mark Done does nothing" shape. The
|
|
231
233
|
* compiler now catches it in action literals AUTHORED IN CODE — objectstack#4075
|
|
232
234
|
* step 3 closed `ActionDef` — but not in the actions that arrive as DATA, which
|
|
233
235
|
* reach the runner unparsed and which no compiler ever looked at. This is the
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*
|
|
19
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
|
-
* sail through to a runner that then silently does nothing — the #2169 "Mark
|
|
21
|
+
* sail through to a runner that then silently does nothing — the objectstack-ai/objectstack#2169 "Mark
|
|
22
22
|
* Done does nothing" shape.
|
|
23
23
|
*
|
|
24
24
|
* This module was step 1 of the staged narrowing: make the key set VISIBLE and
|
|
@@ -74,10 +74,12 @@
|
|
|
74
74
|
* rejection" into a compile error at no cost. Hand-copying would have quietly
|
|
75
75
|
* re-legitimized two dead keys — which is why the types are derived.
|
|
76
76
|
*
|
|
77
|
-
*
|
|
77
|
+
* 16 keys `ActionDef` declares that the spec does not own — `actionType`, `api`,
|
|
78
78
|
* `chain`, `chainMode`, `close`, `condition`, `confirm`, `endpoint`, `modal`,
|
|
79
|
-
* `navigate`, `onClick`, `onFailure`, `
|
|
80
|
-
* `actionParams`.
|
|
79
|
+
* `navigate`, `onClick`, `onFailure`, `redirect`, `reload`, `toast`,
|
|
80
|
+
* `actionParams`. (`onSuccess` was the 17th until objectui#5934 retired the
|
|
81
|
+
* runner's chained-callback meaning; the key is now spec-owned and derived,
|
|
82
|
+
* like the 18 below.) Step 2 marked `@deprecated`, with the spec spelling to use
|
|
81
83
|
* instead, ONLY the four the runner itself proves are aliases: `actionType` (→
|
|
82
84
|
* `type`), `api` and `endpoint` (→ `target`; `executeAPI` resolves
|
|
83
85
|
* `api || endpoint || target`), and `navigate` (→ flat `target`/`openIn`;
|
|
@@ -154,7 +156,6 @@ export const ACTION_DEF_KEYS = [
|
|
|
154
156
|
'modal',
|
|
155
157
|
'chain',
|
|
156
158
|
'chainMode',
|
|
157
|
-
'onSuccess',
|
|
158
159
|
'onFailure',
|
|
159
160
|
'opensInNewTab',
|
|
160
161
|
'newTabUrl',
|
|
@@ -172,13 +173,30 @@ export const ACTION_DEF_KEYS = [
|
|
|
172
173
|
'component',
|
|
173
174
|
'objectName',
|
|
174
175
|
'ai',
|
|
175
|
-
|
|
176
|
+
// `aria` left this list, with its `ActionDef` field, when `@objectstack/spec`
|
|
177
|
+
// 17.5.0 retired `action.aria` as a `retiredKey()` tombstone (objectui#10929):
|
|
178
|
+
// the derived type had become `undefined`, so the field mirrored nothing. It
|
|
179
|
+
// stays in `SPEC_ACTION_KEYS` below, because `ActionSchema` still declares the
|
|
180
|
+
// tombstone.
|
|
176
181
|
'bodyExtra',
|
|
177
182
|
'bodyShape',
|
|
183
|
+
// The declarative single-record field write (spec 17.3.0). Promoted from
|
|
184
|
+
// inventory-only to declared `ActionDef` fields when the runner learned to
|
|
185
|
+
// read them — the branch that dispatches `operation: 'update'` on the
|
|
186
|
+
// platform action route, ahead of `type`.
|
|
187
|
+
'operation',
|
|
188
|
+
'patch',
|
|
178
189
|
'mode',
|
|
179
190
|
'recordIdField',
|
|
180
191
|
'recordIdParam',
|
|
181
192
|
'requiresFeature',
|
|
193
|
+
// Moved from the runner-native cluster above by objectui#5934: the legacy
|
|
194
|
+
// chained-callback meaning is retired and the key's type now derives the
|
|
195
|
+
// spec's `{ navigate, openIn }` block.
|
|
196
|
+
'onSuccess',
|
|
197
|
+
// Spec 17.6.0's success copy per handler outcome (objectui#11344), declared
|
|
198
|
+
// when the runner learned to read it: the success toast's first rung.
|
|
199
|
+
'outcomeMessages',
|
|
182
200
|
'shortcut',
|
|
183
201
|
'bulkEnabled',
|
|
184
202
|
];
|
|
@@ -228,6 +246,14 @@ export const SPEC_ACTION_KEYS = [
|
|
|
228
246
|
'disabled',
|
|
229
247
|
'errorMessage',
|
|
230
248
|
'execute',
|
|
249
|
+
// Added to `ActionSchema` in @objectstack/spec 17.5.0 (objectui#11073): the
|
|
250
|
+
// bulk dispatch contract the action's body is written for, in
|
|
251
|
+
// `bulkActionDefs`' own `'perRecord' | 'aggregate'` vocabulary. Listed for the
|
|
252
|
+
// reason `description` is — this array restates the spec's declared keys, so
|
|
253
|
+
// an action carrying it is not reported as having an unknown key. `ActionDef`
|
|
254
|
+
// does NOT declare it and the runner does not read it: the spec's own
|
|
255
|
+
// enforcement is `@objectstack/lint`'s authoring-time check.
|
|
256
|
+
'execution',
|
|
231
257
|
'icon',
|
|
232
258
|
'label',
|
|
233
259
|
'locations',
|
|
@@ -237,22 +263,49 @@ export const SPEC_ACTION_KEYS = [
|
|
|
237
263
|
'newTabUrl',
|
|
238
264
|
'objectName',
|
|
239
265
|
// Declared by `ActionSchema` as of @objectstack/spec 17.1.0 (objectui#5328).
|
|
240
|
-
//
|
|
241
|
-
// `
|
|
242
|
-
//
|
|
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.
|
|
266
|
+
// All four declared action surfaces forward it since objectui#5493/#6304, and
|
|
267
|
+
// `ActionDef` derives its type from the spec since objectui#5934 retired the
|
|
268
|
+
// runner's legacy chained-callback meaning for the same key.
|
|
246
269
|
'onSuccess',
|
|
247
270
|
'openIn',
|
|
248
271
|
'opensInNewTab',
|
|
272
|
+
// Added to `ActionSchema` in @objectstack/spec 17.3.0 (objectui#7122), the
|
|
273
|
+
// declarative single-record field write that mirrors a list view's
|
|
274
|
+
// `bulkActionDefs`: `operation: 'update'` applies `patch` (merged UNDER the
|
|
275
|
+
// collected `params`) to the current record on the data plane AS THE CALLER.
|
|
276
|
+
//
|
|
277
|
+
// Both keys were inventory-ONLY when that bump landed, under the maintainer's
|
|
278
|
+
// 2026-09-05 ruling on it ("record both as justified omissions now; forward
|
|
279
|
+
// only the key a runtime actually reads, once its semantics are read from
|
|
280
|
+
// upstream — no speculative forwarding"). That condition is now met: the
|
|
281
|
+
// runner reads both (`executeUpdateOperation`, dispatched ahead of `type`),
|
|
282
|
+
// `ActionDef` declares both, and every action surface forwards them — which
|
|
283
|
+
// is what `check:action-forward-parity` now requires rather than excuses.
|
|
284
|
+
'operation',
|
|
249
285
|
'order',
|
|
286
|
+
// Added to `ActionSchema` in @objectstack/spec 17.6.0 (objectstack#21095,
|
|
287
|
+
// objectui#11344): success copy per handler outcome, keyed by the snake_case
|
|
288
|
+
// `outcome` the handler returns. `ActionDef` declares it (derived) and the
|
|
289
|
+
// runner reads it as the success toast's first rung, ahead of
|
|
290
|
+
// `successMessage`.
|
|
291
|
+
'outcomeMessages',
|
|
250
292
|
'params',
|
|
293
|
+
'patch',
|
|
251
294
|
'recordIdField',
|
|
252
295
|
'recordIdParam',
|
|
253
296
|
'refreshAfter',
|
|
254
297
|
'requiredPermissions',
|
|
255
298
|
'requiresFeature',
|
|
299
|
+
// Added to `ActionSchema` in @objectstack/spec 17.7.0 (objectui#11717): the
|
|
300
|
+
// organization endpoint (a `MEMBERSHIP_REACH` row) whose membership-grade gate
|
|
301
|
+
// the action follows, which the spec's parse LOWERS into `visible` over
|
|
302
|
+
// `current_user.positions` (the same transform that lowers `requiresFeature`
|
|
303
|
+
// above). Listed for the reason `description` is — this array restates the
|
|
304
|
+
// spec's declared keys, so an action carrying it is not reported as having an
|
|
305
|
+
// unknown key. `ActionDef` does NOT declare it and the runner does not read
|
|
306
|
+
// it; whether it should, beside `requiresFeature`, is not this inventory's
|
|
307
|
+
// question.
|
|
308
|
+
'requiresMembershipReach',
|
|
256
309
|
'resultDialog',
|
|
257
310
|
'shortcut',
|
|
258
311
|
'successMessage',
|
|
@@ -340,7 +393,7 @@ export const HOST_DISPATCH_ACTION_KEYS = ['overrideNotice'];
|
|
|
340
393
|
* a tombstone the spec keeps only in order to reject it by name.
|
|
341
394
|
*/
|
|
342
395
|
export const RETIRED_ACTION_KEYS = {
|
|
343
|
-
execute: '`execute` was removed in @objectstack/spec 17 (#3855) — rename the key to `target`. ' +
|
|
396
|
+
execute: '`execute` was removed in @objectstack/spec 17 (objectstack-ai/objectstack#3855) — rename the key to `target`. ' +
|
|
344
397
|
'The value (a script name or expression) is unchanged. ' +
|
|
345
398
|
'Run `os migrate meta --from 16` to rewrite it automatically.',
|
|
346
399
|
};
|
|
@@ -393,7 +446,7 @@ const isDev = () => globalThis.process?.env?.NODE_ENV !==
|
|
|
393
446
|
* Dev-mode only: name the keys an action carries that no reader will ever look
|
|
394
447
|
* at. Non-breaking by construction — it changes no types and rejects nothing.
|
|
395
448
|
*
|
|
396
|
-
* Silently binding no handler is the #2169 "Mark Done does nothing" shape. The
|
|
449
|
+
* Silently binding no handler is the objectstack-ai/objectstack#2169 "Mark Done does nothing" shape. The
|
|
397
450
|
* compiler now catches it in action literals AUTHORED IN CODE — objectstack#4075
|
|
398
451
|
* step 3 closed `ActionDef` — but not in the actions that arrive as DATA, which
|
|
399
452
|
* reach the runner unparsed and which no compiler ever looked at. This is the
|
|
@@ -59,7 +59,7 @@ import { actionErrorDetail } from './actionErrorDetail.js';
|
|
|
59
59
|
export function readActionPayload(envelope) {
|
|
60
60
|
// objectstack#3962 servers single-wrap: `body.data` IS the handler value,
|
|
61
61
|
// so most of the time this is the identity function. Only the exact LEGACY
|
|
62
|
-
// action envelope (pre
|
|
62
|
+
// action envelope (pre-objectstack-ai/objectstack#3962: a boolean `success` and no keys beyond the
|
|
63
63
|
// envelope's own) is unwrapped one more level — a handler value that
|
|
64
64
|
// merely contains a `success` key passes through untouched.
|
|
65
65
|
if (isLegacyActionEnvelope(envelope)) {
|
|
@@ -82,7 +82,7 @@ export function isLegacyActionEnvelope(v) {
|
|
|
82
82
|
*/
|
|
83
83
|
export function interpretActionResponse(res, json, label) {
|
|
84
84
|
const envelope = json?.data;
|
|
85
|
-
// Pre
|
|
85
|
+
// Pre-objectstack-ai/objectstack#3962 servers reported a rejection as HTTP 200 with the inner
|
|
86
86
|
// `{success:false, error}`; current servers answer a real status, which
|
|
87
87
|
// `res.ok` catches first. Detected narrowly so a handler value that merely
|
|
88
88
|
// contains `success: false` is not misread as a failure.
|
package/dist/actions/index.d.ts
CHANGED
package/dist/actions/index.js
CHANGED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* What a click may navigate to, and how.
|
|
10
|
+
*
|
|
11
|
+
* This is the one answer, shared by every caller that turns an authored or
|
|
12
|
+
* served target into a user-click navigation (objectui#12191, ruling A+):
|
|
13
|
+
*
|
|
14
|
+
* - the action runner: a `type: 'url'` action, its `navigation` alias (which is
|
|
15
|
+
* how an `element:button` CTA reaches it) and `onSuccess.navigate`;
|
|
16
|
+
* - app-shell's entitlement CTA, `resolveCtaHref`.
|
|
17
|
+
*
|
|
18
|
+
* ⛔ No caller keeps a scheme list of its own. A second list is how the runner
|
|
19
|
+
* came to refuse the `mailto:` target the CTA already admitted, so a mail button
|
|
20
|
+
* the spec accepts published cleanly and then failed at click.
|
|
21
|
+
*
|
|
22
|
+
* The admitted set is closed:
|
|
23
|
+
*
|
|
24
|
+
* - `'web'`: `http://` or `https://`. It leaves the app. The caller's `openIn`
|
|
25
|
+
* decides the tab.
|
|
26
|
+
* - `'mail'`: `mailto:`. It leaves the app IN PLACE: never a new tab, and
|
|
27
|
+
* `openIn` is not consulted. The mail client opens and the page stays.
|
|
28
|
+
* - `'path'`: an in-app relative path, `/…` or `./…`.
|
|
29
|
+
*
|
|
30
|
+
* Everything else answers `null` and is refused: `javascript:`, `data:`, `tel:`
|
|
31
|
+
* (not admitted: no measured producer) and every other scheme, and a
|
|
32
|
+
* protocol-relative `//host`. Two other spellings of `//host` are refused with
|
|
33
|
+
* it, because the browser's URL parser reads them as `//host`: a backslash in
|
|
34
|
+
* second place (`/` then a backslash, then `host`), and any target that holds an
|
|
35
|
+
* ASCII tab, line feed or carriage return, since the parser deletes those three
|
|
36
|
+
* before it reads anything.
|
|
37
|
+
*
|
|
38
|
+
* Scheme names compare case-insensitively, as the URL parser compares them.
|
|
39
|
+
*/
|
|
40
|
+
export type NavigationTargetKind = 'web' | 'mail' | 'path';
|
|
41
|
+
export declare function classifyNavigationTarget(url: unknown): NavigationTargetKind | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
export function classifyNavigationTarget(url) {
|
|
9
|
+
if (typeof url !== 'string' || /[\t\n\r]/.test(url))
|
|
10
|
+
return null;
|
|
11
|
+
if (/^https?:\/\//i.test(url))
|
|
12
|
+
return 'web';
|
|
13
|
+
if (/^mailto:/i.test(url))
|
|
14
|
+
return 'mail';
|
|
15
|
+
if (url.startsWith('./'))
|
|
16
|
+
return 'path';
|
|
17
|
+
if (url.startsWith('/') && url[1] !== '/' && url[1] !== '\\')
|
|
18
|
+
return 'path';
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* The ONE record-delete core — the confirm question and the delete itself —
|
|
10
|
+
* that every host's list Delete binds to (objectui#10383).
|
|
11
|
+
*
|
|
12
|
+
* ## Why this lives here, and why there is only one
|
|
13
|
+
*
|
|
14
|
+
* The console's object list deleted through `useObjectActions` (`app-shell`):
|
|
15
|
+
* the confirm question, the single delete with its ADR-0094 detection, the bulk
|
|
16
|
+
* delete and their toasts were written inline in that hook. The registered
|
|
17
|
+
* `object-view` renderer (`plugin-view`) had no delete at all — its grid
|
|
18
|
+
* handlers only refreshed — and the first repair COPIED those steps into a
|
|
19
|
+
* second flow. The copy already diverged on consent: it asked every row the
|
|
20
|
+
* plain "delete this record?" question, while the console asked a package-owned
|
|
21
|
+
* permission set the reset question (that question went with the catalog
|
|
22
|
+
* objects, ADR-0131). One operation with two
|
|
23
|
+
* implementations drifts on exactly the part that matters, so the rule is: the
|
|
24
|
+
* side with the governance keeps it, the other side re-binds to it, and there
|
|
25
|
+
* is one copy. This module is that copy, and both hosts call it.
|
|
26
|
+
*
|
|
27
|
+
* `@object-ui/core` is the lowest package both hosts already depend on. The
|
|
28
|
+
* host-specific pieces are INJECTED — the translator, the toast sink, the data
|
|
29
|
+
* source and the refresh — so this package gains no i18n or toast dependency.
|
|
30
|
+
* The host keeps its own confirm UI (`app-shell` hands the copy to the console's
|
|
31
|
+
* confirm handler; `plugin-view` renders it in its own AlertDialog); the COPY —
|
|
32
|
+
* title, body and confirm-button label — comes from
|
|
33
|
+
* {@link recordDelete}.confirmCopy, whose body for one record is
|
|
34
|
+
* {@link recordDelete}.confirmText.
|
|
35
|
+
*
|
|
36
|
+
* ## The confirmation names what it deletes (objectui#11695)
|
|
37
|
+
*
|
|
38
|
+
* A generic "Confirm Action" / "Continue" dialog never said WHICH record was
|
|
39
|
+
* about to go, nor that the click is a delete. The title names the record by
|
|
40
|
+
* the ONE ADR-0079 display-name resolver ({@link getRecordDisplayName}, the
|
|
41
|
+
* resolver the record header and lookups use), and the object label — or, for
|
|
42
|
+
* a batch, the count. The confirm button reads as the deletion it is; every
|
|
43
|
+
* host paints it in the destructive button style.
|
|
44
|
+
*
|
|
45
|
+
* ## The result shape is the action runner's, on purpose
|
|
46
|
+
*
|
|
47
|
+
* `run` returns what a registered `delete` handler returns, because the console
|
|
48
|
+
* registers it as exactly that. The toasts here are the AUTHORITATIVE feedback,
|
|
49
|
+
* so every path returns WITHOUT an `error` key (and success returns `silent`) —
|
|
50
|
+
* otherwise the runner's post-execution hook, which has its own toast handler,
|
|
51
|
+
* would toast the same outcome a second time. The single exception is a
|
|
52
|
+
* request with no record id at all, which toasts nothing here and returns the
|
|
53
|
+
* `error` for the runner to report.
|
|
54
|
+
*
|
|
55
|
+
* Record ids are forwarded exactly as the caller supplied them; nothing here
|
|
56
|
+
* converts them.
|
|
57
|
+
*/
|
|
58
|
+
import type { ActionResult } from './ActionRunner.js';
|
|
59
|
+
type Row = Record<string, unknown>;
|
|
60
|
+
/** Translate a key — the host's `t`, injected so core takes no i18n dependency. */
|
|
61
|
+
type Translate = (key: string, options?: Record<string, unknown>) => string;
|
|
62
|
+
/** Everything `run` needs from its host. `confirmText` needs only the first two. */
|
|
63
|
+
interface RecordDeleteDeps {
|
|
64
|
+
objectName: string;
|
|
65
|
+
t: Translate;
|
|
66
|
+
/** The object's display label, used by the toasts. */
|
|
67
|
+
label: string;
|
|
68
|
+
dataSource: {
|
|
69
|
+
delete(resource: string, id: string): Promise<unknown>;
|
|
70
|
+
};
|
|
71
|
+
/** The host's toast sink (sonner's `toast` in both hosts today). */
|
|
72
|
+
toast: {
|
|
73
|
+
success(message: string): unknown;
|
|
74
|
+
error(message: string, data?: {
|
|
75
|
+
description?: string;
|
|
76
|
+
}): unknown;
|
|
77
|
+
};
|
|
78
|
+
/** Re-read the list after a delete. */
|
|
79
|
+
onRefresh?: () => void;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The request, in the action runner's `delete` shape — the console registers
|
|
83
|
+
* `run` as its `delete` handler, so the runner's action arrives here verbatim:
|
|
84
|
+
* `params.records` (several), `params.recordId` + optional `params.record`
|
|
85
|
+
* (one), and the legacy top-level `recordId`.
|
|
86
|
+
*/
|
|
87
|
+
interface RecordDeleteRequest {
|
|
88
|
+
params?: {
|
|
89
|
+
records?: unknown;
|
|
90
|
+
recordId?: unknown;
|
|
91
|
+
record?: Row | null;
|
|
92
|
+
};
|
|
93
|
+
recordId?: unknown;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The copy of a delete confirmation — everything a host's confirm dialog shows,
|
|
97
|
+
* from {@link recordDelete}.confirmCopy (objectui#11695).
|
|
98
|
+
*/
|
|
99
|
+
export interface RecordDeleteConfirmCopy {
|
|
100
|
+
/** The dialog title: names the record and its object, or the batch size. */
|
|
101
|
+
title: string;
|
|
102
|
+
/** The dialog body: the delete question, or the batch question. */
|
|
103
|
+
message: string;
|
|
104
|
+
/** The confirm button's label: a deletion verb, painted destructive by the host. */
|
|
105
|
+
confirmText: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* What a delete confirmation is about: ONE record (its row — at least its
|
|
109
|
+
* `id`, so a nameless row still reads by the resolver's `Record #id` floor) or
|
|
110
|
+
* a batch (how many).
|
|
111
|
+
*/
|
|
112
|
+
export type RecordDeleteConfirmTarget = {
|
|
113
|
+
record: Row | null | undefined;
|
|
114
|
+
} | {
|
|
115
|
+
count: number;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* The record-delete core: `confirmText` is the question to ask before deleting
|
|
119
|
+
* one record, `run` performs the delete (one record, or several settled
|
|
120
|
+
* together) and reports it. See the module docblock for objectui#10383.
|
|
121
|
+
*/
|
|
122
|
+
export declare const recordDelete: Readonly<{
|
|
123
|
+
/**
|
|
124
|
+
* The question to ask before deleting ONE record — the body of
|
|
125
|
+
* {@link recordDelete}.confirmCopy.
|
|
126
|
+
*/
|
|
127
|
+
confirmText(deps: Pick<RecordDeleteDeps, "t">): string;
|
|
128
|
+
/**
|
|
129
|
+
* The whole delete confirmation — title, body and confirm-button label — for
|
|
130
|
+
* ONE record or a batch (objectui#11695). Every host's delete dialog shows
|
|
131
|
+
* this copy, so the list's row Delete, its bulk Delete and the record page's
|
|
132
|
+
* Delete say the same thing.
|
|
133
|
+
*
|
|
134
|
+
* One record: the title names it — the object label plus the record's
|
|
135
|
+
* display name from {@link getRecordDisplayName}, reading `objectDef`'s
|
|
136
|
+
* declared name field when the host has the definition — and the body is
|
|
137
|
+
* {@link recordDelete}.confirmText. A batch: the title counts it. The confirm
|
|
138
|
+
* button is the delete verb in both, which the host paints destructive.
|
|
139
|
+
*/
|
|
140
|
+
confirmCopy(deps: Pick<RecordDeleteDeps, "objectName" | "t" | "label"> & {
|
|
141
|
+
/** The object definition, so the name follows its declared `nameField`. */
|
|
142
|
+
objectDef?: unknown;
|
|
143
|
+
}, target: RecordDeleteConfirmTarget): RecordDeleteConfirmCopy;
|
|
144
|
+
/**
|
|
145
|
+
* Delete, refresh and report. Several records (`params.records`, more than
|
|
146
|
+
* one with an `id`) are deleted one call each and settled together, then the
|
|
147
|
+
* list refreshes and ONE summary toast reports the batch. Otherwise one
|
|
148
|
+
* record is deleted; on success the list refreshes and a success toast shows,
|
|
149
|
+
* on failure an error
|
|
150
|
+
* toast carries the error message and the list is left as it is.
|
|
151
|
+
*/
|
|
152
|
+
run(deps: RecordDeleteDeps, request: RecordDeleteRequest): Promise<ActionResult>;
|
|
153
|
+
}>;
|
|
154
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
import { getRecordDisplayName } from '../utils/record-title.js';
|
|
9
|
+
/**
|
|
10
|
+
* The record-delete core: `confirmText` is the question to ask before deleting
|
|
11
|
+
* one record, `run` performs the delete (one record, or several settled
|
|
12
|
+
* together) and reports it. See the module docblock for objectui#10383.
|
|
13
|
+
*/
|
|
14
|
+
export const recordDelete = Object.freeze({
|
|
15
|
+
/**
|
|
16
|
+
* The question to ask before deleting ONE record — the body of
|
|
17
|
+
* {@link recordDelete}.confirmCopy.
|
|
18
|
+
*/
|
|
19
|
+
confirmText(deps) {
|
|
20
|
+
return deps.t('objectActions.deleteConfirm');
|
|
21
|
+
},
|
|
22
|
+
/**
|
|
23
|
+
* The whole delete confirmation — title, body and confirm-button label — for
|
|
24
|
+
* ONE record or a batch (objectui#11695). Every host's delete dialog shows
|
|
25
|
+
* this copy, so the list's row Delete, its bulk Delete and the record page's
|
|
26
|
+
* Delete say the same thing.
|
|
27
|
+
*
|
|
28
|
+
* One record: the title names it — the object label plus the record's
|
|
29
|
+
* display name from {@link getRecordDisplayName}, reading `objectDef`'s
|
|
30
|
+
* declared name field when the host has the definition — and the body is
|
|
31
|
+
* {@link recordDelete}.confirmText. A batch: the title counts it. The confirm
|
|
32
|
+
* button is the delete verb in both, which the host paints destructive.
|
|
33
|
+
*/
|
|
34
|
+
confirmCopy(deps, target) {
|
|
35
|
+
const { t, label } = deps;
|
|
36
|
+
const confirmText = t('objectActions.deleteConfirmButton');
|
|
37
|
+
if ('count' in target) {
|
|
38
|
+
return {
|
|
39
|
+
title: t('objectActions.bulkDeleteConfirmTitle', { count: target.count, label }),
|
|
40
|
+
message: t('console.objectView.bulkDeleteConfirm', { count: target.count }),
|
|
41
|
+
confirmText,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
title: t('objectActions.deleteConfirmTitle', {
|
|
46
|
+
label,
|
|
47
|
+
name: getRecordDisplayName(deps.objectDef, target.record),
|
|
48
|
+
}),
|
|
49
|
+
message: recordDelete.confirmText(deps),
|
|
50
|
+
confirmText,
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* Delete, refresh and report. Several records (`params.records`, more than
|
|
55
|
+
* one with an `id`) are deleted one call each and settled together, then the
|
|
56
|
+
* list refreshes and ONE summary toast reports the batch. Otherwise one
|
|
57
|
+
* record is deleted; on success the list refreshes and a success toast shows,
|
|
58
|
+
* on failure an error
|
|
59
|
+
* toast carries the error message and the list is left as it is.
|
|
60
|
+
*/
|
|
61
|
+
async run(deps, request) {
|
|
62
|
+
const { objectName, t, label, dataSource, toast, onRefresh } = deps;
|
|
63
|
+
const params = request.params;
|
|
64
|
+
const records = Array.isArray(params?.records)
|
|
65
|
+
? params.records.filter((r) => r?.id != null)
|
|
66
|
+
: null;
|
|
67
|
+
// Bulk path — delete every record in parallel and report a summary.
|
|
68
|
+
if (records && records.length > 1) {
|
|
69
|
+
const results = await Promise.allSettled(records.map((r) => dataSource.delete(objectName, r.id)));
|
|
70
|
+
const failed = results.filter((r) => r.status === 'rejected').length;
|
|
71
|
+
const succeeded = results.length - failed;
|
|
72
|
+
onRefresh?.();
|
|
73
|
+
if (failed === 0) {
|
|
74
|
+
toast.success(t('objectActions.bulkDeleteSuccess', {
|
|
75
|
+
count: succeeded,
|
|
76
|
+
label,
|
|
77
|
+
defaultValue: `Deleted ${succeeded} ${label} records`,
|
|
78
|
+
}));
|
|
79
|
+
// `silent`: the summary above is the feedback — without it the runner's
|
|
80
|
+
// post-execution hook adds a second, generic success toast.
|
|
81
|
+
return { success: true, reload: true, silent: true };
|
|
82
|
+
}
|
|
83
|
+
toast.error(t('objectActions.bulkDeletePartial', {
|
|
84
|
+
succeeded,
|
|
85
|
+
failed,
|
|
86
|
+
defaultValue: `${succeeded} deleted, ${failed} failed`,
|
|
87
|
+
}));
|
|
88
|
+
// The summary above is authoritative; returning WITHOUT `error` keeps the
|
|
89
|
+
// runner from toasting the failure a second time.
|
|
90
|
+
return { success: false };
|
|
91
|
+
}
|
|
92
|
+
const recordId = params?.recordId ?? params?.record?.id ?? records?.[0]?.id ?? request.recordId;
|
|
93
|
+
if (!recordId)
|
|
94
|
+
return { success: false, error: t('objectActions.noRecordId') };
|
|
95
|
+
try {
|
|
96
|
+
await dataSource.delete(objectName, recordId);
|
|
97
|
+
onRefresh?.();
|
|
98
|
+
toast.success(t('objectActions.deleteSuccess', { label }));
|
|
99
|
+
return { success: true, reload: true, silent: true };
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
toast.error(t('objectActions.deleteFailed', { label }), {
|
|
103
|
+
description: err.message,
|
|
104
|
+
});
|
|
105
|
+
// The toast above (label + error message) is the feedback; returning
|
|
106
|
+
// WITHOUT `error` keeps the runner from toasting the raw message again.
|
|
107
|
+
return { success: false };
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
});
|
|
@@ -5,8 +5,11 @@
|
|
|
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
|
-
* A DataSource adapter
|
|
9
|
-
*
|
|
8
|
+
* A DataSource adapter over raw HTTP, built in code from an
|
|
9
|
+
* `ApiDataSourceConfig` (e.g. the console's approvals inbox). It is not a
|
|
10
|
+
* `ViewData` mode: the view-level `provider: 'api'` is retired in
|
|
11
|
+
* `@objectstack/spec` (objectstack#23082), and `resolveDataSource` builds no
|
|
12
|
+
* `ApiDataSource` (objectui#12325).
|
|
10
13
|
*/
|
|
11
14
|
import type { DataSource, BatchTransactionOperation, QueryParams, QueryResult, HttpRequest, AggregateParams, AggregateResult } from '@object-ui/types';
|
|
12
15
|
export interface ApiDataSourceConfig {
|
|
@@ -22,8 +25,9 @@ export interface ApiDataSourceConfig {
|
|
|
22
25
|
/**
|
|
23
26
|
* ApiDataSource — a DataSource adapter for raw HTTP APIs.
|
|
24
27
|
*
|
|
25
|
-
*
|
|
26
|
-
* configs define the endpoints; all
|
|
28
|
+
* Constructed in code — never resolved from a `ViewData` block (see the file
|
|
29
|
+
* header). The read and write HttpRequest configs define the endpoints; all
|
|
30
|
+
* CRUD methods map onto HTTP verbs.
|
|
27
31
|
*
|
|
28
32
|
* Read operations use the `read` config, write operations use the `write` config.
|
|
29
33
|
* Both fall back to each other when one is not provided.
|