@statelyai/sdk 0.1.1 → 0.2.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 +20 -20
- package/dist/index.d.mts +33 -71
- package/dist/index.mjs +45 -83
- package/dist/inspect-Bt5Ohkrp.d.mts +214 -0
- package/dist/inspect-C3Rjgn1o.mjs +369 -0
- package/dist/inspect.d.mts +2 -0
- package/dist/inspect.mjs +3 -0
- package/package.json +16 -8
package/README.md
CHANGED
|
@@ -46,20 +46,20 @@ embed.init({
|
|
|
46
46
|
|
|
47
47
|
Creates an embed instance.
|
|
48
48
|
|
|
49
|
-
| Option
|
|
50
|
-
|
|
51
|
-
| `baseUrl`
|
|
52
|
-
| `apiKey`
|
|
53
|
-
| `origin`
|
|
54
|
-
| `onReady`
|
|
55
|
-
| `onLoaded` | `(graph) => void`
|
|
56
|
-
| `onChange` | `(graph, machineConfig) => void` | Called on every change
|
|
57
|
-
| `onSave`
|
|
58
|
-
| `onError`
|
|
49
|
+
| Option | Type | Description |
|
|
50
|
+
| ---------- | -------------------------------- | ----------------------------------------- |
|
|
51
|
+
| `baseUrl` | `string` | **Required.** Base URL of the Stately app |
|
|
52
|
+
| `apiKey` | `string` | **Required.** Your Stately API key |
|
|
53
|
+
| `origin` | `string` | Custom target origin for postMessage |
|
|
54
|
+
| `onReady` | `() => void` | Called when embed is ready |
|
|
55
|
+
| `onLoaded` | `(graph) => void` | Called when machine is loaded |
|
|
56
|
+
| `onChange` | `(graph, machineConfig) => void` | Called on every change |
|
|
57
|
+
| `onSave` | `(graph, machineConfig) => void` | Called on save |
|
|
58
|
+
| `onError` | `({ code, message }) => void` | Called on error |
|
|
59
59
|
|
|
60
60
|
### Embed methods
|
|
61
61
|
|
|
62
|
-
#### `mount(container)` / `attach(iframe)`
|
|
62
|
+
#### `embed.mount(container)` / `embed.attach(iframe)`
|
|
63
63
|
|
|
64
64
|
Mount creates an iframe inside a container element. Attach connects to an existing iframe.
|
|
65
65
|
|
|
@@ -71,7 +71,7 @@ const iframe = embed.mount(document.getElementById('editor')!);
|
|
|
71
71
|
embed.attach(document.querySelector('iframe')!);
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
#### `init(options)`
|
|
74
|
+
#### `embed.init(options)`
|
|
75
75
|
|
|
76
76
|
Initialize the embed with a machine and display options.
|
|
77
77
|
|
|
@@ -79,8 +79,8 @@ Initialize the embed with a machine and display options.
|
|
|
79
79
|
embed.init({
|
|
80
80
|
machine: machineConfig,
|
|
81
81
|
format: 'xstate', // optional
|
|
82
|
-
mode: 'editing',
|
|
83
|
-
theme: 'dark',
|
|
82
|
+
mode: 'editing', // 'editing' | 'viewing' | 'simulating'
|
|
83
|
+
theme: 'dark', // 'light' | 'dark'
|
|
84
84
|
readOnly: false,
|
|
85
85
|
depth: 3,
|
|
86
86
|
panels: {
|
|
@@ -91,15 +91,15 @@ embed.init({
|
|
|
91
91
|
});
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
#### `updateMachine(machine, format?)`
|
|
94
|
+
#### `embed.updateMachine(machine, format?)`
|
|
95
95
|
|
|
96
96
|
Update the displayed machine.
|
|
97
97
|
|
|
98
|
-
#### `setMode(mode)` / `setTheme(theme)`
|
|
98
|
+
#### `embed.setMode(mode)` / `embed.setTheme(theme)`
|
|
99
99
|
|
|
100
100
|
Change the embed mode or theme at runtime.
|
|
101
101
|
|
|
102
|
-
#### `export(format, options?)`
|
|
102
|
+
#### `embed.export(format, options?)`
|
|
103
103
|
|
|
104
104
|
Export the current machine. Returns a promise.
|
|
105
105
|
|
|
@@ -111,7 +111,7 @@ const mermaid = await embed.export('mermaid');
|
|
|
111
111
|
|
|
112
112
|
Supported formats: `xstate`, `json`, `digraph`, `mermaid`, `scxml`
|
|
113
113
|
|
|
114
|
-
#### `on(event, handler)` / `off(event, handler)`
|
|
114
|
+
#### `embed.on(event, handler)` / `embed.off(event, handler)`
|
|
115
115
|
|
|
116
116
|
Subscribe/unsubscribe to embed events: `ready`, `loaded`, `change`, `save`, `error`.
|
|
117
117
|
|
|
@@ -121,10 +121,10 @@ embed.on('change', ({ graph, machineConfig }) => {
|
|
|
121
121
|
});
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
#### `toast(message, type?)`
|
|
124
|
+
#### `embed.toast(message, type?)`
|
|
125
125
|
|
|
126
126
|
Show a toast notification in the embed. Type: `'success' | 'error' | 'info' | 'warning'`
|
|
127
127
|
|
|
128
|
-
#### `destroy()`
|
|
128
|
+
#### `embed.destroy()`
|
|
129
129
|
|
|
130
130
|
Tear down the embed. Removes listeners, rejects pending promises, and removes the iframe if it was created via `mount()`.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,74 +1,6 @@
|
|
|
1
|
+
import { a as EmbedEventHandler, c as EmbedMode, d as ExportFormatMap, f as InitOptions, i as createInspector, l as ExportCallOptions, n as InspectOptions, o as EmbedEventMap, p as ProtocolMessage, r as Inspector, s as EmbedEventName, t as CreateInspectorOptions, u as ExportFormat } from "./inspect-Bt5Ohkrp.mjs";
|
|
2
|
+
|
|
1
3
|
//#region src/embed.d.ts
|
|
2
|
-
interface ExportFormatMap {
|
|
3
|
-
xstate: {
|
|
4
|
-
options: {
|
|
5
|
-
version?: 4 | 5;
|
|
6
|
-
addTSTypes?: boolean;
|
|
7
|
-
showIds?: boolean;
|
|
8
|
-
showDescriptions?: boolean;
|
|
9
|
-
};
|
|
10
|
-
result: string;
|
|
11
|
-
};
|
|
12
|
-
json: {
|
|
13
|
-
options: {
|
|
14
|
-
simplifyArrays?: boolean;
|
|
15
|
-
version?: 4 | 5;
|
|
16
|
-
};
|
|
17
|
-
result: Record<string, unknown>;
|
|
18
|
-
};
|
|
19
|
-
digraph: {
|
|
20
|
-
options: Record<string, never>;
|
|
21
|
-
result: Record<string, unknown>;
|
|
22
|
-
};
|
|
23
|
-
mermaid: {
|
|
24
|
-
options: Record<string, never>;
|
|
25
|
-
result: string;
|
|
26
|
-
};
|
|
27
|
-
scxml: {
|
|
28
|
-
options: Record<string, never>;
|
|
29
|
-
result: string;
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
type ExportFormat = keyof ExportFormatMap;
|
|
33
|
-
type ExportCallOptions<F extends ExportFormat> = ExportFormatMap[F]['options'] & {
|
|
34
|
-
timeout?: number;
|
|
35
|
-
};
|
|
36
|
-
type EmbedMode = 'editing' | 'viewing' | 'simulating';
|
|
37
|
-
interface InitOptions {
|
|
38
|
-
machine: unknown;
|
|
39
|
-
format?: string;
|
|
40
|
-
mode?: EmbedMode;
|
|
41
|
-
theme?: 'light' | 'dark';
|
|
42
|
-
readOnly?: boolean;
|
|
43
|
-
depth?: number;
|
|
44
|
-
panels?: {
|
|
45
|
-
leftPanels?: string[];
|
|
46
|
-
rightPanels?: string[];
|
|
47
|
-
activePanels?: string[];
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
interface EmbedEventMap {
|
|
51
|
-
ready: {
|
|
52
|
-
version: string;
|
|
53
|
-
};
|
|
54
|
-
loaded: {
|
|
55
|
-
graph: unknown;
|
|
56
|
-
};
|
|
57
|
-
change: {
|
|
58
|
-
graph: unknown;
|
|
59
|
-
machineConfig: unknown;
|
|
60
|
-
};
|
|
61
|
-
save: {
|
|
62
|
-
graph: unknown;
|
|
63
|
-
machineConfig: unknown;
|
|
64
|
-
};
|
|
65
|
-
error: {
|
|
66
|
-
code: string;
|
|
67
|
-
message: string;
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
type EmbedEventName = keyof EmbedEventMap;
|
|
71
|
-
type EmbedEventHandler<K extends EmbedEventName> = (data: EmbedEventMap[K]) => void;
|
|
72
4
|
interface StatelyEmbedOptions {
|
|
73
5
|
baseUrl: string;
|
|
74
6
|
apiKey?: string;
|
|
@@ -108,4 +40,34 @@ interface StatelyEmbed {
|
|
|
108
40
|
}
|
|
109
41
|
declare function createStatelyEmbed(options: StatelyEmbedOptions): StatelyEmbed;
|
|
110
42
|
//#endregion
|
|
111
|
-
|
|
43
|
+
//#region src/transport.d.ts
|
|
44
|
+
interface Transport {
|
|
45
|
+
send(msg: ProtocolMessage): void;
|
|
46
|
+
onMessage(handler: (msg: ProtocolMessage) => void): () => void;
|
|
47
|
+
destroy(): void;
|
|
48
|
+
readonly ready: boolean;
|
|
49
|
+
onReady(handler: () => void): () => void;
|
|
50
|
+
}
|
|
51
|
+
interface PostMessageTransportOptions {
|
|
52
|
+
iframe: HTMLIFrameElement;
|
|
53
|
+
targetOrigin: string;
|
|
54
|
+
/** Filter by source. Defaults to iframe.contentWindow. */
|
|
55
|
+
source?: Window;
|
|
56
|
+
}
|
|
57
|
+
declare function createPostMessageTransport(options: PostMessageTransportOptions): Transport;
|
|
58
|
+
interface WebSocketTransportOptions {
|
|
59
|
+
url: string;
|
|
60
|
+
role: 'client' | 'viz';
|
|
61
|
+
sessionId: string;
|
|
62
|
+
metadata?: {
|
|
63
|
+
name?: string;
|
|
64
|
+
machineId?: string;
|
|
65
|
+
};
|
|
66
|
+
/** Reconnect on disconnect. Default true. */
|
|
67
|
+
reconnect?: boolean;
|
|
68
|
+
/** Max reconnect attempts. Default 10. */
|
|
69
|
+
maxReconnectAttempts?: number;
|
|
70
|
+
}
|
|
71
|
+
declare function createWebSocketTransport(options: WebSocketTransportOptions): Transport;
|
|
72
|
+
//#endregion
|
|
73
|
+
export { type CreateInspectorOptions, type EmbedEventHandler, type EmbedEventMap, type EmbedEventName, type EmbedMode, type ExportCallOptions, type ExportFormat, type ExportFormatMap, type InitOptions, type InspectOptions, type Inspector, type StatelyEmbed, type StatelyEmbedOptions, type Transport, createInspector, createPostMessageTransport, createStatelyEmbed, createWebSocketTransport };
|
package/dist/index.mjs
CHANGED
|
@@ -1,95 +1,96 @@
|
|
|
1
|
+
import { a as createPendingExportManager, i as createEventRegistry, n as createPostMessageTransport, o as toInitMessage, r as createWebSocketTransport, t as createInspector } from "./inspect-C3Rjgn1o.mjs";
|
|
2
|
+
|
|
1
3
|
//#region src/embed.ts
|
|
2
|
-
const PREFIX = "@statelyai.";
|
|
3
4
|
function createStatelyEmbed(options) {
|
|
4
5
|
const base = options.baseUrl.replace(/\/+$/, "") + "/embed";
|
|
5
6
|
const embedUrl = options.apiKey ? `${base}?api_key=${encodeURIComponent(options.apiKey)}` : base;
|
|
6
7
|
const targetOrigin = options.origin ?? new URL(embedUrl).origin;
|
|
7
8
|
let iframe = null;
|
|
9
|
+
let transport = null;
|
|
8
10
|
let ownedIframe = false;
|
|
9
|
-
let ready = false;
|
|
10
11
|
let destroyed = false;
|
|
11
12
|
const pendingMessages = [];
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const listeners = {};
|
|
15
|
-
function emit(event, data) {
|
|
16
|
-
const set = listeners[event];
|
|
17
|
-
if (set) set.forEach((fn) => fn(data));
|
|
18
|
-
}
|
|
13
|
+
const events = createEventRegistry();
|
|
14
|
+
const exportManager = createPendingExportManager((message) => send(message));
|
|
19
15
|
function send(msg) {
|
|
20
|
-
if (!ready) {
|
|
16
|
+
if (!transport?.ready) {
|
|
21
17
|
pendingMessages.push(msg);
|
|
22
18
|
return;
|
|
23
19
|
}
|
|
24
|
-
|
|
20
|
+
transport.send(msg);
|
|
25
21
|
}
|
|
26
22
|
function flush() {
|
|
23
|
+
if (!transport) return;
|
|
27
24
|
while (pendingMessages.length > 0) {
|
|
28
25
|
const msg = pendingMessages.shift();
|
|
29
|
-
|
|
26
|
+
transport.send(msg);
|
|
30
27
|
}
|
|
31
28
|
}
|
|
32
|
-
function handleMessage(
|
|
29
|
+
function handleMessage(data) {
|
|
33
30
|
if (destroyed) return;
|
|
34
|
-
if (e.source !== iframe?.contentWindow) return;
|
|
35
|
-
const data = e.data;
|
|
36
|
-
if (!data?.type?.startsWith?.(PREFIX)) return;
|
|
37
31
|
switch (data.type) {
|
|
38
32
|
case "@statelyai.ready":
|
|
39
|
-
ready = true;
|
|
40
33
|
flush();
|
|
41
34
|
options.onReady?.();
|
|
42
|
-
emit("ready", { version: data.version });
|
|
35
|
+
events.emit("ready", { version: data.version });
|
|
43
36
|
break;
|
|
44
37
|
case "@statelyai.loaded":
|
|
45
38
|
options.onLoaded?.(data.graph);
|
|
46
|
-
emit("loaded", { graph: data.graph });
|
|
39
|
+
events.emit("loaded", { graph: data.graph });
|
|
47
40
|
break;
|
|
48
41
|
case "@statelyai.change":
|
|
49
42
|
options.onChange?.(data.graph, data.machineConfig);
|
|
50
|
-
emit("change", {
|
|
43
|
+
events.emit("change", {
|
|
51
44
|
graph: data.graph,
|
|
52
45
|
machineConfig: data.machineConfig
|
|
53
46
|
});
|
|
54
47
|
break;
|
|
55
48
|
case "@statelyai.save":
|
|
56
49
|
options.onSave?.(data.graph, data.machineConfig);
|
|
57
|
-
emit("save", {
|
|
50
|
+
events.emit("save", {
|
|
58
51
|
graph: data.graph,
|
|
59
52
|
machineConfig: data.machineConfig
|
|
60
53
|
});
|
|
61
54
|
break;
|
|
62
55
|
case "@statelyai.retrieved":
|
|
63
|
-
if (
|
|
64
|
-
clearTimeout(pendingExport.timer);
|
|
65
|
-
let result = data.data;
|
|
66
|
-
if (jsonResultFormats.has(pendingExport.format) && typeof result === "string") result = JSON.parse(result);
|
|
67
|
-
pendingExport.resolve(result);
|
|
68
|
-
pendingExport = null;
|
|
69
|
-
}
|
|
56
|
+
if (typeof data.requestId === "string") exportManager.resolve(data.requestId, data.data);
|
|
70
57
|
break;
|
|
71
58
|
case "@statelyai.error": {
|
|
72
59
|
const err = {
|
|
73
60
|
code: data.code,
|
|
74
61
|
message: data.message
|
|
75
62
|
};
|
|
63
|
+
exportManager.reject(new Error(err.message), typeof data.requestId === "string" ? data.requestId : void 0);
|
|
76
64
|
options.onError?.(err);
|
|
77
|
-
emit("error", err);
|
|
65
|
+
events.emit("error", err);
|
|
78
66
|
break;
|
|
79
67
|
}
|
|
80
68
|
}
|
|
81
69
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
70
|
+
function replaceTransport(nextTransport) {
|
|
71
|
+
transport?.destroy();
|
|
72
|
+
transport = nextTransport;
|
|
73
|
+
}
|
|
74
|
+
function setupTransport(el) {
|
|
75
|
+
replaceTransport(createPostMessageTransport({
|
|
76
|
+
iframe: el,
|
|
77
|
+
targetOrigin
|
|
78
|
+
}));
|
|
79
|
+
transport.onMessage(handleMessage);
|
|
80
|
+
transport.onReady(flush);
|
|
84
81
|
}
|
|
85
82
|
return {
|
|
86
83
|
attach(el) {
|
|
87
84
|
if (destroyed) return;
|
|
85
|
+
const currentSrc = el.getAttribute("src");
|
|
86
|
+
if (currentSrc && currentSrc !== "about:blank" && el.src !== embedUrl) console.warn("Replacing existing iframe src during attach()", {
|
|
87
|
+
currentSrc,
|
|
88
|
+
nextSrc: embedUrl
|
|
89
|
+
});
|
|
88
90
|
iframe = el;
|
|
89
91
|
ownedIframe = false;
|
|
90
|
-
ready = false;
|
|
91
92
|
el.src = embedUrl;
|
|
92
|
-
|
|
93
|
+
setupTransport(el);
|
|
93
94
|
},
|
|
94
95
|
mount(container) {
|
|
95
96
|
if (destroyed) throw new Error("Embed is destroyed");
|
|
@@ -103,23 +104,11 @@ function createStatelyEmbed(options) {
|
|
|
103
104
|
container.appendChild(el);
|
|
104
105
|
iframe = el;
|
|
105
106
|
ownedIframe = true;
|
|
106
|
-
|
|
107
|
-
startListening();
|
|
107
|
+
setupTransport(el);
|
|
108
108
|
return el;
|
|
109
109
|
},
|
|
110
110
|
init(opts) {
|
|
111
|
-
send(
|
|
112
|
-
type: "@statelyai.init",
|
|
113
|
-
machine: opts.machine,
|
|
114
|
-
format: opts.format,
|
|
115
|
-
mode: opts.mode,
|
|
116
|
-
theme: opts.theme,
|
|
117
|
-
readOnly: opts.readOnly,
|
|
118
|
-
depth: opts.depth,
|
|
119
|
-
leftPanels: opts.panels?.leftPanels,
|
|
120
|
-
rightPanels: opts.panels?.rightPanels,
|
|
121
|
-
activePanels: opts.panels?.activePanels
|
|
122
|
-
});
|
|
111
|
+
send(toInitMessage(opts));
|
|
123
112
|
},
|
|
124
113
|
updateMachine(machine, format) {
|
|
125
114
|
send({
|
|
@@ -147,49 +136,22 @@ function createStatelyEmbed(options) {
|
|
|
147
136
|
toastType
|
|
148
137
|
});
|
|
149
138
|
},
|
|
150
|
-
export(format,
|
|
151
|
-
|
|
152
|
-
return new Promise((resolve, reject) => {
|
|
153
|
-
if (destroyed) {
|
|
154
|
-
reject(/* @__PURE__ */ new Error("Embed is destroyed"));
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
if (pendingExport) {
|
|
158
|
-
clearTimeout(pendingExport.timer);
|
|
159
|
-
pendingExport.reject(/* @__PURE__ */ new Error("Superseded by new export"));
|
|
160
|
-
}
|
|
161
|
-
pendingExport = {
|
|
162
|
-
resolve,
|
|
163
|
-
reject,
|
|
164
|
-
timer: setTimeout(() => {
|
|
165
|
-
pendingExport = null;
|
|
166
|
-
reject(/* @__PURE__ */ new Error("Export timed out"));
|
|
167
|
-
}, timeout),
|
|
168
|
-
format
|
|
169
|
-
};
|
|
170
|
-
send({
|
|
171
|
-
type: "@statelyai.retrieve",
|
|
172
|
-
format,
|
|
173
|
-
...Object.keys(formatOptions).length > 0 && { options: formatOptions }
|
|
174
|
-
});
|
|
175
|
-
});
|
|
139
|
+
export(format, callOptions) {
|
|
140
|
+
return exportManager.start(format, callOptions, "Embed is destroyed", () => destroyed);
|
|
176
141
|
},
|
|
177
142
|
on(event, handler) {
|
|
178
|
-
|
|
179
|
-
listeners[event].add(handler);
|
|
143
|
+
events.on(event, handler);
|
|
180
144
|
},
|
|
181
145
|
off(event, handler) {
|
|
182
|
-
|
|
146
|
+
events.off(event, handler);
|
|
183
147
|
},
|
|
184
148
|
destroy() {
|
|
185
149
|
if (destroyed) return;
|
|
186
150
|
destroyed = true;
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
pendingExport = null;
|
|
192
|
-
}
|
|
151
|
+
transport?.destroy();
|
|
152
|
+
transport = null;
|
|
153
|
+
exportManager.clear("Embed destroyed");
|
|
154
|
+
events.clear();
|
|
193
155
|
pendingMessages.length = 0;
|
|
194
156
|
if (ownedIframe && iframe) iframe.remove();
|
|
195
157
|
iframe = null;
|
|
@@ -198,4 +160,4 @@ function createStatelyEmbed(options) {
|
|
|
198
160
|
}
|
|
199
161
|
|
|
200
162
|
//#endregion
|
|
201
|
-
export { createStatelyEmbed };
|
|
163
|
+
export { createInspector, createPostMessageTransport, createStatelyEmbed, createWebSocketTransport };
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
//#region src/protocol.d.ts
|
|
2
|
+
type EmbedMode = 'editing' | 'viewing' | 'simulating' | 'inspecting';
|
|
3
|
+
interface ExportFormatMap {
|
|
4
|
+
xstate: {
|
|
5
|
+
options: {
|
|
6
|
+
version?: 4 | 5;
|
|
7
|
+
addTSTypes?: boolean;
|
|
8
|
+
showIds?: boolean;
|
|
9
|
+
showDescriptions?: boolean;
|
|
10
|
+
};
|
|
11
|
+
result: string;
|
|
12
|
+
};
|
|
13
|
+
json: {
|
|
14
|
+
options: {
|
|
15
|
+
simplifyArrays?: boolean;
|
|
16
|
+
version?: 4 | 5;
|
|
17
|
+
};
|
|
18
|
+
result: Record<string, unknown>;
|
|
19
|
+
};
|
|
20
|
+
digraph: {
|
|
21
|
+
options: Record<string, never>;
|
|
22
|
+
result: Record<string, unknown>;
|
|
23
|
+
};
|
|
24
|
+
mermaid: {
|
|
25
|
+
options: Record<string, never>;
|
|
26
|
+
result: string;
|
|
27
|
+
};
|
|
28
|
+
scxml: {
|
|
29
|
+
options: Record<string, never>;
|
|
30
|
+
result: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
type ExportFormat = keyof ExportFormatMap;
|
|
34
|
+
type ExportCallOptions<F extends ExportFormat> = ExportFormatMap[F]['options'] & {
|
|
35
|
+
timeout?: number;
|
|
36
|
+
};
|
|
37
|
+
interface EmbedEventMap {
|
|
38
|
+
ready: {
|
|
39
|
+
version: string;
|
|
40
|
+
};
|
|
41
|
+
loaded: {
|
|
42
|
+
graph: unknown;
|
|
43
|
+
};
|
|
44
|
+
change: {
|
|
45
|
+
graph: unknown;
|
|
46
|
+
machineConfig: unknown;
|
|
47
|
+
};
|
|
48
|
+
save: {
|
|
49
|
+
graph: unknown;
|
|
50
|
+
machineConfig: unknown;
|
|
51
|
+
};
|
|
52
|
+
error: {
|
|
53
|
+
code: string;
|
|
54
|
+
message: string;
|
|
55
|
+
};
|
|
56
|
+
snapshot: {
|
|
57
|
+
snapshot: unknown;
|
|
58
|
+
event: unknown | null;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
type EmbedEventName = keyof EmbedEventMap;
|
|
62
|
+
type EmbedEventHandler<K extends EmbedEventName> = (data: EmbedEventMap[K]) => void;
|
|
63
|
+
interface InitOptions {
|
|
64
|
+
machine: unknown;
|
|
65
|
+
format?: string;
|
|
66
|
+
mode?: EmbedMode;
|
|
67
|
+
theme?: 'light' | 'dark';
|
|
68
|
+
readOnly?: boolean;
|
|
69
|
+
depth?: number;
|
|
70
|
+
panels?: {
|
|
71
|
+
leftPanels?: string[];
|
|
72
|
+
rightPanels?: string[];
|
|
73
|
+
activePanels?: string[];
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
interface InitMessage {
|
|
77
|
+
type: '@statelyai.init';
|
|
78
|
+
machine: unknown;
|
|
79
|
+
format?: string;
|
|
80
|
+
mode?: EmbedMode;
|
|
81
|
+
theme?: 'light' | 'dark';
|
|
82
|
+
readOnly?: boolean;
|
|
83
|
+
depth?: number;
|
|
84
|
+
leftPanels?: string[];
|
|
85
|
+
rightPanels?: string[];
|
|
86
|
+
activePanels?: string[];
|
|
87
|
+
}
|
|
88
|
+
interface UpdateMessage {
|
|
89
|
+
type: '@statelyai.update';
|
|
90
|
+
machine: unknown;
|
|
91
|
+
format?: string;
|
|
92
|
+
}
|
|
93
|
+
interface SetModeMessage {
|
|
94
|
+
type: '@statelyai.setMode';
|
|
95
|
+
mode: EmbedMode;
|
|
96
|
+
}
|
|
97
|
+
interface SetThemeMessage {
|
|
98
|
+
type: '@statelyai.setTheme';
|
|
99
|
+
theme: 'light' | 'dark';
|
|
100
|
+
}
|
|
101
|
+
interface RetrieveMessage {
|
|
102
|
+
type: '@statelyai.retrieve';
|
|
103
|
+
requestId: string;
|
|
104
|
+
format: ExportFormat;
|
|
105
|
+
options?: Record<string, unknown>;
|
|
106
|
+
}
|
|
107
|
+
interface ToastMessage {
|
|
108
|
+
type: '@statelyai.toast';
|
|
109
|
+
message: string;
|
|
110
|
+
toastType?: 'success' | 'error' | 'info' | 'warning';
|
|
111
|
+
}
|
|
112
|
+
interface InspectSnapshotMessage {
|
|
113
|
+
type: '@statelyai.inspectSnapshot';
|
|
114
|
+
snapshot: unknown;
|
|
115
|
+
event: unknown | null;
|
|
116
|
+
}
|
|
117
|
+
/** All messages a client (embed/inspector) can send to the viz. */
|
|
118
|
+
type ClientMessage = InitMessage | UpdateMessage | SetModeMessage | SetThemeMessage | RetrieveMessage | ToastMessage | InspectSnapshotMessage;
|
|
119
|
+
interface ReadyMessage {
|
|
120
|
+
type: '@statelyai.ready';
|
|
121
|
+
version: string;
|
|
122
|
+
}
|
|
123
|
+
interface LoadedMessage {
|
|
124
|
+
type: '@statelyai.loaded';
|
|
125
|
+
graph: unknown;
|
|
126
|
+
}
|
|
127
|
+
interface ChangeMessage {
|
|
128
|
+
type: '@statelyai.change';
|
|
129
|
+
graph: unknown;
|
|
130
|
+
machineConfig: unknown;
|
|
131
|
+
}
|
|
132
|
+
interface SaveMessage {
|
|
133
|
+
type: '@statelyai.save';
|
|
134
|
+
graph: unknown;
|
|
135
|
+
machineConfig: unknown;
|
|
136
|
+
}
|
|
137
|
+
interface RetrievedMessage {
|
|
138
|
+
type: '@statelyai.retrieved';
|
|
139
|
+
requestId: string;
|
|
140
|
+
data: unknown;
|
|
141
|
+
}
|
|
142
|
+
interface ErrorMessage {
|
|
143
|
+
type: '@statelyai.error';
|
|
144
|
+
code: string;
|
|
145
|
+
message: string;
|
|
146
|
+
requestId?: string;
|
|
147
|
+
}
|
|
148
|
+
/** All messages the viz can send back to a client. */
|
|
149
|
+
type VizMessage = ReadyMessage | LoadedMessage | ChangeMessage | SaveMessage | RetrievedMessage | ErrorMessage;
|
|
150
|
+
interface RegisterMessage {
|
|
151
|
+
type: '@statelyai.register';
|
|
152
|
+
role: 'client' | 'viz';
|
|
153
|
+
sessionId: string;
|
|
154
|
+
metadata?: {
|
|
155
|
+
name?: string;
|
|
156
|
+
machineId?: string;
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
interface RegisteredMessage {
|
|
160
|
+
type: '@statelyai.registered';
|
|
161
|
+
sessionId: string;
|
|
162
|
+
}
|
|
163
|
+
interface RequestOpenMessage {
|
|
164
|
+
type: '@statelyai.requestOpen';
|
|
165
|
+
sessionId: string;
|
|
166
|
+
}
|
|
167
|
+
/** All session-management messages for the WS relay. */
|
|
168
|
+
type SessionMessage = RegisterMessage | RegisteredMessage | RequestOpenMessage;
|
|
169
|
+
/** Any valid protocol message. */
|
|
170
|
+
type ProtocolMessage = ClientMessage | VizMessage | SessionMessage;
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region src/inspect.d.ts
|
|
173
|
+
interface CreateInspectorOptions {
|
|
174
|
+
/** WebSocket URL of the devtools server. Default: 'ws://localhost:4242' */
|
|
175
|
+
url?: string;
|
|
176
|
+
/** Auto-open browser to visualizer. Default: true */
|
|
177
|
+
autoOpen?: boolean;
|
|
178
|
+
/** Unique session ID. Auto-generated if not provided. */
|
|
179
|
+
sessionId?: string;
|
|
180
|
+
/** Display name for this connection in the visualizer. */
|
|
181
|
+
name?: string;
|
|
182
|
+
}
|
|
183
|
+
interface Inspector {
|
|
184
|
+
/** Send a machine for inspection (starts visualization). */
|
|
185
|
+
inspect(options: InspectOptions): void;
|
|
186
|
+
/** Update the machine currently being inspected. */
|
|
187
|
+
update(machine: unknown, format?: string): void;
|
|
188
|
+
/** Change the visualization mode. */
|
|
189
|
+
setMode(mode: EmbedMode): void;
|
|
190
|
+
/** Export the current machine in a given format. Returns a promise. */
|
|
191
|
+
export<F extends ExportFormat>(format: F, options?: ExportCallOptions<F>): Promise<ExportFormatMap[F]['result']>;
|
|
192
|
+
/** Subscribe to events from the visualizer. */
|
|
193
|
+
on<K extends EmbedEventName>(event: K, handler: EmbedEventHandler<K>): void;
|
|
194
|
+
/** Unsubscribe from an event. */
|
|
195
|
+
off<K extends EmbedEventName>(event: K, handler: EmbedEventHandler<K>): void;
|
|
196
|
+
/** Send a state snapshot for real-time inspection. */
|
|
197
|
+
sendSnapshot(snapshot: unknown, event?: unknown): void;
|
|
198
|
+
/** Clean up the connection. */
|
|
199
|
+
destroy(): void;
|
|
200
|
+
/** Session ID for this connection. */
|
|
201
|
+
readonly sessionId: string;
|
|
202
|
+
}
|
|
203
|
+
interface InspectOptions {
|
|
204
|
+
machine: unknown;
|
|
205
|
+
format?: string;
|
|
206
|
+
mode?: EmbedMode;
|
|
207
|
+
theme?: 'light' | 'dark';
|
|
208
|
+
readOnly?: boolean;
|
|
209
|
+
depth?: number;
|
|
210
|
+
panels?: InitOptions['panels'];
|
|
211
|
+
}
|
|
212
|
+
declare function createInspector(options?: CreateInspectorOptions): Inspector;
|
|
213
|
+
//#endregion
|
|
214
|
+
export { EmbedEventHandler as a, EmbedMode as c, ExportFormatMap as d, InitOptions as f, createInspector as i, ExportCallOptions as l, InspectOptions as n, EmbedEventMap as o, ProtocolMessage as p, Inspector as r, EmbedEventName as s, CreateInspectorOptions as t, ExportFormat as u };
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
//#region src/clientUtils.ts
|
|
2
|
+
const jsonResultFormats = new Set(["digraph", "json"]);
|
|
3
|
+
function createRequestId() {
|
|
4
|
+
const cryptoObject = globalThis.crypto;
|
|
5
|
+
if (cryptoObject?.randomUUID) return cryptoObject.randomUUID();
|
|
6
|
+
return Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2);
|
|
7
|
+
}
|
|
8
|
+
function createEventRegistry() {
|
|
9
|
+
const listeners = {};
|
|
10
|
+
return {
|
|
11
|
+
emit(event, data) {
|
|
12
|
+
listeners[event]?.forEach((handler) => handler(data));
|
|
13
|
+
},
|
|
14
|
+
on(event, handler) {
|
|
15
|
+
if (!listeners[event]) listeners[event] = /* @__PURE__ */ new Set();
|
|
16
|
+
listeners[event].add(handler);
|
|
17
|
+
},
|
|
18
|
+
off(event, handler) {
|
|
19
|
+
listeners[event]?.delete(handler);
|
|
20
|
+
},
|
|
21
|
+
clear() {
|
|
22
|
+
Object.values(listeners).forEach((handlers) => handlers?.clear());
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function parseExportedData(format, data) {
|
|
27
|
+
if (jsonResultFormats.has(format) && typeof data === "string") return JSON.parse(data);
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
30
|
+
function createPendingExportManager(sendRetrieve) {
|
|
31
|
+
const pendingExports = /* @__PURE__ */ new Map();
|
|
32
|
+
return {
|
|
33
|
+
start(format, callOptions, destroyedMessage, isDestroyed) {
|
|
34
|
+
const { timeout = 1e4, ...formatOptions } = callOptions ?? {};
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
if (isDestroyed()) {
|
|
37
|
+
reject(new Error(destroyedMessage));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const requestId = createRequestId();
|
|
41
|
+
const timer = setTimeout(() => {
|
|
42
|
+
pendingExports.delete(requestId);
|
|
43
|
+
reject(/* @__PURE__ */ new Error("Export timed out"));
|
|
44
|
+
}, timeout);
|
|
45
|
+
pendingExports.set(requestId, {
|
|
46
|
+
resolve,
|
|
47
|
+
reject,
|
|
48
|
+
timer,
|
|
49
|
+
format
|
|
50
|
+
});
|
|
51
|
+
sendRetrieve({
|
|
52
|
+
type: "@statelyai.retrieve",
|
|
53
|
+
requestId,
|
|
54
|
+
format,
|
|
55
|
+
...Object.keys(formatOptions).length > 0 && { options: formatOptions }
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
resolve(requestId, data) {
|
|
60
|
+
const pendingExport = pendingExports.get(requestId);
|
|
61
|
+
if (!pendingExport) return;
|
|
62
|
+
pendingExports.delete(requestId);
|
|
63
|
+
const { resolve, timer, format } = pendingExport;
|
|
64
|
+
clearTimeout(timer);
|
|
65
|
+
resolve(parseExportedData(format, data));
|
|
66
|
+
},
|
|
67
|
+
reject(error, requestId) {
|
|
68
|
+
if (requestId) {
|
|
69
|
+
const pendingExport = pendingExports.get(requestId);
|
|
70
|
+
if (!pendingExport) return;
|
|
71
|
+
pendingExports.delete(requestId);
|
|
72
|
+
clearTimeout(pendingExport.timer);
|
|
73
|
+
pendingExport.reject(error);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
pendingExports.forEach((pendingExport, pendingRequestId) => {
|
|
77
|
+
pendingExports.delete(pendingRequestId);
|
|
78
|
+
clearTimeout(pendingExport.timer);
|
|
79
|
+
pendingExport.reject(error);
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
clear(message) {
|
|
83
|
+
this.reject(new Error(message));
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function toInitMessage(options) {
|
|
88
|
+
return {
|
|
89
|
+
type: "@statelyai.init",
|
|
90
|
+
machine: options.machine,
|
|
91
|
+
format: options.format,
|
|
92
|
+
mode: options.mode,
|
|
93
|
+
theme: options.theme,
|
|
94
|
+
readOnly: options.readOnly,
|
|
95
|
+
depth: options.depth,
|
|
96
|
+
leftPanels: options.panels?.leftPanels,
|
|
97
|
+
rightPanels: options.panels?.rightPanels,
|
|
98
|
+
activePanels: options.panels?.activePanels
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/protocol.ts
|
|
104
|
+
const PREFIX = "@statelyai.";
|
|
105
|
+
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/transport.ts
|
|
108
|
+
function createPostMessageTransport(options) {
|
|
109
|
+
const { iframe, targetOrigin } = options;
|
|
110
|
+
let destroyed = false;
|
|
111
|
+
let isReady = false;
|
|
112
|
+
const readyHandlers = /* @__PURE__ */ new Set();
|
|
113
|
+
const messageHandlers = /* @__PURE__ */ new Set();
|
|
114
|
+
function handleMessage(e) {
|
|
115
|
+
if (destroyed) return;
|
|
116
|
+
const expectedSource = options.source ?? iframe.contentWindow;
|
|
117
|
+
if (e.source !== expectedSource) return;
|
|
118
|
+
if (targetOrigin !== "*" && e.origin !== targetOrigin) return;
|
|
119
|
+
const data = e.data;
|
|
120
|
+
if (!data?.type?.startsWith?.(PREFIX)) return;
|
|
121
|
+
if (data.type === "@statelyai.ready" && !isReady) {
|
|
122
|
+
isReady = true;
|
|
123
|
+
readyHandlers.forEach((fn) => fn());
|
|
124
|
+
readyHandlers.clear();
|
|
125
|
+
}
|
|
126
|
+
messageHandlers.forEach((fn) => fn(data));
|
|
127
|
+
}
|
|
128
|
+
window.addEventListener("message", handleMessage);
|
|
129
|
+
return {
|
|
130
|
+
send(msg) {
|
|
131
|
+
if (destroyed) return;
|
|
132
|
+
iframe.contentWindow?.postMessage(msg, targetOrigin);
|
|
133
|
+
},
|
|
134
|
+
onMessage(handler) {
|
|
135
|
+
messageHandlers.add(handler);
|
|
136
|
+
return () => {
|
|
137
|
+
messageHandlers.delete(handler);
|
|
138
|
+
};
|
|
139
|
+
},
|
|
140
|
+
destroy() {
|
|
141
|
+
if (destroyed) return;
|
|
142
|
+
destroyed = true;
|
|
143
|
+
window.removeEventListener("message", handleMessage);
|
|
144
|
+
messageHandlers.clear();
|
|
145
|
+
readyHandlers.clear();
|
|
146
|
+
},
|
|
147
|
+
get ready() {
|
|
148
|
+
return isReady;
|
|
149
|
+
},
|
|
150
|
+
onReady(handler) {
|
|
151
|
+
if (isReady) {
|
|
152
|
+
handler();
|
|
153
|
+
return () => {};
|
|
154
|
+
}
|
|
155
|
+
readyHandlers.add(handler);
|
|
156
|
+
return () => {
|
|
157
|
+
readyHandlers.delete(handler);
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function createWebSocketTransport(options) {
|
|
163
|
+
const { url, role, sessionId, metadata, reconnect = true, maxReconnectAttempts = 10 } = options;
|
|
164
|
+
let ws = null;
|
|
165
|
+
let destroyed = false;
|
|
166
|
+
let isReady = false;
|
|
167
|
+
let reconnectAttempts = 0;
|
|
168
|
+
let reconnectTimer = null;
|
|
169
|
+
const readyHandlers = /* @__PURE__ */ new Set();
|
|
170
|
+
const messageHandlers = /* @__PURE__ */ new Set();
|
|
171
|
+
function connect() {
|
|
172
|
+
if (destroyed) return;
|
|
173
|
+
ws = new WebSocket(url);
|
|
174
|
+
ws.onopen = () => {
|
|
175
|
+
reconnectAttempts = 0;
|
|
176
|
+
ws.send(JSON.stringify({
|
|
177
|
+
type: "@statelyai.register",
|
|
178
|
+
role,
|
|
179
|
+
sessionId,
|
|
180
|
+
...metadata && { metadata }
|
|
181
|
+
}));
|
|
182
|
+
};
|
|
183
|
+
ws.onmessage = (event) => {
|
|
184
|
+
if (destroyed) return;
|
|
185
|
+
let raw;
|
|
186
|
+
try {
|
|
187
|
+
raw = JSON.parse(event.data);
|
|
188
|
+
} catch {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (!raw?.type || typeof raw.type !== "string") return;
|
|
192
|
+
if (!raw.type.startsWith(PREFIX)) return;
|
|
193
|
+
const data = raw;
|
|
194
|
+
if (data.type === "@statelyai.registered" && !isReady) {
|
|
195
|
+
isReady = true;
|
|
196
|
+
readyHandlers.forEach((fn) => fn());
|
|
197
|
+
readyHandlers.clear();
|
|
198
|
+
}
|
|
199
|
+
messageHandlers.forEach((fn) => fn(data));
|
|
200
|
+
};
|
|
201
|
+
ws.onclose = () => {
|
|
202
|
+
if (destroyed) return;
|
|
203
|
+
isReady = false;
|
|
204
|
+
if (reconnect && reconnectAttempts < maxReconnectAttempts) {
|
|
205
|
+
const delay = Math.min(1e3 * 2 ** reconnectAttempts, 3e4);
|
|
206
|
+
reconnectAttempts++;
|
|
207
|
+
reconnectTimer = setTimeout(connect, delay);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
ws.onerror = () => {};
|
|
211
|
+
}
|
|
212
|
+
connect();
|
|
213
|
+
return {
|
|
214
|
+
send(msg) {
|
|
215
|
+
if (destroyed || !ws || ws.readyState !== WebSocket.OPEN) return;
|
|
216
|
+
ws.send(JSON.stringify(msg));
|
|
217
|
+
},
|
|
218
|
+
onMessage(handler) {
|
|
219
|
+
messageHandlers.add(handler);
|
|
220
|
+
return () => {
|
|
221
|
+
messageHandlers.delete(handler);
|
|
222
|
+
};
|
|
223
|
+
},
|
|
224
|
+
destroy() {
|
|
225
|
+
if (destroyed) return;
|
|
226
|
+
destroyed = true;
|
|
227
|
+
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
228
|
+
ws?.close();
|
|
229
|
+
ws = null;
|
|
230
|
+
messageHandlers.clear();
|
|
231
|
+
readyHandlers.clear();
|
|
232
|
+
},
|
|
233
|
+
get ready() {
|
|
234
|
+
return isReady;
|
|
235
|
+
},
|
|
236
|
+
onReady(handler) {
|
|
237
|
+
if (isReady) {
|
|
238
|
+
handler();
|
|
239
|
+
return () => {};
|
|
240
|
+
}
|
|
241
|
+
readyHandlers.add(handler);
|
|
242
|
+
return () => {
|
|
243
|
+
readyHandlers.delete(handler);
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
//#endregion
|
|
250
|
+
//#region src/inspect.ts
|
|
251
|
+
function generateId() {
|
|
252
|
+
return createRequestId();
|
|
253
|
+
}
|
|
254
|
+
function createInspector(options) {
|
|
255
|
+
const { url = "ws://localhost:4242", autoOpen = true, sessionId = generateId(), name } = options ?? {};
|
|
256
|
+
let destroyed = false;
|
|
257
|
+
const pendingMessages = [];
|
|
258
|
+
const events = createEventRegistry();
|
|
259
|
+
const transport = createWebSocketTransport({
|
|
260
|
+
url,
|
|
261
|
+
role: "client",
|
|
262
|
+
sessionId,
|
|
263
|
+
...name && { metadata: { name } }
|
|
264
|
+
});
|
|
265
|
+
const exportManager = createPendingExportManager((message) => send(message));
|
|
266
|
+
function send(msg) {
|
|
267
|
+
if (!transport.ready) {
|
|
268
|
+
pendingMessages.push(msg);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
transport.send(msg);
|
|
272
|
+
}
|
|
273
|
+
function flush() {
|
|
274
|
+
while (pendingMessages.length > 0) {
|
|
275
|
+
const msg = pendingMessages.shift();
|
|
276
|
+
transport.send(msg);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
transport.onReady(() => {
|
|
280
|
+
flush();
|
|
281
|
+
});
|
|
282
|
+
if (autoOpen) transport.onReady(() => {
|
|
283
|
+
transport.send({
|
|
284
|
+
type: "@statelyai.requestOpen",
|
|
285
|
+
sessionId
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
transport.onMessage((msg) => {
|
|
289
|
+
if (destroyed) return;
|
|
290
|
+
switch (msg.type) {
|
|
291
|
+
case "@statelyai.ready":
|
|
292
|
+
events.emit("ready", { version: msg.version });
|
|
293
|
+
break;
|
|
294
|
+
case "@statelyai.loaded":
|
|
295
|
+
events.emit("loaded", { graph: msg.graph });
|
|
296
|
+
break;
|
|
297
|
+
case "@statelyai.change":
|
|
298
|
+
events.emit("change", {
|
|
299
|
+
graph: msg.graph,
|
|
300
|
+
machineConfig: msg.machineConfig
|
|
301
|
+
});
|
|
302
|
+
break;
|
|
303
|
+
case "@statelyai.save":
|
|
304
|
+
events.emit("save", {
|
|
305
|
+
graph: msg.graph,
|
|
306
|
+
machineConfig: msg.machineConfig
|
|
307
|
+
});
|
|
308
|
+
break;
|
|
309
|
+
case "@statelyai.retrieved":
|
|
310
|
+
exportManager.resolve(msg.requestId, msg.data);
|
|
311
|
+
break;
|
|
312
|
+
case "@statelyai.error":
|
|
313
|
+
exportManager.reject(new Error(msg.message), msg.requestId);
|
|
314
|
+
events.emit("error", {
|
|
315
|
+
code: msg.code,
|
|
316
|
+
message: msg.message
|
|
317
|
+
});
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
return {
|
|
322
|
+
get sessionId() {
|
|
323
|
+
return sessionId;
|
|
324
|
+
},
|
|
325
|
+
inspect(opts) {
|
|
326
|
+
send(toInitMessage(opts));
|
|
327
|
+
},
|
|
328
|
+
update(machine, format) {
|
|
329
|
+
send({
|
|
330
|
+
type: "@statelyai.update",
|
|
331
|
+
machine,
|
|
332
|
+
format
|
|
333
|
+
});
|
|
334
|
+
},
|
|
335
|
+
setMode(mode) {
|
|
336
|
+
send({
|
|
337
|
+
type: "@statelyai.setMode",
|
|
338
|
+
mode
|
|
339
|
+
});
|
|
340
|
+
},
|
|
341
|
+
export(format, callOptions) {
|
|
342
|
+
return exportManager.start(format, callOptions, "Inspector is destroyed", () => destroyed);
|
|
343
|
+
},
|
|
344
|
+
on(event, handler) {
|
|
345
|
+
events.on(event, handler);
|
|
346
|
+
},
|
|
347
|
+
off(event, handler) {
|
|
348
|
+
events.off(event, handler);
|
|
349
|
+
},
|
|
350
|
+
sendSnapshot(snapshot, event) {
|
|
351
|
+
send({
|
|
352
|
+
type: "@statelyai.inspectSnapshot",
|
|
353
|
+
snapshot,
|
|
354
|
+
event: event ?? null
|
|
355
|
+
});
|
|
356
|
+
},
|
|
357
|
+
destroy() {
|
|
358
|
+
if (destroyed) return;
|
|
359
|
+
destroyed = true;
|
|
360
|
+
transport.destroy();
|
|
361
|
+
exportManager.clear("Inspector destroyed");
|
|
362
|
+
events.clear();
|
|
363
|
+
pendingMessages.length = 0;
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
//#endregion
|
|
369
|
+
export { createPendingExportManager as a, createEventRegistry as i, createPostMessageTransport as n, toInitMessage as o, createWebSocketTransport as r, createInspector as t };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as EmbedEventHandler, c as EmbedMode, d as ExportFormatMap, f as InitOptions, i as createInspector, l as ExportCallOptions, n as InspectOptions, o as EmbedEventMap, r as Inspector, s as EmbedEventName, t as CreateInspectorOptions, u as ExportFormat } from "./inspect-Bt5Ohkrp.mjs";
|
|
2
|
+
export { CreateInspectorOptions, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap, InitOptions, InspectOptions, Inspector, createInspector };
|
package/dist/inspect.mjs
ADDED
package/package.json
CHANGED
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statelyai/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"license": "MIT",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
5
8
|
"type": "module",
|
|
6
9
|
"main": "./dist/index.mjs",
|
|
7
10
|
"types": "./dist/index.d.mts",
|
|
8
11
|
"exports": {
|
|
9
12
|
".": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
13
|
+
"types": "./dist/index.d.mts",
|
|
14
|
+
"import": "./dist/index.mjs"
|
|
15
|
+
},
|
|
16
|
+
"./inspect": {
|
|
17
|
+
"types": "./dist/inspect.d.mts",
|
|
18
|
+
"import": "./dist/inspect.mjs"
|
|
12
19
|
}
|
|
13
20
|
},
|
|
14
|
-
"files": [
|
|
15
|
-
"dist"
|
|
16
|
-
],
|
|
17
21
|
"devDependencies": {
|
|
22
|
+
"jsdom": "^27.4.0",
|
|
18
23
|
"tsdown": "0.21.0-beta.2",
|
|
19
|
-
"typescript": "^5.9.3"
|
|
24
|
+
"typescript": "^5.9.3",
|
|
25
|
+
"vitest": "^3.2.4"
|
|
20
26
|
},
|
|
21
27
|
"scripts": {
|
|
22
|
-
"build": "tsdown"
|
|
28
|
+
"build": "tsdown",
|
|
29
|
+
"test": "vitest run",
|
|
30
|
+
"test:watch": "vitest"
|
|
23
31
|
}
|
|
24
32
|
}
|