@colixsystems/widget-sdk 0.81.0 → 0.82.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 +8 -0
- package/dist/contract.cjs +19 -1
- package/dist/contract.js +19 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,6 +62,14 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
62
62
|
|
|
63
63
|
`v0.77.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**.
|
|
64
64
|
|
|
65
|
+
### What's new in 0.82.0 (contract 1.57.0)
|
|
66
|
+
|
|
67
|
+
**Server-action scripts can notify a record's permission subjects (REQ-ACTION-NOTIFY-SUBJECTS, sc-4586).** `await notifications.notifyRecordSubjects(tableId, recordId, { title, body, link, emit_email, emit_push, exclude_user_id })` resolves to `{ recipients }` and notifies every app user whose per-record grant lets them **read** that record. This addresses the one audience the other two primitives cannot name: when membership *is* the ACL, there is no recipient column to read. The Chat widget is the case in point — a channel's participants ARE that channel record's grants, so neither a `recipient_expr` (which resolves only a fixed id or a single user/group reference column) nor a `notifyUser` loop over a column that does not exist can reach them. Subject kinds follow REQ-ACL-09: a `user` grant notifies its user, a `group` grant expands through its memberships, and the two synthetic kinds (`authenticated`, `everyone`) are skipped because they address the whole workspace rather than a membership. Recipients are **deduplicated**, so someone reachable through both a direct grant and a granted group is notified once, and `exclude_user_id` drops one — pass the author so nobody is notified of their own write. Dispatch goes through the same `notifyUser` path as before, so the always-written inbox row, the preference-gated email + push mirrors, the link sanitiser and the title/body caps are inherited unchanged, and written rows count toward the same per-run cap of 500. The tenant is bound host-side and the table/record pair is verified against it, so a foreign or missing id resolves to `{ recipients: 0 }` rather than distinguishing "absent" from "not yours". **The script never receives the member list — only the count.** `CONTRACT.version` → `1.57.0`. Additive; no widget hook, primitive, manifest field, or token changed shape.
|
|
68
|
+
|
|
69
|
+
### 0.82.0 also carries (contract 1.56.0)
|
|
70
|
+
|
|
71
|
+
**Server-action scripts gain a `notifications` global (REQ-ACTION-NOTIFY, sc-4514).** A `scriptSource` action can now send a real notification to a recipient it resolves at run time: `await notifications.notifyUser(userId, { title, body, link, emit_email, emit_push })` and `await notifications.notifyGroup(groupId, opts)`. Options are **snake_case**, matching every other shape a script sees. `notifyUser` resolves to the created notification row (or `null` when the recipient was skipped); `notifyGroup` resolves to `{ recipients }`. This is a directness change rather than a new capability: an action could already notify indirectly by writing into a table carrying an enabled `NotificationRule`, but that costs a throwaway table, a per-table rule, a recipient expressible only as a fixed id or one reference column — and it fails silently, since with no rule attached the row just lands and the run still reports success. `POST /notifications/send` is no alternative (it needs an app-user JWT an action cannot hold). The direct call removes the intermediary and makes a non-delivery throw. Both methods delegate to the platform's one notification dispatch path, so the inbox row is always written, the email + push mirrors respect the recipient's channel preferences, and the push ping never carries the title or body. The tenant is bound host-side: a recipient in another workspace, a soft-deleted group, or a deactivated user is a silent skip, never a cross-tenant write. A blank `title`, a non-string `body`, or exceeding the per-run cap of 500 written notifications throws a catchable Error. New entry in `CONTRACT.actionScriptGlobals`; `CONTRACT.version` → `1.56.0`. Additive — no widget hook, primitive, manifest field, or token changed shape.
|
|
72
|
+
|
|
65
73
|
### What's new in 0.78.0
|
|
66
74
|
|
|
67
75
|
**New `useIdentification()` hook — identify a visitor who is NOT signed in (REQ-IDENT, sc-4313).** A new IDENTIFICATION hook reading a newly-injected `ctx.identification` slice (the new `@colixsystems/identification-client`, constructed by both the web Player and the native Expo export). Returns `{ available, availabilityLoading, status, qr, autoStartToken, message, identity, identificationId, loading, error, start, refresh, cancel, reset }`.
|
package/dist/contract.cjs
CHANGED
|
@@ -1269,6 +1269,7 @@ const ACTION_SCRIPT_GLOBALS = [
|
|
|
1269
1269
|
"secrets",
|
|
1270
1270
|
"fetch",
|
|
1271
1271
|
"connectors",
|
|
1272
|
+
"notifications",
|
|
1272
1273
|
"console",
|
|
1273
1274
|
"record",
|
|
1274
1275
|
"tenantId",
|
|
@@ -2506,7 +2507,24 @@ const CONTRACT = deepFreeze({
|
|
|
2506
2507
|
// already measured its own box with onLayout; this promotes that one
|
|
2507
2508
|
// pattern to the SDK so custom and marketplace widgets get it too,
|
|
2508
2509
|
// instead of each rolling its own.
|
|
2509
|
-
|
|
2510
|
+
// 1.55.0: additive (sc-4505) — `useWidgetInput(inputName)` + the
|
|
2511
|
+
// `PAYLOAD_VALUE_TYPES` a widget event payload field may declare, so
|
|
2512
|
+
// widgets on one page relate through declared inputs.
|
|
2513
|
+
// 1.56.0: additive (sc-4514) — `notifications` joins
|
|
2514
|
+
// `actionScriptGlobals`. `notifications.notifyUser(id, opts)` /
|
|
2515
|
+
// `notifyGroup(id, opts)` delegate to the one notification dispatch path.
|
|
2516
|
+
// Directness, not a new capability: an action could already notify by
|
|
2517
|
+
// writing into a table carrying a NotificationRule, but that needs a
|
|
2518
|
+
// throwaway table plus a per-table rule and fails SILENTLY when no rule
|
|
2519
|
+
// is attached — the row lands and the run still reports success.
|
|
2520
|
+
// 1.57.0: additive (sc-4586) — `notifications.notifyRecordSubjects(tableId,
|
|
2521
|
+
// recordId, opts)`, resolving to { recipients }. Notifies whoever a
|
|
2522
|
+
// record's per-record grants let read it, which is the only way to address
|
|
2523
|
+
// membership-by-ACL: a Chat channel's participants ARE its grants, so no
|
|
2524
|
+
// `recipient_expr` shape and no recipient column can name them. The member
|
|
2525
|
+
// list stays host-side — a script receives a count, never the ids — and
|
|
2526
|
+
// `exclude_user_id` keeps an author off their own message.
|
|
2527
|
+
version: "1.57.0",
|
|
2510
2528
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
2511
2529
|
hooks: HOOKS,
|
|
2512
2530
|
primitives: PRIMITIVES,
|
package/dist/contract.js
CHANGED
|
@@ -1269,6 +1269,7 @@ const ACTION_SCRIPT_GLOBALS = [
|
|
|
1269
1269
|
"secrets",
|
|
1270
1270
|
"fetch",
|
|
1271
1271
|
"connectors",
|
|
1272
|
+
"notifications",
|
|
1272
1273
|
"console",
|
|
1273
1274
|
"record",
|
|
1274
1275
|
"tenantId",
|
|
@@ -2506,7 +2507,24 @@ const CONTRACT = deepFreeze({
|
|
|
2506
2507
|
// already measured its own box with onLayout; this promotes that one
|
|
2507
2508
|
// pattern to the SDK so custom and marketplace widgets get it too,
|
|
2508
2509
|
// instead of each rolling its own.
|
|
2509
|
-
|
|
2510
|
+
// 1.55.0: additive (sc-4505) — `useWidgetInput(inputName)` + the
|
|
2511
|
+
// `PAYLOAD_VALUE_TYPES` a widget event payload field may declare, so
|
|
2512
|
+
// widgets on one page relate through declared inputs.
|
|
2513
|
+
// 1.56.0: additive (sc-4514) — `notifications` joins
|
|
2514
|
+
// `actionScriptGlobals`. `notifications.notifyUser(id, opts)` /
|
|
2515
|
+
// `notifyGroup(id, opts)` delegate to the one notification dispatch path.
|
|
2516
|
+
// Directness, not a new capability: an action could already notify by
|
|
2517
|
+
// writing into a table carrying a NotificationRule, but that needs a
|
|
2518
|
+
// throwaway table plus a per-table rule and fails SILENTLY when no rule
|
|
2519
|
+
// is attached — the row lands and the run still reports success.
|
|
2520
|
+
// 1.57.0: additive (sc-4586) — `notifications.notifyRecordSubjects(tableId,
|
|
2521
|
+
// recordId, opts)`, resolving to { recipients }. Notifies whoever a
|
|
2522
|
+
// record's per-record grants let read it, which is the only way to address
|
|
2523
|
+
// membership-by-ACL: a Chat channel's participants ARE its grants, so no
|
|
2524
|
+
// `recipient_expr` shape and no recipient column can name them. The member
|
|
2525
|
+
// list stays host-side — a script receives a count, never the ids — and
|
|
2526
|
+
// `exclude_user_id` keeps an author off their own message.
|
|
2527
|
+
version: "1.57.0",
|
|
2510
2528
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
2511
2529
|
hooks: HOOKS,
|
|
2512
2530
|
primitives: PRIMITIVES,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.82.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",
|