@colixsystems/widget-sdk 0.92.0 → 0.93.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/README.md +10 -0
- package/dist/contract.cjs +5 -12
- package/dist/contract.js +5 -12
- package/dist/manifest.cjs +18 -64
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -65,6 +65,16 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
65
65
|
|
|
66
66
|
`v0.91.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
|
|
67
67
|
|
|
68
|
+
### What's new in 0.93.0 (contract 1.66.0)
|
|
69
|
+
|
|
70
|
+
**BREAKING: a widget no longer declares server-side actions.** `manifest.actions` is removed from the contract and **refused** by `validateManifest` — an author who declares it now fails the publish with a message naming the replacement, rather than shipping a widget that quietly carries no automation.
|
|
71
|
+
|
|
72
|
+
- **Why.** `actions` made a widget two products in one package: a React component that renders, and a script that never renders at all — different runtime, different lifecycle, different review concerns, one manifest. Automation is now its own marketplace deliverable, an **Action** (`@colixsystems/action-sdk`), with its own manifest, starter kit, developer guide, submit button and platform-admin review. A workspace installs and configures it separately from any widget.
|
|
73
|
+
- **What to do instead.** Move the script into an Action manifest (`appstudio-action lint` / `pack`), publish it, and let the workspace install it. Its `propertySchema` is filled in by the **installing operator** rather than a page author, and the values reach the script as the `properties` global.
|
|
74
|
+
- **Removed from the contract**: the `actions` manifest field. `CONTRACT.actionTriggerTypes` / `actionScriptGlobals` / `actionScriptMaxBytes` remain exported for now but describe a surface no widget field uses — the action-sdk owns that vocabulary.
|
|
75
|
+
- **Existing installs are unaffected.** A tenant Action row materialised from a widget manifest keeps running, keeps its bindings and keeps its run history; the platform migrated those rows onto the Action that ships the automation. What is gone is the ability to declare a NEW one on a widget.
|
|
76
|
+
- **No parity impact.** Actions never ran in the rendered app, so nothing about the Player or the export changes.
|
|
77
|
+
|
|
68
78
|
### What's new in 0.92.0 (contract 1.65.0)
|
|
69
79
|
|
|
70
80
|
**New `useInterpretDraft(tableId)` hook — turn one sentence into DRAFT record values.** A new DATASTORE hook reading a new `interpret` method on the existing `ctx.datastore` slice (`@colixsystems/datastore-client` 0.13.0). Returns `{ interpret, interpreting, error, result, available }`. Call `interpret(text, { fields, timeZone })` **imperatively** from an event handler — never on mount or in a render loop — and it resolves to `{ values, unresolved }`, where `values` is keyed by column NAME (the same shape `useDatastoreMutation().create` takes) and `unresolved` names the fields the sentence did not state.
|
package/dist/contract.cjs
CHANGED
|
@@ -1590,17 +1590,6 @@ const MANIFEST_SCHEMA = {
|
|
|
1590
1590
|
description:
|
|
1591
1591
|
"Optional. Tables the widget needs, seeded into the workspace at install time. Authors wire them into the widget's `tableRef` properties via the Properties Panel — the SDK does not auto-bind. Limits: 8 tables, 24 columns per table. RELATION columns address siblings by `targetSuffix` (must be declared earlier in the array). Tables persist across uninstalls.",
|
|
1592
1592
|
},
|
|
1593
|
-
actions: {
|
|
1594
|
-
type: "object[]",
|
|
1595
|
-
required: false,
|
|
1596
|
-
description:
|
|
1597
|
-
"Optional. Server-side actions the widget declares. Each runs in the shared isolated-vm action runner (cron- or record-triggered) — NEVER in the rendered app. Operators enable them per tenant from the Properties Panel; the action materialises DISABLED until they bind an integration API key (and, for record_* triggers, a target table) in the Actions admin page. Each entry: { key (stable, unique within the manifest), name, description?, triggerTypes (a non-empty array of unique values from " +
|
|
1598
|
-
ACTION_TRIGGER_TYPES.join(", ") +
|
|
1599
|
-
"; combine them so one script serves several events — the script's `triggerType` global names the event that actually fired), scheduleCron? (required iff triggerTypes contains 'schedule'; node-cron syntax), timeoutMs? (100–300000), scriptSource (≤200 KiB; runs against " +
|
|
1600
|
-
ACTION_SCRIPT_GLOBALS.join(", ") +
|
|
1601
|
-
" — NOT the React surface, so SDK imports/hooks are unavailable) }. Do NOT include triggerTableId or apiKeyId — those are tenant-local and bound after install.",
|
|
1602
|
-
default: [],
|
|
1603
|
-
},
|
|
1604
1593
|
translations: {
|
|
1605
1594
|
type: "object",
|
|
1606
1595
|
required: false,
|
|
@@ -2891,7 +2880,11 @@ const CONTRACT = deepFreeze({
|
|
|
2891
2880
|
// published widget keeps validating. The script's `triggerType` global
|
|
2892
2881
|
// now names the trigger that actually FIRED the run ('manual' and 'app'
|
|
2893
2882
|
// included), which is what makes a multi-trigger script able to branch.
|
|
2894
|
-
|
|
2883
|
+
// 1.66.0: BREAKING — `actions` is removed from the manifest contract and
|
|
2884
|
+
// REFUSED by the validator (sc-4879). Server-side automation ships as its own
|
|
2885
|
+
// marketplace deliverable (`@colixsystems/action-sdk`), which a workspace
|
|
2886
|
+
// installs and configures separately. A widget renders; it does not automate.
|
|
2887
|
+
version: "1.66.0",
|
|
2895
2888
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
2896
2889
|
hooks: HOOKS,
|
|
2897
2890
|
primitives: PRIMITIVES,
|
package/dist/contract.js
CHANGED
|
@@ -1590,17 +1590,6 @@ const MANIFEST_SCHEMA = {
|
|
|
1590
1590
|
description:
|
|
1591
1591
|
"Optional. Tables the widget needs, seeded into the workspace at install time. Authors wire them into the widget's `tableRef` properties via the Properties Panel — the SDK does not auto-bind. Limits: 8 tables, 24 columns per table. RELATION columns address siblings by `targetSuffix` (must be declared earlier in the array). Tables persist across uninstalls.",
|
|
1592
1592
|
},
|
|
1593
|
-
actions: {
|
|
1594
|
-
type: "object[]",
|
|
1595
|
-
required: false,
|
|
1596
|
-
description:
|
|
1597
|
-
"Optional. Server-side actions the widget declares. Each runs in the shared isolated-vm action runner (cron- or record-triggered) — NEVER in the rendered app. Operators enable them per tenant from the Properties Panel; the action materialises DISABLED until they bind an integration API key (and, for record_* triggers, a target table) in the Actions admin page. Each entry: { key (stable, unique within the manifest), name, description?, triggerTypes (a non-empty array of unique values from " +
|
|
1598
|
-
ACTION_TRIGGER_TYPES.join(", ") +
|
|
1599
|
-
"; combine them so one script serves several events — the script's `triggerType` global names the event that actually fired), scheduleCron? (required iff triggerTypes contains 'schedule'; node-cron syntax), timeoutMs? (100–300000), scriptSource (≤200 KiB; runs against " +
|
|
1600
|
-
ACTION_SCRIPT_GLOBALS.join(", ") +
|
|
1601
|
-
" — NOT the React surface, so SDK imports/hooks are unavailable) }. Do NOT include triggerTableId or apiKeyId — those are tenant-local and bound after install.",
|
|
1602
|
-
default: [],
|
|
1603
|
-
},
|
|
1604
1593
|
translations: {
|
|
1605
1594
|
type: "object",
|
|
1606
1595
|
required: false,
|
|
@@ -2891,7 +2880,11 @@ const CONTRACT = deepFreeze({
|
|
|
2891
2880
|
// published widget keeps validating. The script's `triggerType` global
|
|
2892
2881
|
// now names the trigger that actually FIRED the run ('manual' and 'app'
|
|
2893
2882
|
// included), which is what makes a multi-trigger script able to branch.
|
|
2894
|
-
|
|
2883
|
+
// 1.66.0: BREAKING — `actions` is removed from the manifest contract and
|
|
2884
|
+
// REFUSED by the validator (sc-4879). Server-side automation ships as its own
|
|
2885
|
+
// marketplace deliverable (`@colixsystems/action-sdk`), which a workspace
|
|
2886
|
+
// installs and configures separately. A widget renders; it does not automate.
|
|
2887
|
+
version: "1.66.0",
|
|
2895
2888
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
2896
2889
|
hooks: HOOKS,
|
|
2897
2890
|
primitives: PRIMITIVES,
|
package/dist/manifest.cjs
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// re-exports the same functions defined here so there is exactly one
|
|
5
5
|
// implementation.
|
|
6
6
|
|
|
7
|
-
const { CONTRACT
|
|
7
|
+
const { CONTRACT } = require("./contract.cjs");
|
|
8
8
|
|
|
9
9
|
const PAYLOAD_VALUE_TYPES = CONTRACT.payloadValueTypes;
|
|
10
10
|
|
|
@@ -39,20 +39,6 @@ const VALID_CATEGORIES = new Set([
|
|
|
39
39
|
]);
|
|
40
40
|
const VALID_PLATFORMS = new Set(["web", "native"]);
|
|
41
41
|
|
|
42
|
-
// REQ-WIDGET-ACTION — structural validation for manifest-declared server
|
|
43
|
-
// actions. Mirrors the backend action.service caps; the runner re-validates
|
|
44
|
-
// the cron expression (node-cron) and binds the tenant-local API key + table
|
|
45
|
-
// at enable time, so we only check shape + size here (cross-env: no Buffer).
|
|
46
|
-
const VALID_ACTION_TRIGGERS = new Set([
|
|
47
|
-
"schedule",
|
|
48
|
-
"record_created",
|
|
49
|
-
"record_updated",
|
|
50
|
-
"record_deleted",
|
|
51
|
-
]);
|
|
52
|
-
const ACTION_SCRIPT_MAX_BYTES = 200 * 1024;
|
|
53
|
-
const ACTION_TIMEOUT_MIN_MS = 100;
|
|
54
|
-
const ACTION_TIMEOUT_MAX_MS = 5 * 60 * 1000;
|
|
55
|
-
|
|
56
42
|
// REQ-L10N-WIDGET — caps + patterns for manifest-declared translations.
|
|
57
43
|
// The relative key pattern is deliberately tighter than the dictionary's
|
|
58
44
|
// own KEY_RE: once the host namespaces it (`widget.<id>.<key>`) the result
|
|
@@ -133,54 +119,22 @@ function validateManifestTranslations(translations, manifestId, errors) {
|
|
|
133
119
|
}
|
|
134
120
|
}
|
|
135
121
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
seenKeys.add(a.key);
|
|
153
|
-
}
|
|
154
|
-
pushIf(errors, isNonEmptyString(a.name), "manifest.actions[].name must be a non-empty string");
|
|
155
|
-
const triggerTypes = normaliseActionTriggerTypes(a);
|
|
156
|
-
if (triggerTypes === null) {
|
|
157
|
-
errors.push(
|
|
158
|
-
`manifest.actions[].triggerTypes must be a non-empty array of unique values from ${[...VALID_ACTION_TRIGGERS].join(", ")}`,
|
|
159
|
-
);
|
|
160
|
-
} else if (triggerTypes.includes("schedule")) {
|
|
161
|
-
pushIf(
|
|
162
|
-
errors,
|
|
163
|
-
isNonEmptyString(a.scheduleCron),
|
|
164
|
-
"manifest.actions[].scheduleCron is required when triggerTypes contains 'schedule'",
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
if (!isNonEmptyString(a.scriptSource)) {
|
|
168
|
-
errors.push("manifest.actions[].scriptSource must be a non-empty string");
|
|
169
|
-
} else if (utf8ByteLength(a.scriptSource) > ACTION_SCRIPT_MAX_BYTES) {
|
|
170
|
-
errors.push("manifest.actions[].scriptSource exceeds 200 KiB");
|
|
171
|
-
}
|
|
172
|
-
if (a.timeoutMs !== undefined) {
|
|
173
|
-
const t = Number(a.timeoutMs);
|
|
174
|
-
if (!Number.isFinite(t) || t < ACTION_TIMEOUT_MIN_MS || t > ACTION_TIMEOUT_MAX_MS) {
|
|
175
|
-
errors.push("manifest.actions[].timeoutMs must be between 100 and 300000");
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (a.triggerTableId !== undefined || a.apiKeyId !== undefined) {
|
|
179
|
-
errors.push(
|
|
180
|
-
"manifest.actions[] must not include triggerTableId or apiKeyId — those are tenant-local and bound after install",
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
122
|
+
// REQ-MKT-ACTION (sc-4879): a widget no longer declares server-side actions.
|
|
123
|
+
//
|
|
124
|
+
// `manifest.actions` was how an automation shipped before Actions existed as
|
|
125
|
+
// their own marketplace deliverable — a widget was two products in one package,
|
|
126
|
+
// a component that renders and a script that never renders at all. It is now
|
|
127
|
+
// REFUSED rather than ignored: an author who declares it believes the
|
|
128
|
+
// automation will ship, and silence would publish that misunderstanding.
|
|
129
|
+
//
|
|
130
|
+
// The replacement is a marketplace Action (`@colixsystems/action-sdk`), which
|
|
131
|
+
// the workspace installs and configures on its own.
|
|
132
|
+
function validateManifestActions(_actions, errors) {
|
|
133
|
+
errors.push(
|
|
134
|
+
"manifest.actions is no longer supported — ship the automation as a " +
|
|
135
|
+
"marketplace Action (@colixsystems/action-sdk) instead of declaring it " +
|
|
136
|
+
"on a widget",
|
|
137
|
+
);
|
|
184
138
|
}
|
|
185
139
|
|
|
186
140
|
function canonicalCategory(c) {
|
|
@@ -355,7 +309,7 @@ function validateManifest(m) {
|
|
|
355
309
|
}
|
|
356
310
|
}
|
|
357
311
|
|
|
358
|
-
//
|
|
312
|
+
// Present at all is now an error (sc-4879) — see validateManifestActions.
|
|
359
313
|
if (manifest.actions !== undefined) {
|
|
360
314
|
validateManifestActions(manifest.actions, errors);
|
|
361
315
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.93.0",
|
|
4
4
|
"description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|