@fluid-app/fluid-cli 0.1.13 → 0.1.14

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-app/fluid-cli",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Core CLI for Fluid Commerce — auth, config, and plugin system",
5
5
  "bin": {
6
6
  "fluid": "./dist/bin/fluid.mjs"
@@ -1,28 +1,29 @@
1
1
  ---
2
2
  name: fluid-widget-authoring
3
- description: Use when creating, modifying, reviewing, validating, building, or publishing Fluid widgets in generated portal projects or standalone widget projects, including manifest metadata, property schemas, runtime CSS, widget previews, validation, build, and publish workflows.
3
+ description: Use when creating, modifying, reviewing, validating, building, or publishing Fluid widgets in generated portal projects or standalone widget projects, including manifest metadata, property schemas, runtime CSS, development endpoints, validation, build, and publish workflows.
4
4
  ---
5
5
 
6
6
  # Fluid Widget Authoring
7
7
 
8
8
  Use this skill when creating, modifying, reviewing, validating, building, or publishing Fluid widgets.
9
9
 
10
- This skill supports two generated-project contexts:
10
+ This skill supports two generated-project contexts with different sources and
11
+ release commands:
11
12
 
12
- - **Generated portal projects:** use `pnpm widget:create <name>` or `pnpm exec fluid portal widget create <name>` for company-owned portal widgets. The scaffold writes widget source under `src/widgets/<name>/` and registers manifests through the portal config/tooling.
13
- - **Generated standalone widget projects:** use the widget CLI project structure and publish flow for droplet-owned or independently versioned widget packages.
13
+ - **Generated portal projects:** use `pnpm widget:create <name>` or `pnpm exec fluid portal widget create <name>` for company-owned portal widgets. The scaffold writes widget source under `src/widgets/<name>/`; `src/widgets.config.ts` is the package source consumed by `fluid portal deploy`.
14
+ - **Generated standalone widget projects:** use the widget CLI for droplet-owned packages. `manifest.ts` is the authoring source, `fluid.widget.config.ts` links ownership, and `fluid widget publish` releases the package.
14
15
 
15
16
  ## Boundaries
16
17
 
17
18
  - Widget code belongs under `src/widgets/` in both generated portal-widget scaffolds and standalone widget projects.
18
19
  - In generated portal projects, keep portal definition work in `portal/` and widget work in `src/widgets/`.
19
20
  - In standalone widget projects, do not add a portal app, droplet scaffold, backend, Rails code, or Next.js structure.
20
- - In standalone widget projects, package metadata lives in root `manifest.ts`, CLI ownership config lives in `fluid.widget.config.ts`, and runtime registration lives in `src/index.ts`.
21
- - Keep runtime CSS in `styles.css` or files imported by `manifest.ts`, widget manifests, or widget modules so build tooling discovers CSS artifacts.
21
+ - In standalone widget projects, package metadata lives in root `manifest.ts`, CLI ownership config lives in `fluid.widget.config.ts`, and the Remote DOM worker entry lives in `src/index.ts`.
22
+ - Keep runtime CSS in `styles.css` or files imported by the worker build graph. Standalone projects keep a guarded import in `src/index.ts` so build tooling emits CSS without running style injection inside the worker.
22
23
 
23
24
  ## Manifest checklist
24
25
 
25
- Use `defineWidget()` and `defineWidgetPackage()` from `@fluid-app/portal-sdk`.
26
+ Use `defineWidget()`, `defineWidgetPackage()`, and `startWidgetPackage()` from `@fluid-app/portal-sdk/widgets/worker`.
26
27
 
27
28
  For each widget:
28
29
 
@@ -32,12 +33,23 @@ For each widget:
32
33
  - `defaultProps`: JSON-serializable defaults only.
33
34
  - `propertySchema`: builder fields, also JSON-serializable.
34
35
  - `container`: `block`, `card`, `inline`, or `fullscreen`.
36
+ - `uses`: every typed portal function the widget calls. Pass the function values themselves; do not write capability names by hand.
35
37
  - `resizable`: omit/false, true, `horizontal`, `vertical`, `both`, or an object with axis flags and optional min sizes.
36
38
 
37
- For the package:
39
+ For a company package in a generated portal project:
40
+
41
+ - Keep the package definition in `src/widgets.config.ts`.
42
+ - Omit `packageType` or set it to `company`.
43
+ - Set a stable `packageStableId`; `defineWidgetPackage()` requires it for company packages.
44
+ - Do not add a worker entry. `fluid portal deploy` builds the company package into its Remote DOM worker artifact.
45
+
46
+ For a standalone droplet package:
38
47
 
39
48
  - Keep `packageType` as `droplet`.
40
- - Keep `remoteEntryUrl` as `widget.js` unless the publish flow changes.
49
+ - Keep the package definition in root `manifest.ts` and export it through `fluid.widget.config.ts`.
50
+ - Do not author runtime artifact URLs. Dev and build inject `workerEntryUrl` into the canonical package descriptor.
51
+ - Built manifests use package-local artifact paths; the catalog resolves them to absolute public URLs before a host loads the descriptor.
52
+ - Droplet package IDs remain fully qualified as `droplet.<linked-droplet-key>` in dev, build, and catalog output.
41
53
  - Keep `version` as SemVer without build metadata.
42
54
  - Keep at least one widget in `widgets`.
43
55
  - Do not manually set `packageStableId` in this generated droplet template; the CLI injects the linked droplet key.
@@ -129,11 +141,91 @@ Tailwind equivalents, when Tailwind is available, are semantic utilities such as
129
141
 
130
142
  Light/dark mode is controlled by host theme variables and may use `data-theme-mode="dark"`. Prefer tokens so light and dark work automatically. If a mode-specific rule is necessary, scope it to the dark-mode attribute and still use tokens.
131
143
 
132
- CSS must be imported by `manifest.ts` or a widget module. Prefix selectors with the widget name and do not rely on global body styles for published runtime output.
144
+ CSS must be reachable from `src/index.ts` or another worker module. Prefix selectors with the widget name and do not rely on global body styles for published runtime output.
145
+
146
+ ## Remote DOM runtime
147
+
148
+ - In a company portal project, `src/widgets.config.ts` is authoring input; the portal CLI generates the worker artifact. Do not add a hand-written worker bootstrap.
149
+ - In a standalone widget project, `src/index.ts` calls `startWidgetPackage(widgetPackage)` exactly once.
150
+ - Generated portals read company packages from the authenticated `/api/app/widget-packages` catalog.
151
+ - Standalone widget dev exposes `/__widget-packages__` as the local canonical descriptor endpoint and `/__runtime-entry__` as the worker entry. It does not bundle a second host or iframe preview application.
152
+ - Do not add global widget registries, classic script loaders, or direct React host previews.
153
+ - Call typed portal functions from `@fluid-app/portal-sdk/widgets/worker` directly and list each function in `defineWidget({ uses: [...] })`.
154
+
155
+ ## Typed portal functions
156
+
157
+ Built-in worker functions are `getUserAccount`, `getStore`, `getPortalApp`,
158
+ `getPortalProfile`, `getNavigationState`, `buildPortalHref`, `navigateTo`,
159
+ `getFullscreenState`, `requestFullscreen`, and `exitFullscreen`. Getters await
160
+ and return resolved data; they do not return query-status snapshots.
161
+
162
+ ```ts
163
+ import {
164
+ defineWidget,
165
+ getUserAccount,
166
+ navigateTo,
167
+ } from "@fluid-app/portal-sdk/widgets/worker";
168
+
169
+ async function openProfile(): Promise<void> {
170
+ const account = await getUserAccount();
171
+ await navigateTo(account.slug);
172
+ }
173
+
174
+ export const profileButton = defineWidget({
175
+ name: "ProfileButton",
176
+ component: ProfileButton,
177
+ uses: [getUserAccount, navigateTo],
178
+ });
179
+ ```
180
+
181
+ `defineWidget()` derives and deduplicates descriptor declarations from `uses`.
182
+ The worker and host both enforce those declarations. If a call fails with
183
+ `PortalFunctionError` code `NOT_DECLARED`, add the called function to that
184
+ widget's `uses` array. Do not author a raw `capabilities` array.
185
+
186
+ The account result is intentionally allowlisted. It may include email, but it
187
+ does not expose phone numbers, addresses, payment data, credentials,
188
+ government or tax identifiers, dates of birth, raw metadata, or unknown future
189
+ fields. There is no `tenantClient` worker API.
190
+
191
+ For a company-specific operation, create one typed function definition shared
192
+ by worker and host:
193
+
194
+ ```ts
195
+ export const getQuote = definePortalFunction<QuoteResult, QuoteRequest>({
196
+ capability: "company.example.quotes",
197
+ version: "1",
198
+ method: "get",
199
+ });
200
+ ```
201
+
202
+ Call `getQuote(input)` directly in the worker and include `getQuote` in `uses`.
203
+ The portal host installs the implementation with
204
+ `implementPortalFunction(getQuote, handler)` in `remoteWidgets.functions`.
205
+ Built-ins cannot be overridden and duplicate custom implementations are
206
+ rejected.
207
+
208
+ Custom inputs and outputs are JSON-only: null, booleans, finite numbers,
209
+ strings, arrays, and objects made from those values. Do not pass `undefined`,
210
+ functions, Dates, Maps, Sets, class instances, `NaN`, or `Infinity`. Types
211
+ describe the contract and runtime validation guards the protocol boundary.
212
+
213
+ ## Company portal widget preflight
133
214
 
134
- ## Preflight
215
+ In a generated portal project, validate and dry-run the company package with:
135
216
 
136
- Run before marking widget work complete:
217
+ ```bash
218
+ pnpm typecheck
219
+ pnpm build
220
+ pnpm exec fluid portal deploy --dry-run
221
+ ```
222
+
223
+ Publish company-owned runtime artifacts with `fluid portal deploy`. This does
224
+ not push `portal/` JSON or deploy the hosted portal shell.
225
+
226
+ ## Standalone droplet widget preflight
227
+
228
+ In a generated standalone widget project, run:
137
229
 
138
230
  ```bash
139
231
  pnpm typecheck
@@ -141,12 +233,15 @@ pnpm validate
141
233
  pnpm build
142
234
  ```
143
235
 
144
- For publish readiness, also run:
236
+ For standalone publish readiness, also run:
145
237
 
146
238
  ```bash
147
- pnpm run widget:publish -- --dry-run
239
+ pnpm run widget:publish --dry-run
148
240
  ```
149
241
 
242
+ Publish the linked droplet-owned package with `fluid widget publish`. Do not use
243
+ `fluid portal deploy` from a standalone project.
244
+
150
245
  Common failures:
151
246
 
152
247
  - Missing droplet UUID: run `pnpm run widget:link` or pass a droplet option.
@@ -154,5 +249,5 @@ Common failures:
154
249
  - Invalid package type: keep `packageType: "droplet"`.
155
250
  - Invalid name/key/version: use URL-safe identifiers and SemVer without build metadata.
156
251
  - Non-serializable metadata: remove functions, undefined, Dates, NaN, Infinity, Maps, Sets, and class instances.
157
- - Missing published CSS: import CSS from the build graph.
158
- - Preview-only success: remove local-only URLs and guard browser APIs.
252
+ - Missing published CSS: keep the guarded CSS import reachable from the worker build graph.
253
+ - Local development only succeeds: remove local-only URLs and guard browser APIs.