@statelyai/sdk 0.1.1 → 0.3.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 +145 -25
- package/dist/embed.d.mts +43 -0
- package/dist/embed.mjs +175 -0
- package/dist/graph-C-7ZK_nK.d.mts +393 -0
- package/dist/graph.d.mts +2 -0
- package/dist/graph.mjs +344 -0
- package/dist/index.d.mts +34 -107
- package/dist/index.mjs +7 -200
- package/dist/inspect.d.mts +45 -0
- package/dist/inspect.mjs +122 -0
- package/dist/protocol-BC-_s3if.d.mts +172 -0
- package/dist/studio.d.mts +54 -0
- package/dist/studio.mjs +62 -0
- package/dist/sync-CzEOizjx.mjs +558 -0
- package/dist/sync.d.mts +43 -0
- package/dist/sync.mjs +5 -0
- package/dist/transport-D352iKKa.mjs +250 -0
- package/package.json +36 -8
|
@@ -0,0 +1,250 @@
|
|
|
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
|
+
export { createRequestId as a, createPendingExportManager as i, createWebSocketTransport as n, toInitMessage as o, createEventRegistry as r, createPostMessageTransport as t };
|
package/package.json
CHANGED
|
@@ -1,24 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statelyai/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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
|
+
"./embed": {
|
|
17
|
+
"types": "./dist/embed.d.mts",
|
|
18
|
+
"import": "./dist/embed.mjs"
|
|
19
|
+
},
|
|
20
|
+
"./inspect": {
|
|
21
|
+
"types": "./dist/inspect.d.mts",
|
|
22
|
+
"import": "./dist/inspect.mjs"
|
|
23
|
+
},
|
|
24
|
+
"./graph": {
|
|
25
|
+
"types": "./dist/graph.d.mts",
|
|
26
|
+
"import": "./dist/graph.mjs"
|
|
27
|
+
},
|
|
28
|
+
"./sync": {
|
|
29
|
+
"types": "./dist/sync.d.mts",
|
|
30
|
+
"import": "./dist/sync.mjs"
|
|
31
|
+
},
|
|
32
|
+
"./studio": {
|
|
33
|
+
"types": "./dist/studio.d.mts",
|
|
34
|
+
"import": "./dist/studio.mjs"
|
|
12
35
|
}
|
|
13
36
|
},
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@statelyai/graph": "^0.4.0"
|
|
39
|
+
},
|
|
17
40
|
"devDependencies": {
|
|
41
|
+
"jsdom": "^27.4.0",
|
|
18
42
|
"tsdown": "0.21.0-beta.2",
|
|
19
|
-
"typescript": "^5.9.3"
|
|
43
|
+
"typescript": "^5.9.3",
|
|
44
|
+
"vitest": "^3.2.4"
|
|
20
45
|
},
|
|
21
46
|
"scripts": {
|
|
22
|
-
"build": "tsdown"
|
|
47
|
+
"build": "tsdown",
|
|
48
|
+
"test": "vitest run",
|
|
49
|
+
"test:live": "vitest run src/studio.live.integration.test.ts",
|
|
50
|
+
"test:watch": "vitest"
|
|
23
51
|
}
|
|
24
52
|
}
|