@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,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,
|
|
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
|
|
13
|
-
- **Generated standalone widget projects:** use the widget CLI
|
|
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
|
|
21
|
-
- Keep runtime CSS in `styles.css` or files imported by
|
|
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 `
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
215
|
+
In a generated portal project, validate and dry-run the company package with:
|
|
135
216
|
|
|
136
|
-
|
|
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 --
|
|
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:
|
|
158
|
-
-
|
|
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.
|