@colixsystems/widget-sdk 0.51.0 → 0.53.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 +11 -3
- package/dist/contract.cjs +10 -1
- package/dist/contract.js +10 -1
- package/dist/hooks.js +2 -2
- package/dist/icon.js +3 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -0
- package/dist/index.native.js +1 -0
- package/dist/lucideIconName.cjs +17 -0
- package/dist/lucideIconName.js +19 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -51,7 +51,15 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
51
51
|
|
|
52
52
|
## Status
|
|
53
53
|
|
|
54
|
-
`v0.
|
|
54
|
+
`v0.53.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**.
|
|
55
|
+
|
|
56
|
+
### What's new in 0.53.0
|
|
57
|
+
|
|
58
|
+
**Server-action scripts gain a `connectors` global (REQ-ACTION-CONNECTORS, sc-2162).** A `scriptSource` action can now call `connectors.call(slug, { method, path, query, body, headers })` to invoke a tenant-configured REST connector by slug; it returns the upstream's `{ status, headers, body }`. Auth and SSRF protection are handled by the platform host — the script names only a slug (never a tenant or base URL), and the tenant is bound host-side. An unknown slug / SSRF rejection / timeout throws a catchable Error. New entry in `CONTRACT.actionScriptGlobals`; `CONTRACT.version` → `1.37.0`. Additive — no widget hook, primitive, manifest field, or token changed shape.
|
|
59
|
+
|
|
60
|
+
### What's new in 0.52.0
|
|
61
|
+
|
|
62
|
+
**Lucide icon names accept any case (sc-2088).** A new `normalizeLucideIconName(name)` export maps a human-typed icon name to the PascalCase form Lucide exports its components under — `arrow-right`, `arrow_right`, `arrow right`, `arrowRight`, and `ArrowRight` all resolve to `ArrowRight`; `building-2` → `Building2`. The lucide.dev gallery and its copy button hand you kebab-case, so authors no longer have to hand-convert. The `<Icon name="…">` primitive normalizes its `name` before lookup, and the `icon` propertySchema type accepts any case. Additive — one new pure export; no existing export changed signature. `CONTRACT` is unchanged.
|
|
55
63
|
|
|
56
64
|
### What's new in 0.51.0
|
|
57
65
|
|
|
@@ -280,7 +288,7 @@ Two additive features land in this version.
|
|
|
280
288
|
|
|
281
289
|
**A widget may declare server-side actions in its manifest.**
|
|
282
290
|
|
|
283
|
-
- **`WidgetManifest.actions` is now part of the public contract.** An optional array; each entry is `{ key, name, description?, triggerType, scheduleCron?, timeoutMs?, scriptSource }`. `triggerType` is one of `schedule`, `record_created`, `record_updated`, `record_deleted`; `scheduleCron` is required when `triggerType === "schedule"`. The `scriptSource` (≤ 200 KiB) runs in the **shared isolated-vm action runner** — against `datastore` / `fetch` / `console` / `record` / `tenantId` (the runner surface, **not** the React/SDK widget surface, so SDK imports and hooks are unavailable there and the component linter does not scan it). Actions never run in the rendered app, so they have **no effect on Player ↔ export parity**.
|
|
291
|
+
- **`WidgetManifest.actions` is now part of the public contract.** An optional array; each entry is `{ key, name, description?, triggerType, scheduleCron?, timeoutMs?, scriptSource }`. `triggerType` is one of `schedule`, `record_created`, `record_updated`, `record_deleted`; `scheduleCron` is required when `triggerType === "schedule"`. The `scriptSource` (≤ 200 KiB) runs in the **shared isolated-vm action runner** — against `datastore` / `fetch` / `connectors` / `console` / `record` / `tenantId` (the runner surface, **not** the React/SDK widget surface, so SDK imports and hooks are unavailable there and the component linter does not scan it). `connectors.call(slug, { method, path, query, body, headers })` resolves a tenant-configured REST connector by slug and returns `{ status, headers, body }` (auth + SSRF handled by the platform; an unknown slug / SSRF / timeout throws a catchable Error). Actions never run in the rendered app, so they have **no effect on Player ↔ export parity**.
|
|
284
292
|
- **Operators enable actions per tenant** from the Properties Panel. An enabled action materialises a tenant `Action` row **DISABLED** until the operator binds an integration API key (and, for `record_*` triggers, a target table) in the Actions admin page — those bindings are tenant-local, so `triggerTableId` / `apiKeyId` must **not** appear in the manifest (the validator and linter reject them).
|
|
285
293
|
- **New contract fields** `CONTRACT.actionTriggerTypes`, `CONTRACT.actionScriptGlobals`, `CONTRACT.actionScriptMaxBytes` expose the grammar so the Developer page, the AI agent prompt, and `validateManifest` derive it from one source. `validateManifest` now structurally validates `actions`; the marketplace linter rejects malformed / oversized declarations.
|
|
286
294
|
- **New manifest category `ADMINISTRATION`** for app-administration widgets such as User Management. Added to `CONTRACT.manifestCategories`, `validateManifest`, the `WidgetCategory` type, the marketplace category list, and the master-DB `WidgetCategory` enum.
|
|
@@ -353,7 +361,7 @@ The "split-implementation + vetted package list" pivot.
|
|
|
353
361
|
|
|
354
362
|
### What's new in 0.9.0
|
|
355
363
|
|
|
356
|
-
- **`usePayments()` — incoming app-user payments.** Returns `{ requestPayment, getPayment }`. `requestPayment({ amountCents, currency?, description, metadata?, returnPath? })` triggers a one-time charge from the signed-in app user and resolves to `{ id, status, checkoutUrl? }`: when `checkoutUrl` is present the widget opens it (web: navigate; native: `expo-web-browser`) — the user pays in **hosted
|
|
364
|
+
- **`usePayments()` — incoming app-user payments.** Returns `{ requestPayment, getPayment }`. `requestPayment({ amountCents, currency?, description, metadata?, returnPath? })` triggers a one-time charge from the signed-in app user and resolves to `{ id, status, checkoutUrl? }`: when `checkoutUrl` is present the widget opens it (web: navigate; native: `expo-web-browser`) — the user pays in the provider's **hosted checkout**; when absent (the platform's built-in **mock** provider, the default until a real provider is configured) the charge auto-confirms (`status: "PAID"`). `getPayment(id)` polls the terminal status. Backed by a new `WidgetContext.payments` slice and gated by the new `payments.charge:appUser` scope. **No card data ever touches the widget** — never collect card fields yourself. The charge settles to the workspace owner; the amount is bounded by a platform per-charge cap. Rejections are a structured `PaymentError` (also a new named export) with a stable `.code`.
|
|
357
365
|
- **`CONTRACT.version` → `1.2.0`** (additive: one new hook, one new context slice, one new scope, one new error class). No existing export changed signature.
|
|
358
366
|
|
|
359
367
|
### What was in 0.8.0
|
package/dist/contract.cjs
CHANGED
|
@@ -818,6 +818,7 @@ const ACTION_TRIGGER_TYPES = [
|
|
|
818
818
|
const ACTION_SCRIPT_GLOBALS = [
|
|
819
819
|
"datastore",
|
|
820
820
|
"fetch",
|
|
821
|
+
"connectors",
|
|
821
822
|
"console",
|
|
822
823
|
"record",
|
|
823
824
|
"tenantId",
|
|
@@ -1815,7 +1816,15 @@ const CONTRACT = deepFreeze({
|
|
|
1815
1816
|
// `notifications.send:appUser` scope it gates on. No existing hook,
|
|
1816
1817
|
// primitive, manifest field, or token changed shape — minor bump on the
|
|
1817
1818
|
// pre-1.0 channel.
|
|
1818
|
-
|
|
1819
|
+
//
|
|
1820
|
+
// 1.37.0: additive (REQ-ACTION-CONNECTORS, sc-2162) — server-action scripts
|
|
1821
|
+
// gain a `connectors` global. `connectors.call(slug, { method, path,
|
|
1822
|
+
// query, body, headers })` resolves a tenant-configured REST connector by
|
|
1823
|
+
// slug and returns `{ status, headers, body }`; auth + SSRF are handled by
|
|
1824
|
+
// the platform host, and an unknown slug / SSRF / timeout throws a
|
|
1825
|
+
// catchable Error. New entry in ACTION_SCRIPT_GLOBALS only — no widget
|
|
1826
|
+
// hook, primitive, manifest field, or token changed shape; minor bump.
|
|
1827
|
+
version: "1.37.0",
|
|
1819
1828
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
1820
1829
|
hooks: HOOKS,
|
|
1821
1830
|
primitives: PRIMITIVES,
|
package/dist/contract.js
CHANGED
|
@@ -818,6 +818,7 @@ const ACTION_TRIGGER_TYPES = [
|
|
|
818
818
|
const ACTION_SCRIPT_GLOBALS = [
|
|
819
819
|
"datastore",
|
|
820
820
|
"fetch",
|
|
821
|
+
"connectors",
|
|
821
822
|
"console",
|
|
822
823
|
"record",
|
|
823
824
|
"tenantId",
|
|
@@ -1815,7 +1816,15 @@ const CONTRACT = deepFreeze({
|
|
|
1815
1816
|
// `notifications.send:appUser` scope it gates on. No existing hook,
|
|
1816
1817
|
// primitive, manifest field, or token changed shape — minor bump on the
|
|
1817
1818
|
// pre-1.0 channel.
|
|
1818
|
-
|
|
1819
|
+
//
|
|
1820
|
+
// 1.37.0: additive (REQ-ACTION-CONNECTORS, sc-2162) — server-action scripts
|
|
1821
|
+
// gain a `connectors` global. `connectors.call(slug, { method, path,
|
|
1822
|
+
// query, body, headers })` resolves a tenant-configured REST connector by
|
|
1823
|
+
// slug and returns `{ status, headers, body }`; auth + SSRF are handled by
|
|
1824
|
+
// the platform host, and an unknown slug / SSRF / timeout throws a
|
|
1825
|
+
// catchable Error. New entry in ACTION_SCRIPT_GLOBALS only — no widget
|
|
1826
|
+
// hook, primitive, manifest field, or token changed shape; minor bump.
|
|
1827
|
+
version: "1.37.0",
|
|
1819
1828
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
1820
1829
|
hooks: HOOKS,
|
|
1821
1830
|
primitives: PRIMITIVES,
|
package/dist/hooks.js
CHANGED
|
@@ -2638,8 +2638,8 @@ function toPaymentError(err) {
|
|
|
2638
2638
|
* requestPayment({ amountCents, currency?, description, metadata? })
|
|
2639
2639
|
* → Promise<{ id, status, checkoutUrl?, ... }>. The host either
|
|
2640
2640
|
* auto-confirms (mock provider, `status: "PAID"`, no redirect) or
|
|
2641
|
-
* returns a hosted-
|
|
2642
|
-
* (
|
|
2641
|
+
* returns a hosted-checkout `checkoutUrl` the widget should open
|
|
2642
|
+
* (Mollie provider, `status: "PENDING"`). Rejects with a
|
|
2643
2643
|
* `PaymentError`.
|
|
2644
2644
|
* getPayment(paymentId) → Promise<payment> — poll the terminal status.
|
|
2645
2645
|
*
|
package/dist/icon.js
CHANGED
|
@@ -16,10 +16,11 @@
|
|
|
16
16
|
|
|
17
17
|
import React from "react";
|
|
18
18
|
import * as LucideIcons from "lucide-react-native";
|
|
19
|
+
import { normalizeLucideIconName } from "./lucideIconName.js";
|
|
19
20
|
|
|
20
21
|
export function Icon({ name, size, color }) {
|
|
21
|
-
const
|
|
22
|
-
|
|
22
|
+
const resolved = normalizeLucideIconName(name);
|
|
23
|
+
const candidate = resolved ? LucideIcons[resolved] : null;
|
|
23
24
|
const Component = candidate || LucideIcons.Square;
|
|
24
25
|
const pixelSize = Number.isFinite(size) && size > 0 ? size : 24;
|
|
25
26
|
return React.createElement(Component, {
|
package/dist/index.d.ts
CHANGED
|
@@ -624,8 +624,8 @@ export interface PaymentResult {
|
|
|
624
624
|
currency?: string;
|
|
625
625
|
description?: string;
|
|
626
626
|
/**
|
|
627
|
-
* Present (
|
|
628
|
-
*
|
|
627
|
+
* Present (Mollie provider) when the app user must complete a hosted
|
|
628
|
+
* checkout: the widget should open this URL. Absent under the mock
|
|
629
629
|
* provider, where the charge auto-confirms (`status: "PAID"`).
|
|
630
630
|
*/
|
|
631
631
|
checkoutUrl?: string | null;
|
package/dist/index.js
CHANGED
package/dist/index.native.js
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// CommonJS twin of lucideIconName.js for the backend (the page service +
|
|
2
|
+
// any other Node consumer require this). Keep the two in sync — same
|
|
3
|
+
// algorithm, same behaviour. See lucideIconName.js for the rationale.
|
|
4
|
+
"use strict";
|
|
5
|
+
|
|
6
|
+
function normalizeLucideIconName(name) {
|
|
7
|
+
if (typeof name !== "string") return "";
|
|
8
|
+
const trimmed = name.trim();
|
|
9
|
+
if (trimmed === "") return "";
|
|
10
|
+
return trimmed
|
|
11
|
+
.split(/[-_\s]+/)
|
|
12
|
+
.filter(Boolean)
|
|
13
|
+
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
|
|
14
|
+
.join("");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = { normalizeLucideIconName };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Normalize a human-typed Lucide icon name to the PascalCase form Lucide
|
|
2
|
+
// exports its components under. The lucide.dev gallery shows kebab-case
|
|
3
|
+
// (`arrow-right`) and its copy button hands you kebab-case, but
|
|
4
|
+
// `lucide-react` / `lucide-react-native` key their components in PascalCase
|
|
5
|
+
// (`ArrowRight`). This bridges the two so any of kebab / snake / spaced /
|
|
6
|
+
// camel / PascalCase resolves: `arrow-right`, `arrow_right`, `arrow right`,
|
|
7
|
+
// `arrowRight`, and `ArrowRight` all become `ArrowRight`; `building-2` becomes
|
|
8
|
+
// `Building2`. Non-strings and blanks return "" so callers fall back to a
|
|
9
|
+
// placeholder. Already-PascalCase names pass through unchanged.
|
|
10
|
+
export function normalizeLucideIconName(name) {
|
|
11
|
+
if (typeof name !== "string") return "";
|
|
12
|
+
const trimmed = name.trim();
|
|
13
|
+
if (trimmed === "") return "";
|
|
14
|
+
return trimmed
|
|
15
|
+
.split(/[-_\s]+/)
|
|
16
|
+
.filter(Boolean)
|
|
17
|
+
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
|
|
18
|
+
.join("");
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.53.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",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
],
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "node scripts/build.js",
|
|
45
|
-
"test": "node --test src/__tests__/contract.test.js src/__tests__/hooks-users.test.js src/__tests__/hooks-groups.test.js src/__tests__/hooks-schema.test.js src/__tests__/hooks-assets-by-tag.test.js src/__tests__/hooks-filestore-upload.test.js src/__tests__/hooks-mutation.test.js src/__tests__/hooks-record-permissions.test.js src/__tests__/hooks-geolocation.test.js src/__tests__/hooks-subscription.test.js src/__tests__/linter-users-scope.test.js src/__tests__/linter-comments.test.js src/__tests__/lucide-icon-names.test.js src/__tests__/manifest-actions.test.js src/__tests__/widget-translations.test.js src/__tests__/devserver.test.js src/__tests__/host-externals.test.js src/__tests__/datetimepicker.test.js"
|
|
45
|
+
"test": "node --test src/__tests__/contract.test.js src/__tests__/hooks-users.test.js src/__tests__/hooks-groups.test.js src/__tests__/hooks-schema.test.js src/__tests__/hooks-assets-by-tag.test.js src/__tests__/hooks-filestore-upload.test.js src/__tests__/hooks-mutation.test.js src/__tests__/hooks-record-permissions.test.js src/__tests__/hooks-geolocation.test.js src/__tests__/hooks-subscription.test.js src/__tests__/linter-users-scope.test.js src/__tests__/linter-comments.test.js src/__tests__/lucide-icon-names.test.js src/__tests__/lucideIconName.test.js src/__tests__/manifest-actions.test.js src/__tests__/widget-translations.test.js src/__tests__/devserver.test.js src/__tests__/host-externals.test.js src/__tests__/datetimepicker.test.js"
|
|
46
46
|
},
|
|
47
47
|
"engines": {
|
|
48
48
|
"node": ">=18"
|