@statelyai/sdk 0.4.0 → 0.5.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/LICENSE +7 -675
- package/README.md +290 -159
- package/dist/cli.d.mts +24 -5
- package/dist/cli.mjs +79 -18
- package/dist/embed.d.mts +5 -3
- package/dist/embed.mjs +30 -10
- package/dist/graph.mjs +27 -19
- package/dist/{graphToXStateTS-C6HQUrBB.mjs → graphToXStateTS-BSUj97r0.mjs} +46 -19
- package/dist/index.d.mts +5 -34
- package/dist/index.mjs +2 -2
- package/dist/inspect-WUC2inmJ.d.mts +206 -0
- package/dist/inspect.d.mts +3 -49
- package/dist/inspect.mjs +229 -62
- package/dist/patchTypes.d.mts +225 -0
- package/dist/patchTypes.mjs +1 -0
- package/dist/protocol-B1cNV7QB.d.mts +397 -0
- package/dist/sync.mjs +1 -1
- package/dist/{transport-C1fRAuv-.mjs → transport-lomH7b0v.mjs} +14 -13
- package/package.json +14 -5
- package/dist/protocol-BgXSkIuc.d.mts +0 -221
package/README.md
CHANGED
|
@@ -1,16 +1,34 @@
|
|
|
1
1
|
# @statelyai/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<!-- package.json#name and #description — top-level summary -->
|
|
4
|
+
|
|
5
|
+
Embed the [Stately editor](https://stately.ai), inspect running actor systems over WebSockets, talk to the Stately Studio API, and convert between Studio graph data and code. Fully typed.
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
|
9
|
+
<!-- install command derived from package.json#name -->
|
|
10
|
+
|
|
7
11
|
```bash
|
|
8
12
|
npm install @statelyai/sdk
|
|
9
13
|
```
|
|
10
14
|
|
|
15
|
+
## What It Includes
|
|
16
|
+
|
|
17
|
+
<!-- top-level runtime exports from src/index.ts and CLI bin from package.json#bin -->
|
|
18
|
+
|
|
19
|
+
- `createStatelyEmbed()` for browser embeds backed by `postMessage`
|
|
20
|
+
- `createStatelyInspector()` for inspecting live actor systems over WebSockets
|
|
21
|
+
- `createStatelyClient()` for Stately Studio API access
|
|
22
|
+
- graph conversion and codegen helpers such as `fromStudioMachine()`, `toStudioMachine()`, `graphToMachineConfig()`, and `graphToXStateTS()`
|
|
23
|
+
- sync helpers under `@statelyai/sdk/sync` and a `statelyai` CLI binary
|
|
24
|
+
|
|
11
25
|
## Authentication
|
|
12
26
|
|
|
13
|
-
The
|
|
27
|
+
The embed supports three common deployment models:
|
|
28
|
+
|
|
29
|
+
- Hosted Stately: pass an API key to `createStatelyEmbed()`
|
|
30
|
+
- Same-origin deployments: rely on the host application's session/cookie auth
|
|
31
|
+
- Self-hosted deployments: configure auth in the editor server and omit `apiKey` when no token is required
|
|
14
32
|
|
|
15
33
|
### With Stately (default)
|
|
16
34
|
|
|
@@ -32,56 +50,38 @@ const embed = createStatelyEmbed({
|
|
|
32
50
|
});
|
|
33
51
|
```
|
|
34
52
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
### Self-hosting
|
|
38
|
-
|
|
39
|
-
When self-hosting the editor, authentication is controlled by the `AUTH_PROVIDER` environment variable on the server:
|
|
40
|
-
|
|
41
|
-
| Value | Behavior |
|
|
42
|
-
| ---------- | ----------------------------------------------------------- |
|
|
43
|
-
| `stately` | Validates tokens against the Stately registry API |
|
|
44
|
-
| `none` | Allows all requests (no authentication) |
|
|
45
|
-
| _(unset)_ | `none` in development, `stately` in production |
|
|
46
|
-
|
|
47
|
-
For a fully self-contained deployment with no Stately dependency:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
AUTH_PROVIDER=none
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Custom authentication
|
|
53
|
+
### Same-origin embed (cookie auth)
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
When the embed host and the editor share a domain, you can omit `apiKey` and rely on the host application's auth/session layer:
|
|
56
56
|
|
|
57
57
|
```ts
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const res = await fetch('https://my-auth-server.com/verify', {
|
|
62
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
63
|
-
});
|
|
64
|
-
return res.ok;
|
|
65
|
-
};
|
|
58
|
+
const embed = createStatelyEmbed({
|
|
59
|
+
baseUrl: process.env.NEXT_PUBLIC_BETA_EDITOR_URL ?? window.location.origin,
|
|
60
|
+
});
|
|
66
61
|
```
|
|
67
62
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
- **`createStatelyValidator(baseUrl?)`** — verifies against the Stately registry API (`/registry/api/v1/verify`)
|
|
71
|
-
- **`allowAllValidator`** — always returns `true`
|
|
63
|
+
### Self-hosting
|
|
72
64
|
|
|
73
|
-
|
|
65
|
+
When self-hosting the editor, authentication is enforced by the editor server, not by this npm package.
|
|
74
66
|
|
|
75
|
-
|
|
67
|
+
The common environment variables are:
|
|
76
68
|
|
|
77
69
|
| Variable | Purpose |
|
|
78
|
-
|
|
|
79
|
-
| `AUTH_PROVIDER` | Auth strategy
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| `AUTH_PROVIDER` | Auth strategy used by the editor host |
|
|
80
72
|
| `STATELY_API_KEY` | Server-side API key for Stately data fetching |
|
|
81
|
-
| `STATELY_API_URL` | Stately API base URL
|
|
82
|
-
| `NEXT_PUBLIC_BASE_URL` | Public-facing
|
|
73
|
+
| `STATELY_API_URL` | Stately API base URL override |
|
|
74
|
+
| `NEXT_PUBLIC_BASE_URL` | Public-facing editor URL |
|
|
83
75
|
|
|
84
|
-
|
|
76
|
+
For a fully self-contained deployment with no auth, omit `apiKey` in the SDK and configure the host/editor to allow unauthenticated access:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
const embed = createStatelyEmbed({
|
|
80
|
+
baseUrl: 'https://your-editor.example.com',
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Quick Start
|
|
85
85
|
|
|
86
86
|
### Third-party embed (with API key)
|
|
87
87
|
|
|
@@ -97,39 +97,15 @@ embed.mount(document.getElementById('editor')!);
|
|
|
97
97
|
|
|
98
98
|
embed.init({
|
|
99
99
|
machine: myMachineConfig,
|
|
100
|
+
format: 'xstate',
|
|
100
101
|
mode: 'editing',
|
|
101
102
|
theme: 'dark',
|
|
102
103
|
});
|
|
103
104
|
```
|
|
104
105
|
|
|
105
|
-
### Same-origin embed (cookie auth)
|
|
106
|
-
|
|
107
|
-
When the embed host and the editor share a domain (e.g. Stately Studio embedding the beta editor), Supabase session cookies handle auth automatically — no API key needed:
|
|
108
|
-
|
|
109
|
-
```ts
|
|
110
|
-
const embed = createStatelyEmbed({
|
|
111
|
-
baseUrl: process.env.NEXT_PUBLIC_BETA_EDITOR_URL ?? window.location.origin,
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
embed.mount(container);
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### Self-hosted (no auth)
|
|
118
|
-
|
|
119
|
-
When self-hosting with `AUTH_PROVIDER=none`, no token is required:
|
|
120
|
-
|
|
121
|
-
```ts
|
|
122
|
-
const embed = createStatelyEmbed({
|
|
123
|
-
baseUrl: 'https://your-editor.example.com',
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
embed.mount(container);
|
|
127
|
-
```
|
|
128
|
-
|
|
129
106
|
### Comments
|
|
130
107
|
|
|
131
|
-
Comments are optional and integrator-configured. Pass a `comments` object to
|
|
132
|
-
`embed.init()` when you want Liveblocks-backed commenting enabled.
|
|
108
|
+
Comments are optional and integrator-configured. Pass a `comments` object to `embed.init()` when you want Liveblocks-backed commenting enabled.
|
|
133
109
|
|
|
134
110
|
```ts
|
|
135
111
|
embed.init({
|
|
@@ -156,30 +132,38 @@ embed.init({
|
|
|
156
132
|
});
|
|
157
133
|
```
|
|
158
134
|
|
|
159
|
-
`roomId` is required when comments are enabled. `userId` is optional and only
|
|
160
|
-
|
|
135
|
+
`roomId` is required when comments are enabled. `userId` is optional and only used for comment identity metadata.
|
|
136
|
+
|
|
137
|
+
## Module Layout
|
|
161
138
|
|
|
162
|
-
|
|
139
|
+
<!-- subpath imports derived from package.json#exports -->
|
|
163
140
|
|
|
164
|
-
The SDK ships
|
|
141
|
+
The SDK ships root exports for the most common entry points and helpers:
|
|
165
142
|
|
|
166
143
|
```ts
|
|
167
144
|
import {
|
|
168
|
-
createStatelyInspector,
|
|
169
|
-
createStatelyEmbed,
|
|
170
145
|
createStatelyClient,
|
|
146
|
+
createStatelyEmbed,
|
|
147
|
+
createStatelyInspector,
|
|
148
|
+
fromStudioMachine,
|
|
149
|
+
graphToMachineConfig,
|
|
150
|
+
graphToXStateTS,
|
|
151
|
+
toStudioMachine,
|
|
171
152
|
} from '@statelyai/sdk';
|
|
172
153
|
```
|
|
173
154
|
|
|
174
|
-
It also supports subpath imports
|
|
155
|
+
It also supports narrower subpath imports:
|
|
175
156
|
|
|
176
157
|
```ts
|
|
177
158
|
import { createStatelyClient } from '@statelyai/sdk/studio';
|
|
178
159
|
import { createStatelyInspector } from '@statelyai/sdk/inspect';
|
|
179
160
|
import { createStatelyEmbed } from '@statelyai/sdk/embed';
|
|
161
|
+
import { fromStudioMachine, toStudioMachine } from '@statelyai/sdk/graph';
|
|
162
|
+
import { planSync, pullSync } from '@statelyai/sdk/sync';
|
|
163
|
+
import type { GraphPatch } from '@statelyai/sdk/patchTypes';
|
|
180
164
|
```
|
|
181
165
|
|
|
182
|
-
## Studio API
|
|
166
|
+
## Studio API Client
|
|
183
167
|
|
|
184
168
|
```ts
|
|
185
169
|
import { createStatelyClient } from '@statelyai/sdk';
|
|
@@ -193,35 +177,90 @@ const machine = await studio.machines.get('machine-id', { version: '42' });
|
|
|
193
177
|
const extracted = await studio.code.extractMachines(sourceCode);
|
|
194
178
|
```
|
|
195
179
|
|
|
196
|
-
|
|
180
|
+
<!-- public methods of StudioClient from src/studio.ts -->
|
|
181
|
+
|
|
182
|
+
Available client methods:
|
|
183
|
+
|
|
184
|
+
| Method | Description |
|
|
185
|
+
| --- | --- |
|
|
186
|
+
| `studio.auth.verify(apiKey?)` | Verify an API key against the registry API |
|
|
187
|
+
| `studio.projects.get(projectId)` | Fetch a project and its machines |
|
|
188
|
+
| `studio.machines.get(machineId, { version? })` | Fetch a machine, optionally pinned to a version |
|
|
189
|
+
| `studio.code.extractMachines(code, { apiKey? })` | Extract machine configs from source text |
|
|
190
|
+
|
|
191
|
+
## Inspector
|
|
192
|
+
|
|
193
|
+
<!-- public API of createStatelyInspector from src/inspect.ts -->
|
|
194
|
+
|
|
195
|
+
`createStatelyInspector()` streams actor-system state to the Stately inspector over WebSockets. It supports both automatic XState actor adoption and manual actor registration.
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import { createActor } from 'xstate';
|
|
199
|
+
import { createStatelyInspector } from '@statelyai/sdk';
|
|
200
|
+
|
|
201
|
+
const actor = createActor(machine);
|
|
202
|
+
const inspector = createStatelyInspector({
|
|
203
|
+
actor,
|
|
204
|
+
url: 'ws://localhost:4242',
|
|
205
|
+
autoOpen: true,
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
actor.start();
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Key options:
|
|
212
|
+
|
|
213
|
+
| Option | Description |
|
|
214
|
+
| --- | --- |
|
|
215
|
+
| `actor` | Root actor to adopt and inspect automatically |
|
|
216
|
+
| `url` | Devtools relay URL. Defaults to `ws://localhost:4242` |
|
|
217
|
+
| `autoOpen` | Whether to ask the relay to open the inspector UI |
|
|
218
|
+
| `sessionId` | Override the relay session id |
|
|
219
|
+
| `name` | Display name shown to the inspector |
|
|
220
|
+
| `serializeSnapshot` | Customize snapshot serialization before sending it over the wire |
|
|
221
|
+
| `extractMachineConfig` | Customize how machine config is derived from an actor |
|
|
222
|
+
| `selectedActorId` | Focus a specific actor first |
|
|
223
|
+
| `panels`, `theme`, `readOnly`, `depth` | Initial inspector UI options |
|
|
224
|
+
| `transport` | Inject an existing transport instead of opening a new WebSocket |
|
|
225
|
+
|
|
226
|
+
Key methods:
|
|
227
|
+
|
|
228
|
+
- `inspector.export(format, options?)`
|
|
229
|
+
- `inspector.actor(id, options?)`
|
|
230
|
+
- `inspector.snapshot(actorId, snapshot, event?)`
|
|
231
|
+
- `inspector.event(actorId, event, { source? })`
|
|
232
|
+
- `inspector.stop(actorId)`
|
|
233
|
+
- `inspector.destroy()`
|
|
234
|
+
|
|
235
|
+
## Embed API
|
|
197
236
|
|
|
198
237
|
### `createStatelyEmbed(options)`
|
|
199
238
|
|
|
200
239
|
Creates an embed instance.
|
|
201
240
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
|
205
|
-
|
|
|
206
|
-
| `
|
|
207
|
-
| `
|
|
208
|
-
| `
|
|
209
|
-
| `
|
|
210
|
-
| `
|
|
211
|
-
| `
|
|
212
|
-
| `
|
|
241
|
+
<!-- public options of StatelyEmbedOptions from src/embed.ts -->
|
|
242
|
+
|
|
243
|
+
| Option | Type | Description |
|
|
244
|
+
| --- | --- | --- |
|
|
245
|
+
| `baseUrl` | `string` | **Required.** Base URL of the Stately app |
|
|
246
|
+
| `apiKey` | `string` | API key for hosted Stately deployments |
|
|
247
|
+
| `origin` | `string` | Optional strict target origin for `postMessage`; defaults to permissive wildcard messaging for local/self-hosted testing |
|
|
248
|
+
| `assets` | `AssetConfig` | Asset upload configuration |
|
|
249
|
+
| `onReady` | `() => void` | Called when the embed is ready |
|
|
250
|
+
| `onLoaded` | `(graph) => void` | Called when a machine is loaded |
|
|
251
|
+
| `onChange` | `(graph, machineConfig) => void` | Called on every change |
|
|
252
|
+
| `onSave` | `(graph, machineConfig) => void` | Called on save |
|
|
253
|
+
| `onError` | `({ code, message }) => void` | Called when the embed reports an error |
|
|
213
254
|
|
|
214
255
|
### Embed methods
|
|
215
256
|
|
|
216
257
|
#### `embed.mount(container)` / `embed.attach(iframe)`
|
|
217
258
|
|
|
218
|
-
|
|
259
|
+
`mount()` creates an iframe inside a container element. `attach()` connects to an existing iframe.
|
|
219
260
|
|
|
220
261
|
```ts
|
|
221
|
-
// Create a new iframe
|
|
222
262
|
const iframe = embed.mount(document.getElementById('editor')!);
|
|
223
263
|
|
|
224
|
-
// Or attach to an existing one
|
|
225
264
|
embed.attach(document.querySelector('iframe')!);
|
|
226
265
|
```
|
|
227
266
|
|
|
@@ -232,9 +271,9 @@ Initialize the embed with a machine and display options.
|
|
|
232
271
|
```ts
|
|
233
272
|
embed.init({
|
|
234
273
|
machine: machineConfig,
|
|
235
|
-
format: 'xstate',
|
|
236
|
-
mode: 'editing',
|
|
237
|
-
theme: 'dark',
|
|
274
|
+
format: 'xstate',
|
|
275
|
+
mode: 'editing',
|
|
276
|
+
theme: 'dark',
|
|
238
277
|
readOnly: false,
|
|
239
278
|
depth: 3,
|
|
240
279
|
panels: {
|
|
@@ -242,6 +281,10 @@ embed.init({
|
|
|
242
281
|
rightPanels: ['events'],
|
|
243
282
|
activePanels: ['code'],
|
|
244
283
|
},
|
|
284
|
+
unsavedIndicator: {
|
|
285
|
+
enabled: true,
|
|
286
|
+
mode: 'structural',
|
|
287
|
+
},
|
|
245
288
|
comments: {
|
|
246
289
|
roomId: 'machine:checkout',
|
|
247
290
|
publicApiKey: 'pk_live_...',
|
|
@@ -252,13 +295,20 @@ embed.init({
|
|
|
252
295
|
`comments` accepts:
|
|
253
296
|
|
|
254
297
|
| Field | Type | Description |
|
|
255
|
-
|
|
|
298
|
+
| --- | --- | --- |
|
|
256
299
|
| `roomId` | `string` | **Required.** Liveblocks room identifier |
|
|
257
300
|
| `publicApiKey` | `string` | Liveblocks public key |
|
|
258
301
|
| `authEndpoint` | `string` | Custom Liveblocks auth endpoint |
|
|
259
302
|
| `baseUrl` | `string` | Custom Liveblocks base URL for self-hosting |
|
|
260
303
|
| `userId` | `string \| null` | Optional user identity metadata |
|
|
261
304
|
|
|
305
|
+
`unsavedIndicator` accepts:
|
|
306
|
+
|
|
307
|
+
| Field | Type | Description |
|
|
308
|
+
| --- | --- | --- |
|
|
309
|
+
| `enabled` | `boolean` | Show the persistent "Save to apply" pill |
|
|
310
|
+
| `mode` | `'structural' \| 'all'` | Track only structural graph edits or all edits |
|
|
311
|
+
|
|
262
312
|
#### `embed.updateMachine(machine, format?)`
|
|
263
313
|
|
|
264
314
|
Update the displayed machine.
|
|
@@ -267,25 +317,60 @@ Update the displayed machine.
|
|
|
267
317
|
|
|
268
318
|
Change the embed mode or theme at runtime.
|
|
269
319
|
|
|
320
|
+
#### `embed.setSettings(settings)`
|
|
321
|
+
|
|
322
|
+
Update editor settings at runtime. Settings are merged with the existing editor settings.
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
embed.setSettings({
|
|
326
|
+
appearance: { colorMode: 'light' },
|
|
327
|
+
canvas: { showGrid: false },
|
|
328
|
+
});
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Available core settings:
|
|
332
|
+
|
|
333
|
+
| Path | Type | Default |
|
|
334
|
+
| --- | --- | --- |
|
|
335
|
+
| `appearance.colorMode` | `'light' \| 'dark' \| 'system'` | `'dark'` |
|
|
336
|
+
| `canvas.showGrid` | `boolean` | `true` |
|
|
337
|
+
| `canvas.viewMode` | `'graph' \| 'list'` | `'graph'` |
|
|
338
|
+
| `canvas.enableSnapLines` | `boolean` | `true` |
|
|
339
|
+
| `canvas.dimUnselected` | `boolean` | `true` |
|
|
340
|
+
| `validation.showValidations` | `boolean` | `true` |
|
|
341
|
+
| `autolayout.autoEnabled` | `boolean` | `false` |
|
|
342
|
+
| `developer.devMode` | `boolean` | `false` |
|
|
343
|
+
|
|
270
344
|
#### `embed.export(format, options?)`
|
|
271
345
|
|
|
272
346
|
Export the current machine. Returns a promise.
|
|
273
347
|
|
|
274
348
|
```ts
|
|
275
|
-
const
|
|
276
|
-
const
|
|
277
|
-
const
|
|
349
|
+
const xstateCode = await embed.export('xstate', { version: 5 });
|
|
350
|
+
const digraph = await embed.export('digraph');
|
|
351
|
+
const rtk = await embed.export('rtk');
|
|
352
|
+
const aslYaml = await embed.export('asl-yaml');
|
|
278
353
|
```
|
|
279
354
|
|
|
280
|
-
|
|
355
|
+
<!-- supported export formats from ExportFormatMap in src/protocol.ts -->
|
|
356
|
+
|
|
357
|
+
Supported formats: `xstate`, `json`, `digraph`, `mermaid`, `rtk`, `zustand`, `asl-json`, `asl-yaml`, `scxml`
|
|
281
358
|
|
|
282
359
|
#### `embed.on(event, handler)` / `embed.off(event, handler)`
|
|
283
360
|
|
|
284
|
-
|
|
361
|
+
<!-- keys of EmbedEventMap in src/protocol.ts -->
|
|
362
|
+
|
|
363
|
+
Event names are `ready`, `loaded`, `change`, `save`, `error`, and `snapshot`.
|
|
364
|
+
|
|
365
|
+
`createStatelyEmbed()` emits `ready`, `loaded`, `change`, `save`, and `error` for browser embeds:
|
|
285
366
|
|
|
286
367
|
```ts
|
|
287
|
-
embed.on('change', ({ graph, machineConfig }) => {
|
|
288
|
-
console.log('Machine changed', machineConfig);
|
|
368
|
+
embed.on('change', ({ graph, machineConfig, patches }) => {
|
|
369
|
+
console.log('Machine changed', graph, machineConfig, patches);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
embed.on('save', ({ validations }) => {
|
|
373
|
+
console.log('Save validations', validations);
|
|
289
374
|
});
|
|
290
375
|
```
|
|
291
376
|
|
|
@@ -299,96 +384,142 @@ Tear down the embed. Removes listeners, rejects pending promises, and removes th
|
|
|
299
384
|
|
|
300
385
|
### Asset uploads
|
|
301
386
|
|
|
302
|
-
By default, dropped
|
|
387
|
+
By default, dropped files are stored as base64 data URLs. To upload assets to your own storage, pass an `assets` config:
|
|
303
388
|
|
|
304
389
|
```ts
|
|
305
390
|
const embed = createStatelyEmbed({
|
|
306
391
|
baseUrl: 'https://stately.ai',
|
|
307
392
|
assets: {
|
|
308
393
|
onUploadRequest: async (file, { stateNodeId }) => {
|
|
309
|
-
|
|
310
|
-
// return { url } at minimum
|
|
394
|
+
return { url: await uploadToStorage(file, stateNodeId) };
|
|
311
395
|
},
|
|
312
|
-
accept: ['image/*'],
|
|
313
|
-
maxFileSize: 5 * 1024 * 1024,
|
|
396
|
+
accept: ['image/*'],
|
|
397
|
+
maxFileSize: 5 * 1024 * 1024,
|
|
314
398
|
},
|
|
315
399
|
});
|
|
316
400
|
```
|
|
317
401
|
|
|
318
402
|
| Option | Type | Description |
|
|
319
403
|
| --- | --- | --- |
|
|
320
|
-
| `onUploadRequest` | `(file: File, context: { stateNodeId: string }) => Promise<UploadResult>` | **Required.** Called when the editor needs to upload a file
|
|
321
|
-
| `accept` | `string[]` | Accepted MIME types. Supports wildcards
|
|
322
|
-
| `maxFileSize` | `number` | Max file size in bytes.
|
|
404
|
+
| `onUploadRequest` | `(file: File, context: { stateNodeId: string }) => Promise<UploadResult>` | **Required.** Called when the editor needs to upload a file |
|
|
405
|
+
| `accept` | `string[]` | Accepted MIME types. Supports wildcards like `image/*` |
|
|
406
|
+
| `maxFileSize` | `number` | Max file size in bytes. Defaults to `10_485_760` |
|
|
323
407
|
|
|
324
408
|
`UploadResult`:
|
|
325
409
|
|
|
326
410
|
```ts
|
|
327
411
|
interface UploadResult {
|
|
328
|
-
url: string;
|
|
329
|
-
name?: string;
|
|
330
|
-
metadata?: Record<string, unknown>;
|
|
412
|
+
url: string;
|
|
413
|
+
name?: string;
|
|
414
|
+
metadata?: Record<string, unknown>;
|
|
331
415
|
}
|
|
332
416
|
```
|
|
333
417
|
|
|
334
|
-
|
|
418
|
+
If `onUploadRequest` throws or rejects, the editor shows an error toast. If no `assets` config is provided, files are stored inline and no upload request is sent.
|
|
419
|
+
|
|
420
|
+
## Graph And Codegen Helpers
|
|
421
|
+
|
|
422
|
+
<!-- root helper exports from src/index.ts -->
|
|
423
|
+
|
|
424
|
+
Use the conversion helpers to move between Studio digraph data, generic Stately graphs, machine config objects, and XState TypeScript source.
|
|
335
425
|
|
|
336
426
|
```ts
|
|
337
|
-
import {
|
|
427
|
+
import {
|
|
428
|
+
fromStudioMachine,
|
|
429
|
+
graphToMachineConfig,
|
|
430
|
+
graphToXStateTS,
|
|
431
|
+
toStudioMachine,
|
|
432
|
+
} from '@statelyai/sdk';
|
|
338
433
|
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
headers: { 'Content-Type': 'application/json' },
|
|
347
|
-
body: JSON.stringify({
|
|
348
|
-
filename: file.name,
|
|
349
|
-
contentType: file.type,
|
|
350
|
-
}),
|
|
351
|
-
}).then((r) => r.json());
|
|
352
|
-
|
|
353
|
-
// 2. PUT the file directly to S3
|
|
354
|
-
await fetch(uploadUrl, {
|
|
355
|
-
method: 'PUT',
|
|
356
|
-
headers: { 'Content-Type': file.type },
|
|
357
|
-
body: file,
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
return { url: publicUrl, name: file.name };
|
|
361
|
-
},
|
|
362
|
-
accept: ['image/*'],
|
|
363
|
-
maxFileSize: 10 * 1024 * 1024,
|
|
364
|
-
},
|
|
434
|
+
const graph = fromStudioMachine(studioMachine);
|
|
435
|
+
const machineConfig = graphToMachineConfig(graph, {
|
|
436
|
+
showDescriptions: true,
|
|
437
|
+
showMeta: true,
|
|
438
|
+
});
|
|
439
|
+
const source = graphToXStateTS(graph, {
|
|
440
|
+
exportStyle: 'named',
|
|
365
441
|
});
|
|
442
|
+
const digraph = toStudioMachine(graph);
|
|
366
443
|
```
|
|
367
444
|
|
|
368
|
-
|
|
445
|
+
Other exported helpers:
|
|
446
|
+
|
|
447
|
+
- `studioMachineConverter` for reusable format conversion
|
|
448
|
+
- `serializeJS()`, `raw()`, and `RawCode` for emitting JavaScript source
|
|
449
|
+
- `jsonSchemaToTSType()`, `contextSchemaToTSType()`, and `eventsSchemaToTSType()` for generating inline TypeScript types from JSON Schema
|
|
450
|
+
- `GraphPatch` and `ActionLocation` types from `@statelyai/sdk/patchTypes`
|
|
451
|
+
|
|
452
|
+
## Sync Helpers And CLI
|
|
453
|
+
|
|
454
|
+
<!-- sync helpers from src/sync.ts and CLI commands from src/cli.ts#COMMANDS -->
|
|
455
|
+
|
|
456
|
+
The sync helpers compare or materialize machines across local files, Stately machine IDs, and Stately URLs.
|
|
457
|
+
|
|
458
|
+
Programmatic usage:
|
|
369
459
|
|
|
370
460
|
```ts
|
|
371
|
-
import {
|
|
461
|
+
import { planSync, pullSync } from '@statelyai/sdk/sync';
|
|
372
462
|
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
form.append('file', file);
|
|
463
|
+
const plan = await planSync({
|
|
464
|
+
source: './checkout.machine.ts',
|
|
465
|
+
target: 'machine-id',
|
|
466
|
+
apiKey: process.env.STATELY_API_KEY,
|
|
467
|
+
});
|
|
379
468
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
body: form,
|
|
384
|
-
}).then((r) => r.json());
|
|
469
|
+
if (plan.summary.hasChanges) {
|
|
470
|
+
console.log(plan.summary);
|
|
471
|
+
}
|
|
385
472
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
},
|
|
473
|
+
await pullSync({
|
|
474
|
+
source: 'machine-id',
|
|
475
|
+
target: './checkout.machine.ts',
|
|
476
|
+
apiKey: process.env.STATELY_API_KEY,
|
|
391
477
|
});
|
|
392
478
|
```
|
|
393
479
|
|
|
394
|
-
|
|
480
|
+
Supported locators:
|
|
481
|
+
|
|
482
|
+
- local files
|
|
483
|
+
- Stately machine IDs
|
|
484
|
+
- full Stately machine URLs
|
|
485
|
+
|
|
486
|
+
Installing the package also exposes a `statelyai` binary:
|
|
487
|
+
|
|
488
|
+
```bash
|
|
489
|
+
npx statelyai open ./checkout.machine.ts
|
|
490
|
+
|
|
491
|
+
statelyai plan ./checkout.machine.ts machine-id
|
|
492
|
+
statelyai diff ./checkout.machine.ts machine-id --fail-on-changes
|
|
493
|
+
statelyai pull machine-id ./checkout.machine.ts
|
|
494
|
+
statelyai open ./checkout.machine.ts
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
For one-off use, `npx statelyai ...` installs the small `statelyai` CLI package, which delegates to this SDK CLI.
|
|
498
|
+
|
|
499
|
+
Available commands:
|
|
500
|
+
|
|
501
|
+
| Command | Description |
|
|
502
|
+
| --- | --- |
|
|
503
|
+
| `statelyai plan <source> <target>` | Print a semantic sync summary |
|
|
504
|
+
| `statelyai diff <source> <target>` | Diff two locators and optionally fail on changes |
|
|
505
|
+
| `statelyai pull <source> <target>` | Materialize a source into a local target file |
|
|
506
|
+
| `statelyai open <file>` | Open a local file in a browser-backed visual editor session |
|
|
507
|
+
|
|
508
|
+
Common flags:
|
|
509
|
+
|
|
510
|
+
- `--api-key` for remote machine resolution
|
|
511
|
+
- `--base-url` for self-hosted or non-default Stately deployments
|
|
512
|
+
- `--fail-on-changes` to return a nonzero exit code when a diff is detected
|
|
513
|
+
|
|
514
|
+
`statelyai open` also supports `--editor-url`, `--host`, `--port`, `--no-open`, and `--debug`. It watches the local file on disk, updates the visual editor after saved source changes, and writes saved visual edits back to source.
|
|
515
|
+
|
|
516
|
+
## Transport Helpers
|
|
517
|
+
|
|
518
|
+
<!-- transport helpers exported from src/index.ts -->
|
|
519
|
+
|
|
520
|
+
For advanced integrations, the root package also exports:
|
|
521
|
+
|
|
522
|
+
- `createPostMessageTransport()` for iframe-based clients
|
|
523
|
+
- `createWebSocketTransport()` for relay-based integrations
|
|
524
|
+
|
|
525
|
+
These power the embed and inspector internals, but they are also available when you need lower-level control over the `@statelyai.*` protocol.
|
package/dist/cli.d.mts
CHANGED
|
@@ -10,16 +10,16 @@ declare abstract class BaseSyncCommand extends Command {
|
|
|
10
10
|
static flags: {
|
|
11
11
|
help: _oclif_core_interfaces0.BooleanFlag<void>;
|
|
12
12
|
'fail-on-changes': _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
13
|
-
'api-key': _oclif_core_interfaces0.OptionFlag<string, _oclif_core_interfaces0.CustomOptions>;
|
|
14
|
-
'base-url': _oclif_core_interfaces0.OptionFlag<string, _oclif_core_interfaces0.CustomOptions>;
|
|
13
|
+
'api-key': _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
14
|
+
'base-url': _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
declare abstract class ParsedSyncCommand extends BaseSyncCommand {
|
|
18
18
|
protected parseSync<T extends typeof BaseSyncCommand>(command: T): Promise<_oclif_core_interfaces0.ParserOutput<{
|
|
19
19
|
help: void;
|
|
20
20
|
'fail-on-changes': boolean;
|
|
21
|
-
'api-key': string;
|
|
22
|
-
'base-url': string;
|
|
21
|
+
'api-key': string | undefined;
|
|
22
|
+
'base-url': string | undefined;
|
|
23
23
|
}, {
|
|
24
24
|
[flag: string]: any;
|
|
25
25
|
}, {
|
|
@@ -53,11 +53,30 @@ declare class PullCommand extends ParsedSyncCommand {
|
|
|
53
53
|
};
|
|
54
54
|
run(): Promise<void>;
|
|
55
55
|
}
|
|
56
|
+
declare class OpenCommand extends Command {
|
|
57
|
+
static enableJsonFlag: boolean;
|
|
58
|
+
static summary: string;
|
|
59
|
+
static description: string;
|
|
60
|
+
static args: {
|
|
61
|
+
file: _oclif_core_interfaces0.Arg<string, Record<string, unknown>>;
|
|
62
|
+
};
|
|
63
|
+
static flags: {
|
|
64
|
+
help: _oclif_core_interfaces0.BooleanFlag<void>;
|
|
65
|
+
'api-key': _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
66
|
+
'editor-url': _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
67
|
+
host: _oclif_core_interfaces0.OptionFlag<string, _oclif_core_interfaces0.CustomOptions>;
|
|
68
|
+
port: _oclif_core_interfaces0.OptionFlag<number, _oclif_core_interfaces0.CustomOptions>;
|
|
69
|
+
open: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
70
|
+
debug: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
71
|
+
};
|
|
72
|
+
run(): Promise<void>;
|
|
73
|
+
}
|
|
56
74
|
declare const COMMANDS: {
|
|
57
75
|
plan: typeof PlanCommand;
|
|
58
76
|
diff: typeof DiffCommand;
|
|
59
77
|
pull: typeof PullCommand;
|
|
78
|
+
open: typeof OpenCommand;
|
|
60
79
|
};
|
|
61
|
-
declare function run(argv?: string[]): Promise<void>;
|
|
80
|
+
declare function run(argv?: string[], entryUrl?: string): Promise<void>;
|
|
62
81
|
//#endregion
|
|
63
82
|
export { COMMANDS, formatPlanSummary, run };
|