@statelyai/sdk 0.3.0 → 0.4.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 +144 -0
- package/dist/cli.d.mts +63 -0
- package/dist/cli.mjs +140 -0
- package/dist/embed.d.mts +24 -2
- package/dist/embed.mjs +48 -1
- package/dist/{graph-C-7ZK_nK.d.mts → graph-BfezxFKJ.d.mts} +1 -1
- package/dist/graph.d.mts +1 -1
- package/dist/graphToXStateTS-C6HQUrBB.mjs +530 -0
- package/dist/index.d.mts +147 -6
- package/dist/index.mjs +3 -3
- package/dist/inspect.d.mts +7 -3
- package/dist/inspect.mjs +1 -1
- package/dist/{protocol-BC-_s3if.d.mts → protocol-BgXSkIuc.d.mts} +53 -4
- package/dist/studio-D2uQhrvX.d.mts +54 -0
- package/dist/studio.d.mts +1 -53
- package/dist/sync.d.mts +2 -2
- package/dist/sync.mjs +253 -3
- package/dist/{transport-D352iKKa.mjs → transport-C1fRAuv-.mjs} +2 -1
- package/package.json +16 -2
- package/dist/sync-CzEOizjx.mjs +0 -558
package/README.md
CHANGED
|
@@ -126,6 +126,39 @@ const embed = createStatelyEmbed({
|
|
|
126
126
|
embed.mount(container);
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
+
### Comments
|
|
130
|
+
|
|
131
|
+
Comments are optional and integrator-configured. Pass a `comments` object to
|
|
132
|
+
`embed.init()` when you want Liveblocks-backed commenting enabled.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
embed.init({
|
|
136
|
+
machine: machineConfig,
|
|
137
|
+
mode: 'editing',
|
|
138
|
+
comments: {
|
|
139
|
+
roomId: 'machine:checkout',
|
|
140
|
+
publicApiKey: 'pk_live_...',
|
|
141
|
+
userId: currentUserId ?? null,
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
You can also use a custom auth endpoint instead of a public key:
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
embed.init({
|
|
150
|
+
machine: machineConfig,
|
|
151
|
+
comments: {
|
|
152
|
+
roomId: 'machine:checkout',
|
|
153
|
+
authEndpoint: '/api/liveblocks-auth',
|
|
154
|
+
userId: currentUserId ?? null,
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`roomId` is required when comments are enabled. `userId` is optional and only
|
|
160
|
+
used for comment identity metadata.
|
|
161
|
+
|
|
129
162
|
## Module layout
|
|
130
163
|
|
|
131
164
|
The SDK ships direct root exports for the common entry points:
|
|
@@ -171,6 +204,7 @@ Creates an embed instance.
|
|
|
171
204
|
| `baseUrl` | `string` | **Required.** Base URL of the Stately app |
|
|
172
205
|
| `apiKey` | `string` | API key for authentication (see [Authentication](#authentication)) |
|
|
173
206
|
| `origin` | `string` | Custom target origin for postMessage |
|
|
207
|
+
| `assets` | `AssetConfig` | Asset upload configuration (see [Asset uploads](#asset-uploads)) |
|
|
174
208
|
| `onReady` | `() => void` | Called when embed is ready |
|
|
175
209
|
| `onLoaded` | `(graph) => void` | Called when machine is loaded |
|
|
176
210
|
| `onChange` | `(graph, machineConfig) => void` | Called on every change |
|
|
@@ -208,9 +242,23 @@ embed.init({
|
|
|
208
242
|
rightPanels: ['events'],
|
|
209
243
|
activePanels: ['code'],
|
|
210
244
|
},
|
|
245
|
+
comments: {
|
|
246
|
+
roomId: 'machine:checkout',
|
|
247
|
+
publicApiKey: 'pk_live_...',
|
|
248
|
+
},
|
|
211
249
|
});
|
|
212
250
|
```
|
|
213
251
|
|
|
252
|
+
`comments` accepts:
|
|
253
|
+
|
|
254
|
+
| Field | Type | Description |
|
|
255
|
+
| ---------- | ---------- | ----------------------------------------------- |
|
|
256
|
+
| `roomId` | `string` | **Required.** Liveblocks room identifier |
|
|
257
|
+
| `publicApiKey` | `string` | Liveblocks public key |
|
|
258
|
+
| `authEndpoint` | `string` | Custom Liveblocks auth endpoint |
|
|
259
|
+
| `baseUrl` | `string` | Custom Liveblocks base URL for self-hosting |
|
|
260
|
+
| `userId` | `string \| null` | Optional user identity metadata |
|
|
261
|
+
|
|
214
262
|
#### `embed.updateMachine(machine, format?)`
|
|
215
263
|
|
|
216
264
|
Update the displayed machine.
|
|
@@ -248,3 +296,99 @@ Show a toast notification in the embed. Type: `'success' | 'error' | 'info' | 'w
|
|
|
248
296
|
#### `embed.destroy()`
|
|
249
297
|
|
|
250
298
|
Tear down the embed. Removes listeners, rejects pending promises, and removes the iframe if it was created via `mount()`.
|
|
299
|
+
|
|
300
|
+
### Asset uploads
|
|
301
|
+
|
|
302
|
+
By default, dropped images are stored as base64 data URLs. To upload assets to your own storage, pass an `assets` config:
|
|
303
|
+
|
|
304
|
+
```ts
|
|
305
|
+
const embed = createStatelyEmbed({
|
|
306
|
+
baseUrl: 'https://stately.ai',
|
|
307
|
+
assets: {
|
|
308
|
+
onUploadRequest: async (file, { stateNodeId }) => {
|
|
309
|
+
// upload `file` (a File object) to your storage
|
|
310
|
+
// return { url } at minimum
|
|
311
|
+
},
|
|
312
|
+
accept: ['image/*'], // MIME patterns (default: ['image/*'])
|
|
313
|
+
maxFileSize: 5 * 1024 * 1024, // bytes (default: 10 MB)
|
|
314
|
+
},
|
|
315
|
+
});
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
| Option | Type | Description |
|
|
319
|
+
| --- | --- | --- |
|
|
320
|
+
| `onUploadRequest` | `(file: File, context: { stateNodeId: string }) => Promise<UploadResult>` | **Required.** Called when the editor needs to upload a file. Return the hosted URL. |
|
|
321
|
+
| `accept` | `string[]` | Accepted MIME types. Supports wildcards (`image/*`). Default: `['image/*']` |
|
|
322
|
+
| `maxFileSize` | `number` | Max file size in bytes. Default: `10_485_760` (10 MB) |
|
|
323
|
+
|
|
324
|
+
`UploadResult`:
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
interface UploadResult {
|
|
328
|
+
url: string; // hosted URL (required)
|
|
329
|
+
name?: string; // display name (defaults to filename)
|
|
330
|
+
metadata?: Record<string, unknown>; // arbitrary metadata stored on the asset
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
#### Example: AWS S3 (presigned URL)
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
import { createStatelyEmbed } from '@statelyai/sdk';
|
|
338
|
+
|
|
339
|
+
const embed = createStatelyEmbed({
|
|
340
|
+
baseUrl: 'https://stately.ai',
|
|
341
|
+
assets: {
|
|
342
|
+
onUploadRequest: async (file) => {
|
|
343
|
+
// 1. Get a presigned upload URL from your backend
|
|
344
|
+
const { uploadUrl, publicUrl } = await fetch('/api/s3/presign', {
|
|
345
|
+
method: 'POST',
|
|
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
|
+
},
|
|
365
|
+
});
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
#### Example: Cloudflare R2 (worker upload)
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
import { createStatelyEmbed } from '@statelyai/sdk';
|
|
372
|
+
|
|
373
|
+
const embed = createStatelyEmbed({
|
|
374
|
+
baseUrl: 'https://stately.ai',
|
|
375
|
+
assets: {
|
|
376
|
+
onUploadRequest: async (file) => {
|
|
377
|
+
const form = new FormData();
|
|
378
|
+
form.append('file', file);
|
|
379
|
+
|
|
380
|
+
// Upload via a Cloudflare Worker that writes to R2
|
|
381
|
+
const { url } = await fetch('https://uploads.example.com/assets', {
|
|
382
|
+
method: 'POST',
|
|
383
|
+
body: form,
|
|
384
|
+
}).then((r) => r.json());
|
|
385
|
+
|
|
386
|
+
return { url, name: file.name };
|
|
387
|
+
},
|
|
388
|
+
accept: ['image/*', 'application/pdf'],
|
|
389
|
+
maxFileSize: 25 * 1024 * 1024,
|
|
390
|
+
},
|
|
391
|
+
});
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
If `onUploadRequest` throws or rejects, the editor shows an error toast. If no `assets` config is provided, files are stored as inline base64 data URLs (no network requests).
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import "./graph-BfezxFKJ.mjs";
|
|
2
|
+
import { SyncPlan } from "./sync.mjs";
|
|
3
|
+
import { Command } from "@oclif/core";
|
|
4
|
+
import * as _oclif_core_interfaces0 from "@oclif/core/interfaces";
|
|
5
|
+
|
|
6
|
+
//#region src/cli.d.ts
|
|
7
|
+
declare function formatPlanSummary(plan: SyncPlan): string;
|
|
8
|
+
declare abstract class BaseSyncCommand extends Command {
|
|
9
|
+
static enableJsonFlag: boolean;
|
|
10
|
+
static flags: {
|
|
11
|
+
help: _oclif_core_interfaces0.BooleanFlag<void>;
|
|
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>;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
declare abstract class ParsedSyncCommand extends BaseSyncCommand {
|
|
18
|
+
protected parseSync<T extends typeof BaseSyncCommand>(command: T): Promise<_oclif_core_interfaces0.ParserOutput<{
|
|
19
|
+
help: void;
|
|
20
|
+
'fail-on-changes': boolean;
|
|
21
|
+
'api-key': string;
|
|
22
|
+
'base-url': string;
|
|
23
|
+
}, {
|
|
24
|
+
[flag: string]: any;
|
|
25
|
+
}, {
|
|
26
|
+
[arg: string]: any;
|
|
27
|
+
}>>;
|
|
28
|
+
}
|
|
29
|
+
declare class PlanCommand extends ParsedSyncCommand {
|
|
30
|
+
static summary: string;
|
|
31
|
+
static description: string;
|
|
32
|
+
static args: {
|
|
33
|
+
source: _oclif_core_interfaces0.Arg<string, Record<string, unknown>>;
|
|
34
|
+
target: _oclif_core_interfaces0.Arg<string, Record<string, unknown>>;
|
|
35
|
+
};
|
|
36
|
+
run(): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
declare class DiffCommand extends ParsedSyncCommand {
|
|
39
|
+
static summary: string;
|
|
40
|
+
static description: string;
|
|
41
|
+
static args: {
|
|
42
|
+
source: _oclif_core_interfaces0.Arg<string, Record<string, unknown>>;
|
|
43
|
+
target: _oclif_core_interfaces0.Arg<string, Record<string, unknown>>;
|
|
44
|
+
};
|
|
45
|
+
run(): Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
declare class PullCommand extends ParsedSyncCommand {
|
|
48
|
+
static summary: string;
|
|
49
|
+
static description: string;
|
|
50
|
+
static args: {
|
|
51
|
+
source: _oclif_core_interfaces0.Arg<string, Record<string, unknown>>;
|
|
52
|
+
target: _oclif_core_interfaces0.Arg<string, Record<string, unknown>>;
|
|
53
|
+
};
|
|
54
|
+
run(): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
declare const COMMANDS: {
|
|
57
|
+
plan: typeof PlanCommand;
|
|
58
|
+
diff: typeof DiffCommand;
|
|
59
|
+
pull: typeof PullCommand;
|
|
60
|
+
};
|
|
61
|
+
declare function run(argv?: string[]): Promise<void>;
|
|
62
|
+
//#endregion
|
|
63
|
+
export { COMMANDS, formatPlanSummary, run };
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { planSync, pullSync } from "./sync.mjs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { Args, Command, Flags, flush, handle, run as run$1 } from "@oclif/core";
|
|
5
|
+
|
|
6
|
+
//#region src/cli.ts
|
|
7
|
+
function loadLocalEnv() {
|
|
8
|
+
if (typeof process.loadEnvFile !== "function") return;
|
|
9
|
+
const cwdEnvPath = path.join(process.cwd(), ".env.local");
|
|
10
|
+
try {
|
|
11
|
+
process.loadEnvFile(cwdEnvPath);
|
|
12
|
+
} catch {}
|
|
13
|
+
}
|
|
14
|
+
loadLocalEnv();
|
|
15
|
+
const sharedFlags = {
|
|
16
|
+
help: Flags.help({ char: "h" }),
|
|
17
|
+
"fail-on-changes": Flags.boolean({
|
|
18
|
+
default: false,
|
|
19
|
+
description: "Exit with a nonzero code when differences are found"
|
|
20
|
+
}),
|
|
21
|
+
"api-key": Flags.string({
|
|
22
|
+
description: "Stately API key used for remote source or target resolution",
|
|
23
|
+
default: process.env.STATELY_API_KEY ?? process.env.NEXT_PUBLIC_STATELY_API_KEY
|
|
24
|
+
}),
|
|
25
|
+
"base-url": Flags.string({
|
|
26
|
+
description: "Base URL for Stately Studio or a self-hosted deployment",
|
|
27
|
+
default: process.env.STATELY_API_URL ?? process.env.NEXT_PUBLIC_BASE_URL ?? process.env.NEXT_PUBLIC_STATELY_API_URL
|
|
28
|
+
})
|
|
29
|
+
};
|
|
30
|
+
function formatChangeList(label, items) {
|
|
31
|
+
if (items.length === 0) return null;
|
|
32
|
+
return `${label}: ${items.map((item) => item.id).join(", ")}`;
|
|
33
|
+
}
|
|
34
|
+
function formatPlanSummary(plan) {
|
|
35
|
+
const lines = [
|
|
36
|
+
`Plan: ${plan.source.locator} -> ${plan.target.locator}`,
|
|
37
|
+
`Source: ${plan.source.kind} (${plan.source.format})`,
|
|
38
|
+
`Target: ${plan.target.kind} (${plan.target.format})`,
|
|
39
|
+
`Has changes: ${plan.summary.hasChanges ? "yes" : "no"}`,
|
|
40
|
+
`Node changes: ${plan.summary.nodeChanges}`,
|
|
41
|
+
`Edge changes: ${plan.summary.edgeChanges}`
|
|
42
|
+
];
|
|
43
|
+
const nodeSections = [
|
|
44
|
+
formatChangeList("Added nodes", plan.diff.nodes.added),
|
|
45
|
+
formatChangeList("Removed nodes", plan.diff.nodes.removed),
|
|
46
|
+
formatChangeList("Updated nodes", plan.diff.nodes.updated)
|
|
47
|
+
].filter(Boolean);
|
|
48
|
+
const edgeSections = [
|
|
49
|
+
formatChangeList("Added edges", plan.diff.edges.added),
|
|
50
|
+
formatChangeList("Removed edges", plan.diff.edges.removed),
|
|
51
|
+
formatChangeList("Updated edges", plan.diff.edges.updated)
|
|
52
|
+
].filter(Boolean);
|
|
53
|
+
lines.push(...nodeSections, ...edgeSections);
|
|
54
|
+
if (plan.warnings.length > 0) lines.push(`Warnings: ${plan.warnings.join("; ")}`);
|
|
55
|
+
return lines.join("\n");
|
|
56
|
+
}
|
|
57
|
+
var BaseSyncCommand = class extends Command {
|
|
58
|
+
static enableJsonFlag = false;
|
|
59
|
+
static flags = sharedFlags;
|
|
60
|
+
};
|
|
61
|
+
const sharedArgs = {
|
|
62
|
+
source: Args.string({
|
|
63
|
+
required: true,
|
|
64
|
+
description: "Source locator. Supports local file paths, URLs, or machine IDs."
|
|
65
|
+
}),
|
|
66
|
+
target: Args.string({
|
|
67
|
+
required: true,
|
|
68
|
+
description: "Target locator. Supports local file paths, URLs, or machine IDs."
|
|
69
|
+
})
|
|
70
|
+
};
|
|
71
|
+
var ParsedSyncCommand = class extends BaseSyncCommand {
|
|
72
|
+
async parseSync(command) {
|
|
73
|
+
return this.parse(command);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
var PlanCommand = class PlanCommand extends ParsedSyncCommand {
|
|
77
|
+
static summary = "Plan semantic sync changes between a source and target.";
|
|
78
|
+
static description = "Resolves the source and target, normalizes both into graph form, and prints a semantic change summary.";
|
|
79
|
+
static args = sharedArgs;
|
|
80
|
+
async run() {
|
|
81
|
+
const { args, flags } = await this.parseSync(PlanCommand);
|
|
82
|
+
const plan = await planSync({
|
|
83
|
+
source: args.source,
|
|
84
|
+
target: args.target,
|
|
85
|
+
apiKey: flags["api-key"],
|
|
86
|
+
baseUrl: flags["base-url"]
|
|
87
|
+
});
|
|
88
|
+
this.log(formatPlanSummary(plan));
|
|
89
|
+
this.exit(flags["fail-on-changes"] && plan.summary.hasChanges ? 1 : 0);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
var DiffCommand = class DiffCommand extends ParsedSyncCommand {
|
|
93
|
+
static summary = "Diff a source and target using semantic graph comparison.";
|
|
94
|
+
static description = "Like plan, but intended for diff-style usage and exit codes in scripts.";
|
|
95
|
+
static args = sharedArgs;
|
|
96
|
+
async run() {
|
|
97
|
+
const { args, flags } = await this.parseSync(DiffCommand);
|
|
98
|
+
const plan = await planSync({
|
|
99
|
+
source: args.source,
|
|
100
|
+
target: args.target,
|
|
101
|
+
apiKey: flags["api-key"],
|
|
102
|
+
baseUrl: flags["base-url"]
|
|
103
|
+
});
|
|
104
|
+
this.log(formatPlanSummary(plan));
|
|
105
|
+
this.exit(flags["fail-on-changes"] && plan.summary.hasChanges ? 1 : 0);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
var PullCommand = class PullCommand extends ParsedSyncCommand {
|
|
109
|
+
static summary = "Pull a source locator into a local target file.";
|
|
110
|
+
static description = "Resolves the source, materializes it in the target format inferred from the target file, and writes the result locally.";
|
|
111
|
+
static args = sharedArgs;
|
|
112
|
+
async run() {
|
|
113
|
+
const { args, flags } = await this.parseSync(PullCommand);
|
|
114
|
+
const result = await pullSync({
|
|
115
|
+
source: args.source,
|
|
116
|
+
target: args.target,
|
|
117
|
+
apiKey: flags["api-key"],
|
|
118
|
+
baseUrl: flags["base-url"]
|
|
119
|
+
});
|
|
120
|
+
this.log(`Pulled: ${result.source.locator} -> ${result.outputPath}\nTarget: ${result.target.kind} (${result.target.format})`);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const COMMANDS = {
|
|
124
|
+
plan: PlanCommand,
|
|
125
|
+
diff: DiffCommand,
|
|
126
|
+
pull: PullCommand
|
|
127
|
+
};
|
|
128
|
+
async function run(argv = process.argv.slice(2)) {
|
|
129
|
+
const normalizedArgv = argv.length === 1 && argv[0] === "-h" ? ["--help"] : argv;
|
|
130
|
+
try {
|
|
131
|
+
await run$1(normalizedArgv, import.meta.url);
|
|
132
|
+
await flush();
|
|
133
|
+
} catch (error) {
|
|
134
|
+
await handle(error);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (process.argv[1] && import.meta.url === new URL(`file://${process.argv[1]}`).href) run();
|
|
138
|
+
|
|
139
|
+
//#endregion
|
|
140
|
+
export { COMMANDS, formatPlanSummary, run };
|
package/dist/embed.d.mts
CHANGED
|
@@ -1,10 +1,32 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as EmbedMode, c as ExportFormatMap, d as UploadResult, i as EmbedEventName, l as InitOptions, n as EmbedEventHandler, o as ExportCallOptions, r as EmbedEventMap, s as ExportFormat, t as CommentsConfig } from "./protocol-BgXSkIuc.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/embed.d.ts
|
|
4
|
+
interface AssetConfig {
|
|
5
|
+
/**
|
|
6
|
+
* Called when the embed needs to upload a file.
|
|
7
|
+
* Receives a real File object (reconstructed from serialized data).
|
|
8
|
+
* Throwing or rejecting will show an error toast in the embed.
|
|
9
|
+
*/
|
|
10
|
+
onUploadRequest: (file: File, context: {
|
|
11
|
+
stateNodeId: string;
|
|
12
|
+
}) => Promise<UploadResult>;
|
|
13
|
+
/**
|
|
14
|
+
* Accepted MIME types. Supports wildcards (e.g. 'image/*').
|
|
15
|
+
* @default ['image/*']
|
|
16
|
+
*/
|
|
17
|
+
accept?: string[];
|
|
18
|
+
/**
|
|
19
|
+
* Maximum file size in bytes.
|
|
20
|
+
* @default 10_485_760 (10MB)
|
|
21
|
+
*/
|
|
22
|
+
maxFileSize?: number;
|
|
23
|
+
}
|
|
4
24
|
interface StatelyEmbedOptions {
|
|
5
25
|
baseUrl: string;
|
|
6
26
|
apiKey?: string;
|
|
7
27
|
origin?: string;
|
|
28
|
+
/** Asset upload configuration. If omitted, files are stored as base64 data URLs. */
|
|
29
|
+
assets?: AssetConfig;
|
|
8
30
|
onReady?: () => void;
|
|
9
31
|
onLoaded?: (graph: unknown) => void;
|
|
10
32
|
onChange?: (graph: unknown, machineConfig: unknown) => void;
|
|
@@ -40,4 +62,4 @@ interface StatelyEmbed {
|
|
|
40
62
|
}
|
|
41
63
|
declare function createStatelyEmbed(options: StatelyEmbedOptions): StatelyEmbed;
|
|
42
64
|
//#endregion
|
|
43
|
-
export { type EmbedEventHandler, type EmbedEventMap, type EmbedEventName, type EmbedMode, type ExportCallOptions, type ExportFormat, type ExportFormatMap, type InitOptions, StatelyEmbed, StatelyEmbedOptions, createStatelyEmbed };
|
|
65
|
+
export { AssetConfig, type CommentsConfig, type EmbedEventHandler, type EmbedEventMap, type EmbedEventName, type EmbedMode, type ExportCallOptions, type ExportFormat, type ExportFormatMap, type InitOptions, StatelyEmbed, StatelyEmbedOptions, type UploadResult, createStatelyEmbed };
|
package/dist/embed.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as createPendingExportManager, o as toInitMessage, r as createEventRegistry, t as createPostMessageTransport } from "./transport-
|
|
1
|
+
import { i as createPendingExportManager, o as toInitMessage, r as createEventRegistry, t as createPostMessageTransport } from "./transport-C1fRAuv-.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/embed.ts
|
|
4
4
|
function createStatelyEmbed(options) {
|
|
@@ -32,6 +32,12 @@ function createStatelyEmbed(options) {
|
|
|
32
32
|
case "@statelyai.ready": {
|
|
33
33
|
const ready = data;
|
|
34
34
|
flush();
|
|
35
|
+
if (options.assets?.onUploadRequest) send({
|
|
36
|
+
type: "@statelyai.uploadCapabilities",
|
|
37
|
+
enabled: true,
|
|
38
|
+
accept: options.assets.accept,
|
|
39
|
+
maxFileSize: options.assets.maxFileSize
|
|
40
|
+
});
|
|
35
41
|
options.onReady?.();
|
|
36
42
|
events.emit("ready", { version: ready.version });
|
|
37
43
|
break;
|
|
@@ -76,6 +82,47 @@ function createStatelyEmbed(options) {
|
|
|
76
82
|
events.emit("error", err);
|
|
77
83
|
break;
|
|
78
84
|
}
|
|
85
|
+
case "@statelyai.uploadRequest": {
|
|
86
|
+
const req = data;
|
|
87
|
+
if (!options.assets?.onUploadRequest) {
|
|
88
|
+
send({
|
|
89
|
+
type: "@statelyai.error",
|
|
90
|
+
requestId: req.requestId,
|
|
91
|
+
code: "upload_not_configured",
|
|
92
|
+
message: "No upload handler configured"
|
|
93
|
+
});
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
const maxSize = options.assets.maxFileSize ?? 10485760;
|
|
97
|
+
if (req.file.size > maxSize) {
|
|
98
|
+
send({
|
|
99
|
+
type: "@statelyai.error",
|
|
100
|
+
requestId: req.requestId,
|
|
101
|
+
code: "upload_file_too_large",
|
|
102
|
+
message: `File exceeds maximum size of ${maxSize} bytes`
|
|
103
|
+
});
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
const binary = atob(req.file.data);
|
|
107
|
+
const bytes = new Uint8Array(binary.length);
|
|
108
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
109
|
+
const file = new File([bytes], req.file.name, { type: req.file.mimeType });
|
|
110
|
+
options.assets.onUploadRequest(file, { stateNodeId: req.stateNodeId }).then((result) => {
|
|
111
|
+
send({
|
|
112
|
+
type: "@statelyai.uploadResponse",
|
|
113
|
+
requestId: req.requestId,
|
|
114
|
+
result
|
|
115
|
+
});
|
|
116
|
+
}).catch((err) => {
|
|
117
|
+
send({
|
|
118
|
+
type: "@statelyai.error",
|
|
119
|
+
requestId: req.requestId,
|
|
120
|
+
code: "upload_failed",
|
|
121
|
+
message: err instanceof Error ? err.message : "Upload failed"
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
79
126
|
}
|
|
80
127
|
}
|
|
81
128
|
function replaceTransport(nextTransport) {
|
|
@@ -388,6 +388,6 @@ type StudioAction = DigraphAction;
|
|
|
388
388
|
type StudioEventTypeData = EventTypeData;
|
|
389
389
|
declare function toStudioMachine(graph: StatelyGraph): StudioMachine;
|
|
390
390
|
declare function fromStudioMachine(studioMachine: StudioMachine): StatelyGraph;
|
|
391
|
-
declare const studioMachineConverter: _statelyai_graph0.GraphFormatConverter<DigraphConfig>;
|
|
391
|
+
declare const studioMachineConverter: _statelyai_graph0.GraphFormatConverter<DigraphConfig, StatelyNodeData, StatelyEdgeData, StatelyGraphData>;
|
|
392
392
|
//#endregion
|
|
393
393
|
export { EventTypeData as C, DigraphNodeConfig as S, studioMachineConverter as _, StatelyGraphData as a, DigraphConfig as b, StatelyInvoke as c, StudioAction as d, StudioEdge as f, fromStudioMachine as g, StudioNode as h, StatelyGraph as i, StatelyNodeData as l, StudioMachine as m, StatelyActorImplementation as n, StatelyGuard as o, StudioEventTypeData as p, StatelyEdgeData as r, StatelyImplementation as s, StatelyAction as t, StatelyTagImplementation as u, toStudioMachine as v, StateNodeJSONData as w, DigraphEdgeConfig as x, DigraphAction as y };
|
package/dist/graph.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as studioMachineConverter, a as StatelyGraphData, c as StatelyInvoke, d as StudioAction, f as StudioEdge, g as fromStudioMachine, h as StudioNode, i as StatelyGraph, l as StatelyNodeData, m as StudioMachine, n as StatelyActorImplementation, o as StatelyGuard, p as StudioEventTypeData, r as StatelyEdgeData, s as StatelyImplementation, t as StatelyAction, u as StatelyTagImplementation, v as toStudioMachine } from "./graph-
|
|
1
|
+
import { _ as studioMachineConverter, a as StatelyGraphData, c as StatelyInvoke, d as StudioAction, f as StudioEdge, g as fromStudioMachine, h as StudioNode, i as StatelyGraph, l as StatelyNodeData, m as StudioMachine, n as StatelyActorImplementation, o as StatelyGuard, p as StudioEventTypeData, r as StatelyEdgeData, s as StatelyImplementation, t as StatelyAction, u as StatelyTagImplementation, v as toStudioMachine } from "./graph-BfezxFKJ.mjs";
|
|
2
2
|
export { StatelyAction, StatelyActorImplementation, StatelyEdgeData, StatelyGraph, StatelyGraphData, StatelyGuard, StatelyImplementation, StatelyInvoke, StatelyNodeData, StatelyTagImplementation, StudioAction, StudioEdge, StudioEventTypeData, StudioMachine, StudioNode, fromStudioMachine, studioMachineConverter, toStudioMachine };
|