@colixsystems/widget-sdk 0.18.0 → 0.19.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 +87 -29
- package/dist/contract.cjs +137 -110
- package/dist/contract.js +147 -119
- package/dist/hooks.js +734 -571
- package/dist/index.d.ts +228 -65
- package/dist/linter.cjs +56 -0
- package/dist/linter.js +57 -0
- package/dist/manifest.cjs +75 -2
- package/dist/manifest.js +75 -2
- package/package.json +2 -2
package/dist/contract.js
CHANGED
|
@@ -168,12 +168,12 @@ const HOOKS = [
|
|
|
168
168
|
name: "useDirectory",
|
|
169
169
|
signature: "useDirectory(query?)",
|
|
170
170
|
returnShape: {
|
|
171
|
-
users: "Array<{ id, name, role }>",
|
|
171
|
+
users: "Array<{ id, name, role }> // snake_case rows; unwrapped from { data, meta }",
|
|
172
172
|
loading: "boolean",
|
|
173
173
|
error: "DatastoreError | null",
|
|
174
174
|
refetch: "() => Promise<void>",
|
|
175
175
|
},
|
|
176
|
-
requiredContextSlice: ["directory.
|
|
176
|
+
requiredContextSlice: ["directory.users"],
|
|
177
177
|
scopes: ["directory.read:users"],
|
|
178
178
|
},
|
|
179
179
|
{
|
|
@@ -207,28 +207,26 @@ const HOOKS = [
|
|
|
207
207
|
name: "useUsers",
|
|
208
208
|
signature: "useUsers(query?)",
|
|
209
209
|
description:
|
|
210
|
-
"AppUser administration
|
|
211
|
-
"deactivate,
|
|
212
|
-
"
|
|
213
|
-
"
|
|
210
|
+
"AppUser administration via the injected directory-client at " +
|
|
211
|
+
"ctx.directory.users.{list,get,invite,deactivate,reactivate}. Returns " +
|
|
212
|
+
"{ users, loading, error, refetch, invite, deactivate, reactivate, remove }. " +
|
|
213
|
+
"list returns the { data, meta } envelope verbatim — the hook unwraps " +
|
|
214
|
+
"res.data; rows are snake_case (is_active, …). Reads need users.read:* " +
|
|
215
|
+
"scope; mutations need users.write:*. The `invite` call accepts " +
|
|
216
|
+
"{ email, name, group_ids? } and returns the resulting AppUserInvite row " +
|
|
217
|
+
"(the email is sent by the host).",
|
|
214
218
|
returnShape: {
|
|
215
|
-
users: "Array<{ id, name, email?, role,
|
|
219
|
+
users: "Array<{ id, name, email?, role, is_active }> // snake_case rows; unwrapped from { data, meta }",
|
|
216
220
|
loading: "boolean",
|
|
217
221
|
error: "DirectoryError | null",
|
|
218
222
|
refetch: "() => Promise<void>",
|
|
219
223
|
invite:
|
|
220
|
-
"({ email, name,
|
|
224
|
+
"({ email, name, group_ids? }) => Promise<Invite> // rejects with DirectoryError",
|
|
221
225
|
deactivate: "(userId) => Promise<User> // rejects with DirectoryError",
|
|
222
226
|
reactivate: "(userId) => Promise<User> // rejects with DirectoryError",
|
|
223
227
|
remove: "(userId) => Promise<void> // rejects with DirectoryError",
|
|
224
228
|
},
|
|
225
|
-
requiredContextSlice: [
|
|
226
|
-
"users.listUsers",
|
|
227
|
-
"users.invite",
|
|
228
|
-
"users.deactivate",
|
|
229
|
-
"users.reactivate",
|
|
230
|
-
"users.remove",
|
|
231
|
-
],
|
|
229
|
+
requiredContextSlice: ["directory.users"],
|
|
232
230
|
scopes: ["users.read:*"],
|
|
233
231
|
},
|
|
234
232
|
// REQ-USERMGMT / REQ-ACL-SYS M3 — AppUserGroup administration. Returns
|
|
@@ -240,11 +238,14 @@ const HOOKS = [
|
|
|
240
238
|
name: "useGroups",
|
|
241
239
|
signature: "useGroups(query?)",
|
|
242
240
|
description:
|
|
243
|
-
"AppUserGroup administration
|
|
244
|
-
"create,
|
|
241
|
+
"AppUserGroup administration via the injected directory-client at " +
|
|
242
|
+
"ctx.directory.groups.{list,create,remove,addMember,removeMember,listMine}. " +
|
|
243
|
+
"Returns { groups, loading, error, refetch, create, remove, addMember, " +
|
|
244
|
+
"removeMember }. list returns the { data, meta } envelope verbatim — the " +
|
|
245
|
+
"hook unwraps res.data; rows are snake_case. Reads need groups.read:*; " +
|
|
245
246
|
"mutations need groups.write:*.",
|
|
246
247
|
returnShape: {
|
|
247
|
-
groups: "Array<{ id, name,
|
|
248
|
+
groups: "Array<{ id, name, member_count }> // snake_case rows; unwrapped from { data, meta }",
|
|
248
249
|
loading: "boolean",
|
|
249
250
|
error: "DirectoryError | null",
|
|
250
251
|
refetch: "() => Promise<void>",
|
|
@@ -256,54 +257,48 @@ const HOOKS = [
|
|
|
256
257
|
removeMember:
|
|
257
258
|
"(groupId, userId) => Promise<void> // rejects with DirectoryError",
|
|
258
259
|
},
|
|
259
|
-
requiredContextSlice: [
|
|
260
|
-
"groups.listGroups",
|
|
261
|
-
"groups.create",
|
|
262
|
-
"groups.remove",
|
|
263
|
-
"groups.addMember",
|
|
264
|
-
"groups.removeMember",
|
|
265
|
-
],
|
|
260
|
+
requiredContextSlice: ["directory.groups"],
|
|
266
261
|
scopes: ["groups.read:*"],
|
|
267
262
|
},
|
|
268
263
|
// REQ-ACL-06 / REQ-ACL-RELINHERIT-05 — per-record VirtualPermission
|
|
269
|
-
// management for a single record. Reads
|
|
270
|
-
//
|
|
271
|
-
//
|
|
272
|
-
//
|
|
273
|
-
//
|
|
274
|
-
//
|
|
275
|
-
//
|
|
264
|
+
// management for a single record. Reads the injected datastore-client at
|
|
265
|
+
// ctx.datastore.records(tableId).permissions(recordId) (the recordPermissions
|
|
266
|
+
// facade was folded into the datastore-client). The backend gates the call
|
|
267
|
+
// on `can_grant` for the target record (Studio owners short-circuit;
|
|
268
|
+
// APP_USER actors must hold `can_grant` via REQ-ACL-05 / REQ-ACL-06). A
|
|
269
|
+
// widget that declares the scope but whose caller lacks the grant receives
|
|
270
|
+
// `PermissionError { code: 'FORBIDDEN' }`.
|
|
276
271
|
{
|
|
277
272
|
name: "useRecordPermissions",
|
|
278
273
|
signature: "useRecordPermissions(tableId, recordId)",
|
|
279
274
|
description:
|
|
280
|
-
"Manage per-record VirtualPermission grants on a single record
|
|
281
|
-
"
|
|
282
|
-
"permissions
|
|
283
|
-
"
|
|
284
|
-
"
|
|
285
|
-
"(
|
|
286
|
-
"
|
|
287
|
-
"
|
|
275
|
+
"Manage per-record VirtualPermission grants on a single record via the " +
|
|
276
|
+
"injected datastore-client at " +
|
|
277
|
+
"ctx.datastore.records(tableId).permissions(recordId).{list,grant,update,revoke}. " +
|
|
278
|
+
"Returns { permissions, loading, error, grant, revoke, update, refetch } " +
|
|
279
|
+
"where permissions is Array<{ id, user_id, group_id, can_read, can_write, " +
|
|
280
|
+
"can_delete, can_grant }> (snake_case rows verbatim; list() returns the " +
|
|
281
|
+
"{ data, meta } envelope and the hook unwraps res.data). grant/update " +
|
|
282
|
+
"bodies are snake_case verbatim ({ user_id | group_id, can_read, " +
|
|
283
|
+
"can_write, can_delete, can_grant }). Mutating requires acl.write:records " +
|
|
284
|
+
"scope AND can_grant on the target record (REQ-ACL-RELINHERIT-05: " +
|
|
285
|
+
"APP_USER actors with can_grant are accepted, not only Studio owners). " +
|
|
286
|
+
"When tableId or recordId is null/empty the hook collapses to an empty " +
|
|
287
|
+
"no-op result without a network round-trip.",
|
|
288
288
|
returnShape: {
|
|
289
289
|
permissions:
|
|
290
|
-
"Array<{ id,
|
|
290
|
+
"Array<{ id, user_id, group_id, can_read, can_write, can_delete, can_grant }> // snake_case rows; unwrapped from { data, meta }",
|
|
291
291
|
loading: "boolean",
|
|
292
292
|
error: "PermissionError | null",
|
|
293
293
|
grant:
|
|
294
|
-
"({
|
|
294
|
+
"({ user_id?, group_id?, can_read?, can_write?, can_delete?, can_grant? }) => Promise<RecordPermission> // rejects with PermissionError",
|
|
295
295
|
revoke:
|
|
296
296
|
"(permissionId) => Promise<void> // rejects with PermissionError",
|
|
297
297
|
update:
|
|
298
|
-
"(permissionId, {
|
|
298
|
+
"(permissionId, { can_read?, can_write?, can_delete?, can_grant? }) => Promise<RecordPermission> // rejects with PermissionError",
|
|
299
299
|
refetch: "() => Promise<void>",
|
|
300
300
|
},
|
|
301
|
-
requiredContextSlice: [
|
|
302
|
-
"recordPermissions.list",
|
|
303
|
-
"recordPermissions.grant",
|
|
304
|
-
"recordPermissions.revoke",
|
|
305
|
-
"recordPermissions.update",
|
|
306
|
-
],
|
|
301
|
+
requiredContextSlice: ["datastore.records"],
|
|
307
302
|
scopes: ["acl.write:records"],
|
|
308
303
|
},
|
|
309
304
|
// REQ-WSDK-PLATFORM §6 — Tier A SDK hooks.
|
|
@@ -455,10 +450,40 @@ const CATEGORIES = [
|
|
|
455
450
|
"DATA",
|
|
456
451
|
"MEDIA",
|
|
457
452
|
"COMMUNICATION",
|
|
453
|
+
// REQ-USERMGMT-06: app-administration widgets (User Management, …) the
|
|
454
|
+
// published app embeds for its own member management — its own palette
|
|
455
|
+
// section, distinct from COMMUNICATION.
|
|
456
|
+
"ADMINISTRATION",
|
|
458
457
|
"CUSTOM",
|
|
459
458
|
];
|
|
460
459
|
const PLATFORMS = ["web", "native"];
|
|
461
460
|
|
|
461
|
+
// REQ-WIDGET-ACTION — server-side actions a widget may declare in its
|
|
462
|
+
// manifest. Each runs in the shared isolated-vm action runner (see backend
|
|
463
|
+
// action-runner.service.js) on a cron schedule or in response to a record
|
|
464
|
+
// CRUD event — NEVER in the rendered app, so they never affect Player ↔
|
|
465
|
+
// export parity. The trigger vocabulary mirrors the backend Action model.
|
|
466
|
+
const ACTION_TRIGGER_TYPES = [
|
|
467
|
+
"schedule",
|
|
468
|
+
"record_created",
|
|
469
|
+
"record_updated",
|
|
470
|
+
"record_deleted",
|
|
471
|
+
];
|
|
472
|
+
// Globals the action script runs against (the runner's surface) — distinct
|
|
473
|
+
// from the React/SDK widget surface, so the component import/banned-API
|
|
474
|
+
// linter does NOT scan action scripts.
|
|
475
|
+
const ACTION_SCRIPT_GLOBALS = [
|
|
476
|
+
"datastore",
|
|
477
|
+
"fetch",
|
|
478
|
+
"console",
|
|
479
|
+
"record",
|
|
480
|
+
"tenantId",
|
|
481
|
+
"triggerType",
|
|
482
|
+
"triggerTableId",
|
|
483
|
+
];
|
|
484
|
+
// Mirrors action.service.js SCRIPT_MAX_BYTES.
|
|
485
|
+
const ACTION_SCRIPT_MAX_BYTES = 200 * 1024;
|
|
486
|
+
|
|
462
487
|
// Reverse-DNS-ish manifest id, e.g. "com.acme.charts.barchart". Two or
|
|
463
488
|
// more labels, lowercase alnum + hyphen, label starts with a letter. The
|
|
464
489
|
// analyzer + the SDK validator both read this from the contract so a
|
|
@@ -544,6 +569,17 @@ const MANIFEST_SCHEMA = {
|
|
|
544
569
|
description:
|
|
545
570
|
"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.",
|
|
546
571
|
},
|
|
572
|
+
actions: {
|
|
573
|
+
type: "object[]",
|
|
574
|
+
required: false,
|
|
575
|
+
description:
|
|
576
|
+
"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?, triggerType (one of " +
|
|
577
|
+
ACTION_TRIGGER_TYPES.join(", ") +
|
|
578
|
+
"), scheduleCron? (required iff triggerType=='schedule'; node-cron syntax), timeoutMs? (100–300000), scriptSource (≤200 KiB; runs against " +
|
|
579
|
+
ACTION_SCRIPT_GLOBALS.join(", ") +
|
|
580
|
+
" — NOT the React surface, so SDK imports/hooks are unavailable) }. Do NOT include triggerTableId or apiKeyId — those are tenant-local and bound after install.",
|
|
581
|
+
default: [],
|
|
582
|
+
},
|
|
547
583
|
};
|
|
548
584
|
|
|
549
585
|
const WIDGET_CONTEXT_SHAPE = {
|
|
@@ -559,9 +595,10 @@ const WIDGET_CONTEXT_SHAPE = {
|
|
|
559
595
|
fields: { id: "manifest.id", version: "manifest.version" },
|
|
560
596
|
},
|
|
561
597
|
user: {
|
|
562
|
-
description:
|
|
598
|
+
description:
|
|
599
|
+
"Signed-in user, host-provided VERBATIM (snake_case: { id, email, display_name, roles, group_ids }). Not a data-client.",
|
|
563
600
|
required: true,
|
|
564
|
-
fields: { id: "string", email: "string",
|
|
601
|
+
fields: { id: "string", email: "string", display_name: "string" },
|
|
565
602
|
},
|
|
566
603
|
workspace: {
|
|
567
604
|
description:
|
|
@@ -581,19 +618,30 @@ const WIDGET_CONTEXT_SHAPE = {
|
|
|
581
618
|
},
|
|
582
619
|
datastore: {
|
|
583
620
|
description:
|
|
584
|
-
"
|
|
621
|
+
"Injected @colixsystems/datastore-client instance. " +
|
|
622
|
+
"{ tables: { list(), get(idOrName) }, schema(tableId) -> Promise<{ id, name, columns: [...] }>, " +
|
|
623
|
+
"records(tableId) -> { list(query) -> Promise<{ data, meta }>, get(id), create(values), update(id, values), delete(id), aggregate(spec), " +
|
|
624
|
+
"permissions(recordId) -> { list() -> Promise<{ data, meta }>, grant(body), update(permId, patch), revoke(permId) } } }. " +
|
|
625
|
+
"`records` backs the query/record/mutation hooks; `records(t).permissions(r)` backs useRecordPermissions(); `schema` backs useDatastoreSchema(). " +
|
|
626
|
+
"List methods return the { data, meta } envelope verbatim (hooks unwrap res.data); rows/bodies are snake_case (author column values keep their author-given names).",
|
|
585
627
|
required: true,
|
|
586
|
-
fields: { records: "function", schema: "function" },
|
|
628
|
+
fields: { records: "function", schema: "function", tables: "object" },
|
|
587
629
|
},
|
|
588
630
|
directory: {
|
|
589
631
|
description:
|
|
590
|
-
"
|
|
632
|
+
"Injected @colixsystems/directory-client instance. " +
|
|
633
|
+
"{ me(), users: { list(query?) -> Promise<{ data, meta }>, get(id), invite(body), deactivate(id), reactivate(id) }, " +
|
|
634
|
+
"groups: { list(query?) -> Promise<{ data, meta }>, create(body), remove(id), addMember(groupId, userId), removeMember(groupId, userId), listMine() }, " +
|
|
635
|
+
"invites: { list(), revoke(id), resend(id) } }. " +
|
|
636
|
+
"users backs useDirectory() + useUsers(); groups backs useGroups(). List methods return the { data, meta } envelope verbatim (hooks unwrap res.data); rows/bodies are snake_case. Reads gated by directory.read:users / users.read:* / groups.read:*; mutations by users.write:* / groups.write:*.",
|
|
591
637
|
required: true,
|
|
592
|
-
fields: {
|
|
638
|
+
fields: { users: "object", groups: "object" },
|
|
593
639
|
},
|
|
594
640
|
files: {
|
|
595
641
|
description:
|
|
596
|
-
"
|
|
642
|
+
"Injected @colixsystems/files-client instance, FLATTENED so file ops are top-level. " +
|
|
643
|
+
"{ get(id) -> Promise<{ id, url, ... }>, list(query) -> Promise<{ data, meta }>, upload(formData), folders: { list, create }, shares: { list, create, remove } }. " +
|
|
644
|
+
"Backs useFile(); the returned file already carries an absolute url the widget can drop into an <Image source>.",
|
|
597
645
|
required: true,
|
|
598
646
|
fields: { get: "function" },
|
|
599
647
|
},
|
|
@@ -610,64 +658,17 @@ const WIDGET_CONTEXT_SHAPE = {
|
|
|
610
658
|
},
|
|
611
659
|
payments: {
|
|
612
660
|
description:
|
|
613
|
-
"
|
|
661
|
+
"Injected @colixsystems/payments-client instance (REQ-BILL-07-WIDGETPAY). { requestPayment(body) -> Promise<{ id, status, checkoutUrl? }>, getPayment(id) -> Promise<payment> }. Backs usePayments(); requires the payments.charge:appUser scope. The host opens hosted Checkout (or auto-confirms under the mock provider); the charge settles to the workspace owner.",
|
|
614
662
|
required: true,
|
|
615
663
|
fields: { requestPayment: "function", getPayment: "function" },
|
|
616
664
|
},
|
|
617
|
-
// REQ-
|
|
618
|
-
//
|
|
619
|
-
//
|
|
620
|
-
//
|
|
621
|
-
//
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
"AppUser administration. { listUsers(query?) -> Promise<User[]>, invite({ email, name, groupIds? }) -> Promise<Invite>, deactivate(userId) -> Promise<User>, reactivate(userId) -> Promise<User>, remove(userId) -> Promise<void> }. Backs useUsers(); reads require users.read:*, mutations require users.write:*.",
|
|
625
|
-
required: true,
|
|
626
|
-
fields: {
|
|
627
|
-
listUsers: "function",
|
|
628
|
-
invite: "function",
|
|
629
|
-
deactivate: "function",
|
|
630
|
-
reactivate: "function",
|
|
631
|
-
remove: "function",
|
|
632
|
-
},
|
|
633
|
-
},
|
|
634
|
-
// REQ-ACL-06 / REQ-ACL-RELINHERIT-05 — per-record VirtualPermission
|
|
635
|
-
// management facade backing useRecordPermissions(). Hits the existing
|
|
636
|
-
// /api/v1/tables/:tableId/records/:recordId/permissions REST surface;
|
|
637
|
-
// the host normalises the wire shape (userId / groupId / both-null =
|
|
638
|
-
// public) into the principalType+principalId pair widgets read.
|
|
639
|
-
recordPermissions: {
|
|
640
|
-
description:
|
|
641
|
-
"Per-record VirtualPermission management. " +
|
|
642
|
-
"{ list(tableId, recordId) -> Promise<RecordPermission[]>, " +
|
|
643
|
-
"grant(tableId, recordId, body) -> Promise<RecordPermission>, " +
|
|
644
|
-
"revoke(tableId, recordId, permissionId) -> Promise<void>, " +
|
|
645
|
-
"update(tableId, recordId, permissionId, body) -> Promise<RecordPermission> }. " +
|
|
646
|
-
"Backs useRecordPermissions(); requires acl.write:records scope AND " +
|
|
647
|
-
"canGrant on the target record.",
|
|
648
|
-
required: true,
|
|
649
|
-
fields: {
|
|
650
|
-
list: "function",
|
|
651
|
-
grant: "function",
|
|
652
|
-
revoke: "function",
|
|
653
|
-
update: "function",
|
|
654
|
-
},
|
|
655
|
-
},
|
|
656
|
-
// REQ-USERMGMT / REQ-ACL-SYS M3 — AppUserGroup administration facade
|
|
657
|
-
// backing useGroups(). Reads gated by `groups.read:*`; mutations by
|
|
658
|
-
// `groups.write:*`. Same X-Widget-Scopes + SystemAcl gating as users.
|
|
659
|
-
groups: {
|
|
660
|
-
description:
|
|
661
|
-
"AppUserGroup administration. { listGroups(query?) -> Promise<Group[]>, create({ name }) -> Promise<Group>, remove(groupId) -> Promise<void>, addMember(groupId, userId) -> Promise<void>, removeMember(groupId, userId) -> Promise<void> }. Backs useGroups(); reads require groups.read:*, mutations require groups.write:*.",
|
|
662
|
-
required: true,
|
|
663
|
-
fields: {
|
|
664
|
-
listGroups: "function",
|
|
665
|
-
create: "function",
|
|
666
|
-
remove: "function",
|
|
667
|
-
addMember: "function",
|
|
668
|
-
removeMember: "function",
|
|
669
|
-
},
|
|
670
|
-
},
|
|
665
|
+
// REQ-WSDK-DOMAIN-CLIENTS — the AppUser administration, AppUserGroup
|
|
666
|
+
// administration, and per-record VirtualPermission facades that used to
|
|
667
|
+
// live here (`users`, `groups`, `recordPermissions`) were folded into the
|
|
668
|
+
// injected domain-client instances: useUsers()/useGroups() read
|
|
669
|
+
// ctx.directory.{users,groups}; useRecordPermissions() reads
|
|
670
|
+
// ctx.datastore.records(table).permissions(record). See the `directory`
|
|
671
|
+
// and `datastore` slices above.
|
|
671
672
|
i18n: {
|
|
672
673
|
description: "{ t(key, fallback?), locale }.",
|
|
673
674
|
required: true,
|
|
@@ -873,19 +874,46 @@ function deepFreeze(value) {
|
|
|
873
874
|
}
|
|
874
875
|
|
|
875
876
|
const CONTRACT = deepFreeze({
|
|
876
|
-
// 1.
|
|
877
|
-
//
|
|
878
|
-
//
|
|
879
|
-
//
|
|
880
|
-
//
|
|
881
|
-
//
|
|
882
|
-
// the
|
|
883
|
-
|
|
877
|
+
// 1.7.0: additive — new useDatastoreSchema(tableId) hook + the
|
|
878
|
+
// datastore.schema host-context slice it reads (resolves a table's column
|
|
879
|
+
// structure at runtime via the existing ACL-gated GET /tables/:id).
|
|
880
|
+
//
|
|
881
|
+
// 1.8.0: two additive features.
|
|
882
|
+
// - REQ-WIDGET-ACTION — manifests may declare an optional `actions` array:
|
|
883
|
+
// server-side cron/record-triggered scripts the operator enables per
|
|
884
|
+
// tenant, run in the existing isolated-vm action runner (never in the
|
|
885
|
+
// rendered app). New fields actionTriggerTypes / actionScriptGlobals /
|
|
886
|
+
// actionScriptMaxBytes feed the docs + agent prompt. New ADMINISTRATION
|
|
887
|
+
// manifest category (REQ-USERMGMT-06).
|
|
888
|
+
// - REQ-ACL-06 — new useRecordPermissions(tableId, recordId) hook + the
|
|
889
|
+
// recordPermissions host-context slice it reads + the acl.write:records
|
|
890
|
+
// scope it gates on. Hits the existing REQ-ACL-06
|
|
891
|
+
// /api/v1/tables/:tableId/records/:recordId/permissions REST surface;
|
|
892
|
+
// the host normalises the wire shape into a single principalType+
|
|
893
|
+
// principalId pair widgets branch on. Caller still needs canGrant on
|
|
894
|
+
// the target record (REQ-ACL-RELINHERIT-05).
|
|
895
|
+
//
|
|
896
|
+
// 1.9.0: host-contract change (REQ-WSDK-DOMAIN-CLIENTS) — the host now
|
|
897
|
+
// injects domain-client INSTANCES on the WidgetContext rather than
|
|
898
|
+
// bespoke per-hook facades. ctx.datastore is a @colixsystems/datastore-client
|
|
899
|
+
// (records(t).list now returns the { data, meta } envelope verbatim;
|
|
900
|
+
// records(t).permissions(r) replaces the deleted ctx.recordPermissions),
|
|
901
|
+
// ctx.directory is a @colixsystems/directory-client (users/groups
|
|
902
|
+
// namespaces replace the deleted ctx.users / ctx.groups; list returns
|
|
903
|
+
// envelopes), ctx.files is a flattened @colixsystems/files-client,
|
|
904
|
+
// ctx.payments is a @colixsystems/payments-client. All rows/bodies are
|
|
905
|
+
// snake_case. Hooks now unwrap the list envelope (res.data ?? []). The
|
|
906
|
+
// SDK stays duck-typed — it imports none of the four data SDKs. Minor
|
|
907
|
+
// bump on the contract's pre-1.0 versioning (the breaking channel).
|
|
908
|
+
version: "1.9.0",
|
|
884
909
|
hooks: HOOKS,
|
|
885
910
|
primitives: PRIMITIVES,
|
|
886
911
|
manifestSchema: MANIFEST_SCHEMA,
|
|
887
912
|
manifestCategories: CATEGORIES,
|
|
888
913
|
manifestPlatforms: PLATFORMS,
|
|
914
|
+
actionTriggerTypes: ACTION_TRIGGER_TYPES,
|
|
915
|
+
actionScriptGlobals: ACTION_SCRIPT_GLOBALS,
|
|
916
|
+
actionScriptMaxBytes: ACTION_SCRIPT_MAX_BYTES,
|
|
889
917
|
themeTokens: DEFAULT_THEME_TOKENS,
|
|
890
918
|
widgetContextShape: WIDGET_CONTEXT_SHAPE,
|
|
891
919
|
bundleExportContract: BUNDLE_EXPORT_CONTRACT,
|