@statelyai/sdk 0.7.1 → 0.9.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 +12 -637
- package/dist/assetStorage.d.mts +1 -1
- package/dist/embed.d.mts +1 -1
- package/dist/embed.mjs +1 -1
- package/dist/graph.d.mts +1 -1
- package/dist/{graphToXStateTS-Gzh0ZqbN.mjs → graphToXStateTS-moihsH_U.mjs} +17 -16
- package/dist/index.d.mts +144 -5
- package/dist/index.mjs +2 -2
- package/dist/{inspect-YoEwfiKb.d.mts → inspect-BLlM3qKf.d.mts} +1 -1
- package/dist/inspect.d.mts +2 -2
- package/dist/inspect.mjs +1 -1
- package/dist/{protocol-s9zwsiCW.d.mts → protocol.d.mts} +2 -1
- package/dist/protocol.mjs +5 -0
- package/dist/sync.d.mts +1 -1
- package/dist/sync.mjs +1254 -3
- package/dist/{transport-C8UTS3Fa.mjs → transport-CVZGF0w9.mjs} +2 -4
- package/package.json +5 -18
- package/schemas/statelyai.schema.json +13 -72
- package/dist/cli.d.mts +0 -203
- package/dist/cli.mjs +0 -1760
- package/dist/sync-DLkTmSyA.mjs +0 -2513
- /package/dist/{graph-zuNj3kfa.d.mts → graph-CJ3N2r43.d.mts} +0 -0
package/README.md
CHANGED
|
@@ -1,651 +1,26 @@
|
|
|
1
1
|
# @statelyai/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Shared SDK modules for Stately clients, sync helpers, graph conversion, and code generation.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The Stately CLI now lives in:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- `statelyai`
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
If you want the command-line workflow, use:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
|
|
12
|
+
npx statelyai --help
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
This package is the programmatic dependency used by that CLI.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
The broader in-progress package documentation draft is kept in:
|
|
18
18
|
|
|
19
|
-
-
|
|
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
|
|
19
|
+
- [README-next.md](./README-next.md)
|
|
24
20
|
|
|
25
|
-
|
|
21
|
+
Published schemas:
|
|
26
22
|
|
|
27
|
-
|
|
23
|
+
- `@statelyai/sdk/statelyai.schema.json`
|
|
24
|
+
- `@statelyai/sdk/xstate-json.schema.json`
|
|
28
25
|
|
|
29
|
-
-
|
|
30
|
-
- Self-hosted deployments: configure auth in the editor server and omit `apiKey` when no token is required
|
|
31
|
-
|
|
32
|
-
### Hosted Stately
|
|
33
|
-
|
|
34
|
-
An API key is required. To get one:
|
|
35
|
-
|
|
36
|
-
1. Go to your [Stately settings](https://stately.ai/settings)
|
|
37
|
-
2. Select the **API Key** tab
|
|
38
|
-
3. Click **Create API Key** (Project or Account scope)
|
|
39
|
-
4. Copy and store it securely
|
|
40
|
-
|
|
41
|
-
See the [Studio API docs](https://stately.ai/docs/studio-api) for more details.
|
|
42
|
-
|
|
43
|
-
Pass the key to the SDK:
|
|
44
|
-
|
|
45
|
-
```ts
|
|
46
|
-
const embed = createStatelyEmbed({
|
|
47
|
-
baseUrl: 'https://stately.ai',
|
|
48
|
-
apiKey: 'your-api-key',
|
|
49
|
-
});
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Self-hosting
|
|
53
|
-
|
|
54
|
-
When self-hosting the editor, authentication is enforced by the editor server, not by this npm package.
|
|
55
|
-
|
|
56
|
-
The common environment variables are:
|
|
57
|
-
|
|
58
|
-
| Variable | Purpose |
|
|
59
|
-
| --------------------------- | ----------------------------------------------------------------------- |
|
|
60
|
-
| `AUTH_PROVIDER` | Auth strategy used by the editor host |
|
|
61
|
-
| `EDITOR_SYNC_AUTH_REQUIRED` | Set to `false` to disable API-key checks for editor-sync endpoints only |
|
|
62
|
-
| `STATELY_API_KEY` | Server-side API key for Stately data fetching |
|
|
63
|
-
| `STATELY_API_URL` | Stately API base URL override |
|
|
64
|
-
| `NEXT_PUBLIC_BASE_URL` | Public-facing editor URL |
|
|
65
|
-
|
|
66
|
-
For a fully self-contained deployment with no auth, omit `apiKey` in the SDK and configure the host/editor to allow unauthenticated access:
|
|
67
|
-
|
|
68
|
-
```ts
|
|
69
|
-
const embed = createStatelyEmbed({
|
|
70
|
-
baseUrl: 'https://your-editor.example.com',
|
|
71
|
-
});
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Quick Start
|
|
75
|
-
|
|
76
|
-
### Third-party embed (with API key)
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
import { createStatelyEmbed } from '@statelyai/sdk';
|
|
80
|
-
|
|
81
|
-
const embed = createStatelyEmbed({
|
|
82
|
-
baseUrl: 'https://stately.ai',
|
|
83
|
-
apiKey: 'your-api-key',
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
embed.mount(document.getElementById('editor')!);
|
|
87
|
-
|
|
88
|
-
embed.init({
|
|
89
|
-
machine: myMachineConfig,
|
|
90
|
-
format: 'xstate',
|
|
91
|
-
mode: 'editing',
|
|
92
|
-
theme: 'dark',
|
|
93
|
-
});
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### Comments
|
|
97
|
-
|
|
98
|
-
Comments are optional and integrator-configured. Pass a `comments` object to `embed.init()` when you want Liveblocks-backed commenting enabled.
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
embed.init({
|
|
102
|
-
machine: machineConfig,
|
|
103
|
-
mode: 'editing',
|
|
104
|
-
comments: {
|
|
105
|
-
roomId: 'machine:checkout',
|
|
106
|
-
publicApiKey: 'pk_live_...',
|
|
107
|
-
userId: currentUserId ?? null,
|
|
108
|
-
},
|
|
109
|
-
});
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
You can also use a custom auth endpoint instead of a public key:
|
|
113
|
-
|
|
114
|
-
```ts
|
|
115
|
-
embed.init({
|
|
116
|
-
machine: machineConfig,
|
|
117
|
-
comments: {
|
|
118
|
-
roomId: 'machine:checkout',
|
|
119
|
-
authEndpoint: '/api/liveblocks-auth',
|
|
120
|
-
userId: currentUserId ?? null,
|
|
121
|
-
},
|
|
122
|
-
});
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
`roomId` is required when comments are enabled. `userId` is optional and only used for comment identity metadata.
|
|
126
|
-
|
|
127
|
-
## Module Layout
|
|
128
|
-
|
|
129
|
-
<!-- subpath imports derived from package.json#exports -->
|
|
130
|
-
|
|
131
|
-
The SDK ships root exports for the most common entry points and helpers:
|
|
132
|
-
|
|
133
|
-
```ts
|
|
134
|
-
import {
|
|
135
|
-
createStatelyApiClient,
|
|
136
|
-
createStatelyApiUrl,
|
|
137
|
-
createStatelyClient,
|
|
138
|
-
createStatelyEmbed,
|
|
139
|
-
createStatelyInspector,
|
|
140
|
-
createS3AssetUploadAdapter,
|
|
141
|
-
createSupabaseAssetUploadAdapter,
|
|
142
|
-
fromStudioMachine,
|
|
143
|
-
graphToMachineConfig,
|
|
144
|
-
graphToXStateTS,
|
|
145
|
-
toStudioMachine,
|
|
146
|
-
} from '@statelyai/sdk';
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
It also supports narrower subpath imports:
|
|
150
|
-
|
|
151
|
-
```ts
|
|
152
|
-
import { createStatelyClient } from '@statelyai/sdk/studio';
|
|
153
|
-
import { createStatelyInspector } from '@statelyai/sdk/inspect';
|
|
154
|
-
import { createStatelyEmbed } from '@statelyai/sdk/embed';
|
|
155
|
-
import {
|
|
156
|
-
createStatelyApiClient,
|
|
157
|
-
createStatelyApiUrl,
|
|
158
|
-
} from '@statelyai/sdk/api';
|
|
159
|
-
import { fromStudioMachine, toStudioMachine } from '@statelyai/sdk/graph';
|
|
160
|
-
import { planSync, pullSync, pushSync } from '@statelyai/sdk/sync';
|
|
161
|
-
import {
|
|
162
|
-
createS3AssetUploadAdapter,
|
|
163
|
-
createSupabaseAssetUploadAdapter,
|
|
164
|
-
} from '@statelyai/sdk/assetStorage';
|
|
165
|
-
import type { GraphPatch } from '@statelyai/sdk/patchTypes';
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
The root package also exports `getStatelyPragma()`, `findStatelyPragmaAttachments()`, and `upsertStatelyPragma()` for working with canonical source annotations such as `// @statelyai id=machine-123`.
|
|
169
|
-
|
|
170
|
-
## Studio API Client
|
|
171
|
-
|
|
172
|
-
```ts
|
|
173
|
-
import { createStatelyClient } from '@statelyai/sdk';
|
|
174
|
-
|
|
175
|
-
const studio = createStatelyClient({
|
|
176
|
-
apiKey: process.env.STATELY_API_KEY,
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
const createdProject = await studio.projects.create({
|
|
180
|
-
name: 'My project',
|
|
181
|
-
visibility: 'Private',
|
|
182
|
-
});
|
|
183
|
-
const project = await studio.projects.get('project-id');
|
|
184
|
-
const projects = await studio.projects.list();
|
|
185
|
-
const createdMachine = await studio.machines.create({
|
|
186
|
-
projectVersionId: createdProject.projectVersionId!,
|
|
187
|
-
definition: digraphDefinition,
|
|
188
|
-
xstateVersion: 5,
|
|
189
|
-
});
|
|
190
|
-
const machine = await studio.machines.get('machine-id', { version: '42' });
|
|
191
|
-
const extracted = await studio.code.extractMachines(sourceCode);
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
`studio.projects.list(...)`, `studio.projects.create(...)`, and `studio.machines.create(...)` use the documented Studio REST API. `studio.projects.ensure(...)` is a client-side helper that uses the documented list/create endpoints to reuse an existing connected project when the repo metadata matches.
|
|
195
|
-
|
|
196
|
-
<!-- public methods of StudioClient from src/studio.ts -->
|
|
197
|
-
|
|
198
|
-
Available client methods:
|
|
199
|
-
|
|
200
|
-
| Method | Description |
|
|
201
|
-
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
|
202
|
-
| `studio.auth.verify(apiKey?)` | Verify an API key against the registry API |
|
|
203
|
-
| `studio.projects.list()` | List accessible projects, including connected repo metadata when present |
|
|
204
|
-
| `studio.projects.create({ name, visibility, description?, keywords? })` | Create a new project through the published REST API |
|
|
205
|
-
| `studio.projects.ensure({ name, visibility, repo?, ... })` | Reuse an existing connected project or create one through the REST API |
|
|
206
|
-
| `studio.projects.get(projectId)` | Fetch a project and its machines |
|
|
207
|
-
| `studio.machines.create({ projectVersionId, ... })` | Create a machine through the published REST API |
|
|
208
|
-
| `studio.machines.createMany({ projectVersionId, ... })` | Compatibility wrapper around `create()` that returns a one-item array |
|
|
209
|
-
| `studio.machines.update({ id, ... })` | Update a machine through the published REST API |
|
|
210
|
-
| `studio.machines.get(machineId, { version? })` | Fetch a machine, optionally pinned to a version |
|
|
211
|
-
| `studio.code.extractMachines(code, { apiKey? })` | Extract machine configs from source text |
|
|
212
|
-
|
|
213
|
-
## Sync Helpers
|
|
214
|
-
|
|
215
|
-
`pushSync()` complements `planSync()` and `pullSync()` for local-to-Studio flows. It resolves a local source file, ensures there is a target project, updates the linked remote machine when `// @statelyai id=...` is present, otherwise creates one, and writes the pragma back into XState source files when needed.
|
|
216
|
-
|
|
217
|
-
For project-scoped discovery flows, `statelyai.json` defines which local files should be scanned. The CLI `statelyai push` command uses that config to find local XState sources, creates remote Studio machines for unlabeled ones, updates already-linked ones, and writes returned `// @statelyai id=...` pragmas back into source.
|
|
218
|
-
|
|
219
|
-
```ts
|
|
220
|
-
import { pushSync } from '@statelyai/sdk/sync';
|
|
221
|
-
|
|
222
|
-
const result = await pushSync({
|
|
223
|
-
source: './src/machines/toggle.ts',
|
|
224
|
-
apiKey: process.env.STATELY_API_KEY,
|
|
225
|
-
project: {
|
|
226
|
-
visibility: 'Private',
|
|
227
|
-
repo: {
|
|
228
|
-
url: 'https://github.com/statelyai/viz',
|
|
229
|
-
owner: 'statelyai',
|
|
230
|
-
repo: 'viz',
|
|
231
|
-
branch: 'main',
|
|
232
|
-
treeSha: 'abc123',
|
|
233
|
-
},
|
|
234
|
-
},
|
|
235
|
-
});
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
Projects can also check in a `statelyai.json` file to describe which local sources belong to a Studio project. The published schema lives at `@statelyai/sdk/statelyai.schema.json` and the canonical schema id is `https://stately.ai/schemas/statelyai.json`. The strict XState JSON export schema is published at `@statelyai/sdk/xstate-json.schema.json`.
|
|
239
|
-
|
|
240
|
-
```json
|
|
241
|
-
{
|
|
242
|
-
"$schema": "https://stately.ai/schemas/statelyai.json",
|
|
243
|
-
"version": "1.0.0",
|
|
244
|
-
"projectId": "project_123",
|
|
245
|
-
"studioUrl": "https://stately.ai",
|
|
246
|
-
"defaultXStateVersion": 5,
|
|
247
|
-
"sources": []
|
|
248
|
-
}
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
## Inspector
|
|
252
|
-
|
|
253
|
-
<!-- public API of createStatelyInspector from src/inspect.ts -->
|
|
254
|
-
|
|
255
|
-
`createStatelyInspector()` streams actor-system state to the Stately inspector over WebSockets. It supports both automatic XState actor adoption and manual actor registration.
|
|
256
|
-
|
|
257
|
-
```ts
|
|
258
|
-
import { createActor } from 'xstate';
|
|
259
|
-
import { createStatelyInspector } from '@statelyai/sdk';
|
|
260
|
-
|
|
261
|
-
const actor = createActor(machine);
|
|
262
|
-
const inspector = createStatelyInspector({
|
|
263
|
-
actor,
|
|
264
|
-
url: 'ws://localhost:4242',
|
|
265
|
-
autoOpen: true,
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
actor.start();
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
Key options:
|
|
272
|
-
|
|
273
|
-
| Option | Description |
|
|
274
|
-
| -------------------------------------- | ---------------------------------------------------------------- |
|
|
275
|
-
| `actor` | Root actor to adopt and inspect automatically |
|
|
276
|
-
| `url` | Devtools relay URL. Defaults to `ws://localhost:4242` |
|
|
277
|
-
| `autoOpen` | Whether to ask the relay to open the inspector UI |
|
|
278
|
-
| `sessionId` | Override the relay session id |
|
|
279
|
-
| `name` | Display name shown to the inspector |
|
|
280
|
-
| `serializeSnapshot` | Customize snapshot serialization before sending it over the wire |
|
|
281
|
-
| `extractMachineConfig` | Customize how machine config is derived from an actor |
|
|
282
|
-
| `selectedActorId` | Focus a specific actor first |
|
|
283
|
-
| `panels`, `theme`, `readOnly`, `depth` | Initial inspector UI options |
|
|
284
|
-
| `transport` | Inject an existing transport instead of opening a new WebSocket |
|
|
285
|
-
|
|
286
|
-
Key methods:
|
|
287
|
-
|
|
288
|
-
- `inspector.export(format, options?)`
|
|
289
|
-
- `inspector.actor(id, options?)`
|
|
290
|
-
- `inspector.snapshot(actorId, snapshot, event?)`
|
|
291
|
-
- `inspector.event(actorId, event, { source? })`
|
|
292
|
-
- `inspector.stop(actorId)`
|
|
293
|
-
- `inspector.destroy()`
|
|
294
|
-
|
|
295
|
-
## Embed API
|
|
296
|
-
|
|
297
|
-
### `createStatelyEmbed(options)`
|
|
298
|
-
|
|
299
|
-
Creates an embed instance.
|
|
300
|
-
|
|
301
|
-
<!-- public options of StatelyEmbedOptions from src/embed.ts -->
|
|
302
|
-
|
|
303
|
-
| Option | Type | Description |
|
|
304
|
-
| ---------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
305
|
-
| `baseUrl` | `string` | **Required.** Base URL of the Stately app |
|
|
306
|
-
| `apiKey` | `string` | API key for hosted Stately deployments |
|
|
307
|
-
| `origin` | `string` | Optional strict target origin for `postMessage`; defaults to permissive wildcard messaging for local/self-hosted testing |
|
|
308
|
-
| `assets` | `AssetConfig` | Asset upload configuration |
|
|
309
|
-
| `onReady` | `() => void` | Called when the embed is ready |
|
|
310
|
-
| `onLoaded` | `(graph) => void` | Called when a machine is loaded |
|
|
311
|
-
| `onChange` | `(graph, machineConfig) => void` | Called on every change |
|
|
312
|
-
| `onSave` | `(graph, machineConfig) => void` | Called on save |
|
|
313
|
-
| `onError` | `({ code, message }) => void` | Called when the embed reports an error |
|
|
314
|
-
|
|
315
|
-
### Embed methods
|
|
316
|
-
|
|
317
|
-
#### `embed.mount(container)` / `embed.attach(iframe)`
|
|
318
|
-
|
|
319
|
-
`mount()` creates an iframe inside a container element. `attach()` connects to an existing iframe.
|
|
320
|
-
|
|
321
|
-
```ts
|
|
322
|
-
const iframe = embed.mount(document.getElementById('editor')!);
|
|
323
|
-
|
|
324
|
-
embed.attach(document.querySelector('iframe')!);
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
#### `embed.init(options)`
|
|
328
|
-
|
|
329
|
-
Initialize the embed with a machine and display options.
|
|
330
|
-
|
|
331
|
-
```ts
|
|
332
|
-
embed.init({
|
|
333
|
-
machine: machineConfig,
|
|
334
|
-
format: 'xstate',
|
|
335
|
-
mode: 'editing',
|
|
336
|
-
theme: 'dark',
|
|
337
|
-
readOnly: false,
|
|
338
|
-
depth: 3,
|
|
339
|
-
panels: {
|
|
340
|
-
leftPanels: ['code'],
|
|
341
|
-
rightPanels: ['events'],
|
|
342
|
-
activePanels: ['code'],
|
|
343
|
-
},
|
|
344
|
-
unsavedIndicator: {
|
|
345
|
-
enabled: true,
|
|
346
|
-
mode: 'structural',
|
|
347
|
-
},
|
|
348
|
-
comments: {
|
|
349
|
-
roomId: 'machine:checkout',
|
|
350
|
-
publicApiKey: 'pk_live_...',
|
|
351
|
-
},
|
|
352
|
-
});
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
`comments` accepts:
|
|
356
|
-
|
|
357
|
-
| Field | Type | Description |
|
|
358
|
-
| -------------- | ---------------- | ------------------------------------------- |
|
|
359
|
-
| `roomId` | `string` | **Required.** Liveblocks room identifier |
|
|
360
|
-
| `publicApiKey` | `string` | Liveblocks public key |
|
|
361
|
-
| `authEndpoint` | `string` | Custom Liveblocks auth endpoint |
|
|
362
|
-
| `baseUrl` | `string` | Custom Liveblocks base URL for self-hosting |
|
|
363
|
-
| `userId` | `string \| null` | Optional user identity metadata |
|
|
364
|
-
|
|
365
|
-
`unsavedIndicator` accepts:
|
|
366
|
-
|
|
367
|
-
| Field | Type | Description |
|
|
368
|
-
| --------- | ----------------------- | ---------------------------------------------- |
|
|
369
|
-
| `enabled` | `boolean` | Show the persistent "Save to apply" pill |
|
|
370
|
-
| `mode` | `'structural' \| 'all'` | Track only structural graph edits or all edits |
|
|
371
|
-
|
|
372
|
-
#### `embed.updateMachine(machine, format?)`
|
|
373
|
-
|
|
374
|
-
Update the displayed machine.
|
|
375
|
-
|
|
376
|
-
#### `embed.setMode(mode)` / `embed.setTheme(theme)`
|
|
377
|
-
|
|
378
|
-
Change the embed mode or theme at runtime.
|
|
379
|
-
|
|
380
|
-
#### `embed.setSettings(settings)`
|
|
381
|
-
|
|
382
|
-
Update editor settings at runtime. Settings are merged with the existing editor settings.
|
|
383
|
-
|
|
384
|
-
```ts
|
|
385
|
-
embed.setSettings({
|
|
386
|
-
appearance: { colorMode: 'light' },
|
|
387
|
-
canvas: { showGrid: false },
|
|
388
|
-
});
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
Available core settings:
|
|
392
|
-
|
|
393
|
-
<!-- core setting paths from ../../src/settings.ts -->
|
|
394
|
-
|
|
395
|
-
| Path | Type | Default |
|
|
396
|
-
| ---------------------------- | ------------------------------- | --------- |
|
|
397
|
-
| `appearance.colorMode` | `'light' \| 'dark' \| 'system'` | `'dark'` |
|
|
398
|
-
| `canvas.showGrid` | `boolean` | `true` |
|
|
399
|
-
| `canvas.viewMode` | `'graph' \| 'list'` | `'graph'` |
|
|
400
|
-
| `canvas.enableSnapLines` | `boolean` | `true` |
|
|
401
|
-
| `canvas.dimUnselected` | `boolean` | `true` |
|
|
402
|
-
| `validation.showValidations` | `boolean` | `true` |
|
|
403
|
-
| `layout.autolayout` | `boolean` | `false` |
|
|
404
|
-
| `developer.devMode` | `boolean` | `false` |
|
|
405
|
-
|
|
406
|
-
#### `embed.export(format, options?)`
|
|
407
|
-
|
|
408
|
-
Export the current machine. Returns a promise.
|
|
409
|
-
|
|
410
|
-
```ts
|
|
411
|
-
const xstateCode = await embed.export('xstate', { version: 5 });
|
|
412
|
-
const digraph = await embed.export('digraph');
|
|
413
|
-
const redux = await embed.export('redux');
|
|
414
|
-
const aslYaml = await embed.export('asl-yaml');
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
<!-- supported export formats from ExportFormatMap in src/protocol.ts -->
|
|
418
|
-
|
|
419
|
-
Supported formats: `xstate`, `xstate-json`, `xgraph`, `digraph`, `mermaid`, `redux`, `zustand`, `asl-json`, `asl-yaml`, `scxml`
|
|
420
|
-
|
|
421
|
-
#### `embed.on(event, handler)` / `embed.off(event, handler)`
|
|
422
|
-
|
|
423
|
-
<!-- keys of EmbedEventMap in src/protocol.ts -->
|
|
424
|
-
|
|
425
|
-
Event names are `ready`, `loaded`, `change`, `save`, `error`, and `snapshot`.
|
|
426
|
-
|
|
427
|
-
`createStatelyEmbed()` emits `ready`, `loaded`, `change`, `save`, and `error` for browser embeds:
|
|
428
|
-
|
|
429
|
-
```ts
|
|
430
|
-
embed.on('change', ({ graph, machineConfig, patches }) => {
|
|
431
|
-
console.log('Machine changed', graph, machineConfig, patches);
|
|
432
|
-
});
|
|
433
|
-
|
|
434
|
-
embed.on('save', ({ validations }) => {
|
|
435
|
-
console.log('Save validations', validations);
|
|
436
|
-
});
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
#### `embed.toast(message, type?)`
|
|
440
|
-
|
|
441
|
-
Show a toast notification in the embed. Type: `'success' | 'error' | 'info' | 'warning'`
|
|
442
|
-
|
|
443
|
-
#### `embed.destroy()`
|
|
444
|
-
|
|
445
|
-
Tear down the embed. Removes listeners, rejects pending promises, and removes the iframe if it was created via `mount()`.
|
|
446
|
-
|
|
447
|
-
### Asset uploads
|
|
448
|
-
|
|
449
|
-
By default, dropped files are stored as base64 data URLs. To upload assets to your own storage, pass an `assets` config:
|
|
450
|
-
|
|
451
|
-
```ts
|
|
452
|
-
const embed = createStatelyEmbed({
|
|
453
|
-
baseUrl: 'https://stately.ai',
|
|
454
|
-
assets: {
|
|
455
|
-
onUploadRequest: async (file, { stateNodeId }) => {
|
|
456
|
-
return { url: await uploadToStorage(file, stateNodeId) };
|
|
457
|
-
},
|
|
458
|
-
accept: ['image/*'],
|
|
459
|
-
maxFileSize: 5 * 1024 * 1024,
|
|
460
|
-
},
|
|
461
|
-
});
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
For reusable integrations, pass an upload adapter instead of wiring the callback inline:
|
|
465
|
-
|
|
466
|
-
```ts
|
|
467
|
-
import { createStatelyEmbed, createS3AssetUploadAdapter } from '@statelyai/sdk';
|
|
468
|
-
|
|
469
|
-
const adapter = createS3AssetUploadAdapter({
|
|
470
|
-
bucket: 'assets',
|
|
471
|
-
publicBaseUrl: 'https://cdn.example.com/assets',
|
|
472
|
-
async getUploadTarget({ key, contentType }) {
|
|
473
|
-
const response = await fetch('/api/assets/presign', {
|
|
474
|
-
method: 'POST',
|
|
475
|
-
headers: { 'Content-Type': 'application/json' },
|
|
476
|
-
body: JSON.stringify({ key, contentType }),
|
|
477
|
-
});
|
|
478
|
-
return response.json();
|
|
479
|
-
},
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
const embed = createStatelyEmbed({
|
|
483
|
-
baseUrl: 'https://stately.ai',
|
|
484
|
-
assets: { adapter },
|
|
485
|
-
});
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
Supabase storage can use the same adapter contract:
|
|
489
|
-
|
|
490
|
-
```ts
|
|
491
|
-
import {
|
|
492
|
-
createStatelyEmbed,
|
|
493
|
-
createSupabaseAssetUploadAdapter,
|
|
494
|
-
} from '@statelyai/sdk';
|
|
495
|
-
|
|
496
|
-
const adapter = createSupabaseAssetUploadAdapter({
|
|
497
|
-
client: supabaseClient,
|
|
498
|
-
bucket: 'assets',
|
|
499
|
-
projectVersionId,
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
const embed = createStatelyEmbed({
|
|
503
|
-
baseUrl: 'https://stately.ai',
|
|
504
|
-
assets: { adapter },
|
|
505
|
-
});
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
| Option | Type | Description |
|
|
509
|
-
| ----------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------- |
|
|
510
|
-
| `onUploadRequest` | `(file: File, context: { stateNodeId: string }) => Promise<UploadResult>` | Called when the editor needs to upload a file |
|
|
511
|
-
| `adapter` | `AssetUploadAdapter` | Provider-specific uploader, such as the S3 or Supabase adapter |
|
|
512
|
-
| `accept` | `string[]` | Accepted MIME types. Supports wildcards like `image/*` |
|
|
513
|
-
| `maxFileSize` | `number` | Max file size in bytes. Defaults to `10_485_760` |
|
|
514
|
-
|
|
515
|
-
`UploadResult`:
|
|
516
|
-
|
|
517
|
-
```ts
|
|
518
|
-
interface UploadResult {
|
|
519
|
-
url: string;
|
|
520
|
-
name?: string;
|
|
521
|
-
metadata?: Record<string, unknown>;
|
|
522
|
-
}
|
|
523
|
-
```
|
|
524
|
-
|
|
525
|
-
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.
|
|
526
|
-
|
|
527
|
-
## Graph And Codegen Helpers
|
|
528
|
-
|
|
529
|
-
<!-- root helper exports from src/index.ts -->
|
|
530
|
-
|
|
531
|
-
Use the conversion helpers to move between Studio digraph data, generic Stately graphs, machine config objects, and XState TypeScript source.
|
|
532
|
-
|
|
533
|
-
```ts
|
|
534
|
-
import {
|
|
535
|
-
fromStudioMachine,
|
|
536
|
-
graphToMachineConfig,
|
|
537
|
-
graphToXStateTS,
|
|
538
|
-
toStudioMachine,
|
|
539
|
-
} from '@statelyai/sdk';
|
|
540
|
-
|
|
541
|
-
const graph = fromStudioMachine(studioMachine);
|
|
542
|
-
const machineConfig = graphToMachineConfig(graph, {
|
|
543
|
-
showDescriptions: true,
|
|
544
|
-
showMeta: true,
|
|
545
|
-
});
|
|
546
|
-
const source = graphToXStateTS(graph, {
|
|
547
|
-
exportStyle: 'named',
|
|
548
|
-
});
|
|
549
|
-
const digraph = toStudioMachine(graph);
|
|
550
|
-
```
|
|
551
|
-
|
|
552
|
-
Other exported helpers:
|
|
553
|
-
|
|
554
|
-
- `studioMachineConverter` for reusable format conversion
|
|
555
|
-
- `createStatelyApiUrl()` and `createStatelyApiClient()` for building and
|
|
556
|
-
calling self-hosted Viz API routes from a shared API base URL
|
|
557
|
-
- `serializeJS()`, `raw()`, and `RawCode` for emitting JavaScript source
|
|
558
|
-
- `jsonSchemaToTSType()`, `contextSchemaToTSType()`, and `eventsSchemaToTSType()` for generating inline TypeScript types from JSON Schema
|
|
559
|
-
- `GraphPatch` and `ActionLocation` types from `@statelyai/sdk/patchTypes`
|
|
560
|
-
|
|
561
|
-
## Sync Helpers And CLI
|
|
562
|
-
|
|
563
|
-
<!-- sync helpers from src/sync.ts and CLI commands from src/cli.ts#COMMANDS -->
|
|
564
|
-
|
|
565
|
-
The sync helpers compare or materialize machines across local files, Stately machine IDs, and Stately URLs.
|
|
566
|
-
|
|
567
|
-
Programmatic usage:
|
|
568
|
-
|
|
569
|
-
```ts
|
|
570
|
-
import { planSync, pullSync } from '@statelyai/sdk/sync';
|
|
571
|
-
|
|
572
|
-
const plan = await planSync({
|
|
573
|
-
source: './checkout.machine.ts',
|
|
574
|
-
target: 'machine-id',
|
|
575
|
-
apiKey: process.env.STATELY_API_KEY,
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
if (plan.summary.hasChanges) {
|
|
579
|
-
console.log(plan.summary);
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
await pullSync({
|
|
583
|
-
source: 'machine-id',
|
|
584
|
-
target: './checkout.machine.ts',
|
|
585
|
-
apiKey: process.env.STATELY_API_KEY,
|
|
586
|
-
});
|
|
587
|
-
```
|
|
588
|
-
|
|
589
|
-
Supported locators:
|
|
590
|
-
|
|
591
|
-
- local files
|
|
592
|
-
- Stately machine IDs
|
|
593
|
-
- full Stately machine URLs
|
|
594
|
-
|
|
595
|
-
Installing the package also exposes a `statelyai` binary:
|
|
596
|
-
|
|
597
|
-
```bash
|
|
598
|
-
npx statelyai open ./checkout.machine.ts
|
|
599
|
-
|
|
600
|
-
statelyai init
|
|
601
|
-
statelyai init --scan
|
|
602
|
-
statelyai login
|
|
603
|
-
statelyai auth status
|
|
604
|
-
statelyai plan ./checkout.machine.ts machine-id
|
|
605
|
-
statelyai diff ./checkout.machine.ts machine-id --fail-on-changes
|
|
606
|
-
statelyai push
|
|
607
|
-
statelyai push ./checkout.machine.ts
|
|
608
|
-
statelyai pull machine-id ./checkout.machine.ts
|
|
609
|
-
statelyai pull ./checkout.machine.ts
|
|
610
|
-
statelyai open ./checkout.machine.ts
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
For one-off use, `npx statelyai ...` installs the small `statelyai` CLI package, which delegates to this SDK CLI.
|
|
614
|
-
|
|
615
|
-
Available commands:
|
|
616
|
-
|
|
617
|
-
| Command | Description |
|
|
618
|
-
| ---------------------------------- | --------------------------------------------------------------------------- |
|
|
619
|
-
| `statelyai init` | Create or reuse a Studio project for the current directory and write `statelyai.json` with an empty `sources` array |
|
|
620
|
-
| `statelyai login` | Store an API key for future CLI use |
|
|
621
|
-
| `statelyai logout` | Remove a stored API key |
|
|
622
|
-
| `statelyai auth status` | Show whether the CLI would use an environment variable or stored credential |
|
|
623
|
-
| `statelyai plan <source> <target>` | Print a semantic sync summary |
|
|
624
|
-
| `statelyai diff <source> <target>` | Diff two locators and optionally fail on changes |
|
|
625
|
-
| `statelyai push [file]` | Discover local machine sources, create remote Studio machines for unlabeled files, update linked ones, and persist returned ids |
|
|
626
|
-
| `statelyai pull <source> <target>` | Materialize a source into a local target file |
|
|
627
|
-
| `statelyai pull <linked-file>` | Refresh a linked local file from the `@statelyai id=...` pragma |
|
|
628
|
-
| `statelyai open <file>` | Open a local file in a browser-backed visual editor session |
|
|
629
|
-
|
|
630
|
-
Common flags:
|
|
631
|
-
|
|
632
|
-
- `--api-key` for remote machine resolution or editor servers that require auth
|
|
633
|
-
- `--base-url` for self-hosted or non-default Stately deployments
|
|
634
|
-
- `--fail-on-changes` to return a nonzero exit code when a diff is detected
|
|
635
|
-
|
|
636
|
-
The CLI resolves credentials in this order: `--api-key`, then `STATELY_API_KEY`/`NEXT_PUBLIC_STATELY_API_KEY`, then the key stored by `statelyai login`. `login` stores the key in the OS credential store when available, with a private file fallback.
|
|
637
|
-
|
|
638
|
-
`statelyai init --scan` walks local code files, detects machine-bearing files from their contents, and suggests `sources` globs to save into `statelyai.json`. Without `--scan`, `init` leaves `sources` empty so you can opt in explicitly before running `statelyai push`.
|
|
639
|
-
|
|
640
|
-
`statelyai open` also supports `--api-key`, `--editor-url`, `--host`, `--port`, `--no-open`, and `--debug`. It watches the local file on disk and sends source snapshots to `/api/editor-sync/*` endpoints, which return the text replacements to apply locally. When the source file contains `// @statelyai id=...` and an API key is available, the editor session also reuses the referenced remote machine layout while continuing to treat the local source as the semantic source of truth. Pass `--api-key`, set `STATELY_API_KEY`, or run `statelyai login` when the editor server requires auth. Self-hosted servers can disable editor-sync API-key checks with `EDITOR_SYNC_AUTH_REQUIRED=false`. The private source reconciliation engine is not bundled into the published CLI.
|
|
641
|
-
|
|
642
|
-
## Transport Helpers
|
|
643
|
-
|
|
644
|
-
<!-- transport helpers exported from src/index.ts -->
|
|
645
|
-
|
|
646
|
-
For advanced integrations, the root package also exports:
|
|
647
|
-
|
|
648
|
-
- `createPostMessageTransport()` for iframe-based clients
|
|
649
|
-
- `createWebSocketTransport()` for relay-based integrations
|
|
650
|
-
|
|
651
|
-
These power the embed and inspector internals, but they are also available when you need lower-level control over the `@statelyai.*` protocol.
|
|
26
|
+
The CLI-facing `statelyai.json` schema now uses top-level `include` / `exclude` globs for local file discovery.
|
package/dist/assetStorage.d.mts
CHANGED
package/dist/embed.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CommentsConfig, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap, InitOptions, MachineInitOptions, MachineSourceLocations, ProjectEmbedMachine, UploadResult } from "./protocol.mjs";
|
|
2
2
|
import { AssetUploadAdapter } from "./assetStorage.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/embed.d.ts
|
package/dist/embed.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as toInitMessage, i as createPendingExportManager, r as createEventRegistry, t as createPostMessageTransport } from "./transport-
|
|
1
|
+
import { a as toInitMessage, i as createPendingExportManager, r as createEventRegistry, t as createPostMessageTransport } from "./transport-CVZGF0w9.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/embed.ts
|
|
4
4
|
function buildEmbedUrl(options) {
|