@colixsystems/widget-sdk 0.1.0 → 0.3.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 CHANGED
@@ -6,7 +6,11 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
6
6
 
7
7
  ## Status
8
8
 
9
- `v0.1.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**.
9
+ `v0.3.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**.
10
+
11
+ ### What's new in 0.3.0
12
+
13
+ Additive: `WidgetManifest` now carries an optional `datastoreTemplate` field. When a tenant installs a widget that declares one, the table set is seeded into their workspace alongside the install. Tables follow the existing built-in template semantics (auto-suffixed naming, REQ-ACL-05 creator-grants, REQ-TEMPLATES-ACL public grants, REQ-ACL-RELINHERIT cross-relation inheritance) and persist when the widget is later uninstalled. See `WidgetDatastoreTemplate` in `src/index.d.ts` for the structural constraints — at most 8 tables per widget, 24 columns per table, RELATION columns address siblings by `suffix`.
10
14
 
11
15
  ## Public API
12
16
 
package/dist/index.d.ts CHANGED
@@ -54,6 +54,71 @@ export interface WidgetEventDescriptor {
54
54
  payloadSchema?: WidgetPropertySchema;
55
55
  }
56
56
 
57
+ /**
58
+ * Optional datastore template a widget can ship in its manifest. When the
59
+ * tenant installs the widget, every declared table is created in their
60
+ * workspace alongside the WidgetInstallation row, named
61
+ * `<widgetDisplayName>_<suffix>` (auto-suffixed `_2`/`_3`/... on name
62
+ * collisions). The tables persist when the widget is uninstalled — the
63
+ * tenant may have authored records into them.
64
+ *
65
+ * The shape mirrors the built-in template registry on the backend, with
66
+ * two limits a third-party widget must satisfy (enforced at submission
67
+ * time by the static analyzer):
68
+ *
69
+ * - At most 8 tables per widget. Templates exist to seed schema, not
70
+ * to be a full database design tool.
71
+ * - At most 24 columns per table. Same reason.
72
+ *
73
+ * RELATION columns reference siblings within the same template via
74
+ * `targetSuffix` — that suffix MUST belong to a table declared earlier
75
+ * in the array. There is intentionally no way to reference a table
76
+ * outside the widget's own template.
77
+ */
78
+ export interface WidgetDatastoreTemplateColumn {
79
+ name: string;
80
+ dataType:
81
+ | "STRING"
82
+ | "TEXT"
83
+ | "NUMBER"
84
+ | "FLOAT"
85
+ | "BOOL"
86
+ | "DATE"
87
+ | "FILE"
88
+ | "STRING_ARRAY"
89
+ | "INT_ARRAY"
90
+ | "RELATION"
91
+ | "USER"
92
+ | "USER_GROUP";
93
+ required?: boolean;
94
+ /** For RELATION columns only — points at a sibling table's `suffix`. */
95
+ targetSuffix?: string;
96
+ /** For RELATION columns only. */
97
+ relationType?: "ONE_TO_ONE" | "ONE_TO_MANY" | "MANY_TO_MANY";
98
+ /** REQ-ACL-RELINHERIT: opt this RELATION column into row-level ACL inheritance. */
99
+ inheritAcl?: boolean;
100
+ }
101
+
102
+ export interface WidgetDatastoreTemplateTable {
103
+ /** Stable identifier within the template; appears in the created table name. */
104
+ suffix: string;
105
+ /** REQ-ACL-05: when true, the row creator gets full RWD+G on the new record. */
106
+ grantCreatorPermissions?: boolean;
107
+ /**
108
+ * REQ-TEMPLATES-ACL: optional table-level public grant. Omitted means
109
+ * the table starts purely per-record (record-level grants are the only
110
+ * access path). canRead opens reads to everyone (including anonymous);
111
+ * canWrite only lets authenticated APP_USERs insert; canDelete remains
112
+ * studio-owner only regardless.
113
+ */
114
+ publicGrant?: { canRead?: boolean; canWrite?: boolean; canDelete?: boolean };
115
+ columns: WidgetDatastoreTemplateColumn[];
116
+ }
117
+
118
+ export interface WidgetDatastoreTemplate {
119
+ tables: WidgetDatastoreTemplateTable[];
120
+ }
121
+
57
122
  export interface WidgetManifest {
58
123
  id: string;
59
124
  name: string;
@@ -67,6 +132,14 @@ export interface WidgetManifest {
67
132
  requestedScopes: WidgetScope[];
68
133
  propertySchema: WidgetPropertySchema;
69
134
  events: WidgetEventDescriptor[];
135
+ /**
136
+ * Optional datastore template seeded into the tenant's workspace when
137
+ * the widget is installed. The author wires the resulting tables into
138
+ * the widget's `tableRef` properties via the Properties Panel — the
139
+ * SDK does not auto-bind them. See `WidgetDatastoreTemplate` for the
140
+ * structural constraints enforced at submission time.
141
+ */
142
+ datastoreTemplate?: WidgetDatastoreTemplate;
70
143
  }
71
144
 
72
145
  export interface ThemeTokens {
@@ -118,15 +191,38 @@ export interface WidgetContext<TProps = unknown> {
118
191
  };
119
192
  }
120
193
 
121
- export interface WidgetModule<TProps = unknown> {
194
+ /**
195
+ * The widget's component receives the author-authored props **as React
196
+ * props** — the same shape and calling convention every built-in widget
197
+ * uses (`<MetricWidget tableId={...} sumField={...} />`). Everything
198
+ * else from `WidgetContext` (datastore, user, workspace, navigation,
199
+ * i18n, …) is reachable via the SDK hooks (`useDatastoreMutation`,
200
+ * `useDatastoreQuery`, `useTheme`, `useI18n`, `useWidgetEvent`), which
201
+ * read from the host-mounted `WidgetContextProvider`.
202
+ *
203
+ * function Counter({ tableId }) { // ← props
204
+ * const mut = useDatastoreMutation(tableId); // ← rest via hook
205
+ * const { t } = useI18n();
206
+ * return ...;
207
+ * }
208
+ *
209
+ * Note: earlier versions of this typing passed the entire
210
+ * `WidgetContext` as the first argument. That was changed to the props-
211
+ * spread form so marketplace widgets follow the same interface as
212
+ * built-ins. Widgets that previously did `function Widget(ctx) { const
213
+ * { table } = ctx.props; }` should rewrite to
214
+ * `function Widget({ table }) { … }` and reach for hooks for anything
215
+ * else they need.
216
+ */
217
+ export interface WidgetModule<TProps = Record<string, unknown>> {
122
218
  manifest: WidgetManifest;
123
- component: (ctx: WidgetContext<TProps>) => JSX.Element;
219
+ component: (props: TProps) => JSX.Element;
124
220
  _kind: "appstudio-widget-module";
125
221
  }
126
222
 
127
- export function defineWidget<TProps = unknown>(opts: {
223
+ export function defineWidget<TProps = Record<string, unknown>>(opts: {
128
224
  manifest: WidgetManifest;
129
- component: (ctx: WidgetContext<TProps>) => JSX.Element;
225
+ component: (props: TProps) => JSX.Element;
130
226
  }): WidgetModule<TProps>;
131
227
 
132
228
  export function validateManifest(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colixsystems/widget-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.3.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",