@statelyai/sdk 0.2.0 → 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/dist/inspect.mjs CHANGED
@@ -1,3 +1,122 @@
1
- import { t as createInspector } from "./inspect-C3Rjgn1o.mjs";
1
+ import { a as createRequestId, i as createPendingExportManager, n as createWebSocketTransport, o as toInitMessage, r as createEventRegistry } from "./transport-D352iKKa.mjs";
2
2
 
3
- export { createInspector };
3
+ //#region src/inspect.ts
4
+ function generateId() {
5
+ return createRequestId();
6
+ }
7
+ function createStatelyInspector(options) {
8
+ const { url = "ws://localhost:4242", autoOpen = true, sessionId = generateId(), name } = options ?? {};
9
+ let destroyed = false;
10
+ const pendingMessages = [];
11
+ const events = createEventRegistry();
12
+ const transport = createWebSocketTransport({
13
+ url,
14
+ role: "client",
15
+ sessionId,
16
+ ...name && { metadata: { name } }
17
+ });
18
+ const exportManager = createPendingExportManager((message) => send(message));
19
+ function send(msg) {
20
+ if (!transport.ready) {
21
+ pendingMessages.push(msg);
22
+ return;
23
+ }
24
+ transport.send(msg);
25
+ }
26
+ function flush() {
27
+ while (pendingMessages.length > 0) {
28
+ const msg = pendingMessages.shift();
29
+ transport.send(msg);
30
+ }
31
+ }
32
+ transport.onReady(() => {
33
+ flush();
34
+ });
35
+ if (autoOpen) transport.onReady(() => {
36
+ transport.send({
37
+ type: "@statelyai.requestOpen",
38
+ sessionId
39
+ });
40
+ });
41
+ transport.onMessage((msg) => {
42
+ if (destroyed) return;
43
+ switch (msg.type) {
44
+ case "@statelyai.ready":
45
+ events.emit("ready", { version: msg.version });
46
+ break;
47
+ case "@statelyai.loaded":
48
+ events.emit("loaded", { graph: msg.graph });
49
+ break;
50
+ case "@statelyai.change":
51
+ events.emit("change", {
52
+ graph: msg.graph,
53
+ machineConfig: msg.machineConfig
54
+ });
55
+ break;
56
+ case "@statelyai.save":
57
+ events.emit("save", {
58
+ graph: msg.graph,
59
+ machineConfig: msg.machineConfig
60
+ });
61
+ break;
62
+ case "@statelyai.retrieved":
63
+ exportManager.resolve(msg.requestId, msg.data);
64
+ break;
65
+ case "@statelyai.error":
66
+ exportManager.reject(new Error(msg.message), msg.requestId);
67
+ events.emit("error", {
68
+ code: msg.code,
69
+ message: msg.message
70
+ });
71
+ break;
72
+ }
73
+ });
74
+ return {
75
+ get sessionId() {
76
+ return sessionId;
77
+ },
78
+ inspect(opts) {
79
+ send(toInitMessage(opts));
80
+ },
81
+ update(machine, format) {
82
+ send({
83
+ type: "@statelyai.update",
84
+ machine,
85
+ format
86
+ });
87
+ },
88
+ setMode(mode) {
89
+ send({
90
+ type: "@statelyai.setMode",
91
+ mode
92
+ });
93
+ },
94
+ export(format, callOptions) {
95
+ return exportManager.start(format, callOptions, "Inspector is destroyed", () => destroyed);
96
+ },
97
+ on(event, handler) {
98
+ events.on(event, handler);
99
+ },
100
+ off(event, handler) {
101
+ events.off(event, handler);
102
+ },
103
+ sendSnapshot(snapshot, event) {
104
+ send({
105
+ type: "@statelyai.inspectSnapshot",
106
+ snapshot,
107
+ event: event ?? null
108
+ });
109
+ },
110
+ destroy() {
111
+ if (destroyed) return;
112
+ destroyed = true;
113
+ transport.destroy();
114
+ exportManager.clear("Inspector destroyed");
115
+ events.clear();
116
+ pendingMessages.length = 0;
117
+ }
118
+ };
119
+ }
120
+
121
+ //#endregion
122
+ export { createStatelyInspector };
@@ -18,15 +18,15 @@ interface ExportFormatMap {
18
18
  result: Record<string, unknown>;
19
19
  };
20
20
  digraph: {
21
- options: Record<string, never>;
21
+ options: object;
22
22
  result: Record<string, unknown>;
23
23
  };
24
24
  mermaid: {
25
- options: Record<string, never>;
25
+ options: object;
26
26
  result: string;
27
27
  };
28
28
  scxml: {
29
- options: Record<string, never>;
29
+ options: object;
30
30
  result: string;
31
31
  };
32
32
  }
@@ -169,46 +169,4 @@ type SessionMessage = RegisterMessage | RegisteredMessage | RequestOpenMessage;
169
169
  /** Any valid protocol message. */
170
170
  type ProtocolMessage = ClientMessage | VizMessage | SessionMessage;
171
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 };
172
+ export { ExportCallOptions as a, InitOptions as c, EmbedMode as i, ProtocolMessage as l, EmbedEventMap as n, ExportFormat as o, EmbedEventName as r, ExportFormatMap as s, EmbedEventHandler as t };
@@ -0,0 +1,54 @@
1
+ //#region src/studio.d.ts
2
+ interface StudioClientOptions {
3
+ baseUrl?: string;
4
+ apiKey?: string;
5
+ fetch?: typeof fetch;
6
+ }
7
+ interface VerifyApiKeyResponse {
8
+ valid: boolean;
9
+ }
10
+ interface ProjectMachine {
11
+ machineId: string;
12
+ name: string;
13
+ }
14
+ interface ProjectData {
15
+ projectId: string;
16
+ machines: ProjectMachine[];
17
+ }
18
+ interface ExtractedMachine {
19
+ id?: string;
20
+ config: Record<string, unknown>;
21
+ setupConfig?: Record<string, unknown>;
22
+ implementations?: Record<string, unknown>;
23
+ _type: 'setup.createMachine' | 'createMachine';
24
+ }
25
+ interface ExtractMachinesResponse {
26
+ machines: ExtractedMachine[];
27
+ error?: string;
28
+ }
29
+ interface GetMachineOptions {
30
+ version?: string;
31
+ }
32
+ declare class StudioApiError extends Error {
33
+ readonly status: number;
34
+ constructor(message: string, status: number);
35
+ }
36
+ interface StudioClient {
37
+ auth: {
38
+ verify(apiKey?: string): Promise<VerifyApiKeyResponse>;
39
+ };
40
+ projects: {
41
+ get(projectId: string): Promise<ProjectData>;
42
+ };
43
+ machines: {
44
+ get<TMachine = Record<string, unknown>>(machineId: string, options?: GetMachineOptions): Promise<TMachine>;
45
+ };
46
+ code: {
47
+ extractMachines(code: string, options?: {
48
+ apiKey?: string | null;
49
+ }): Promise<ExtractMachinesResponse>;
50
+ };
51
+ }
52
+ declare function createStatelyClient(options?: StudioClientOptions): StudioClient;
53
+ //#endregion
54
+ export { ExtractMachinesResponse, ExtractedMachine, GetMachineOptions, ProjectData, ProjectMachine, StudioApiError, StudioClient, StudioClientOptions, VerifyApiKeyResponse, createStatelyClient };
@@ -0,0 +1,62 @@
1
+ //#region src/studio.ts
2
+ var StudioApiError = class extends Error {
3
+ status;
4
+ constructor(message, status) {
5
+ super(message);
6
+ this.name = "StudioApiError";
7
+ this.status = status;
8
+ }
9
+ };
10
+ function getFetch(fetchImpl) {
11
+ const resolvedFetch = fetchImpl ?? globalThis.fetch;
12
+ if (!resolvedFetch) throw new Error("No fetch implementation available. Pass one via createStatelyClient({ fetch }).");
13
+ return resolvedFetch;
14
+ }
15
+ function joinApiUrl(baseUrl, path) {
16
+ return `${baseUrl.replace(/\/+$/, "")}/registry/api/v1${path}`;
17
+ }
18
+ async function parseJson(response) {
19
+ if (!response.headers.get("content-type")?.includes("application/json")) return null;
20
+ return response.json().catch(() => null);
21
+ }
22
+ function createStatelyClient(options = {}) {
23
+ const baseUrl = options.baseUrl ?? "https://stately.ai";
24
+ const fetchImpl = getFetch(options.fetch);
25
+ async function request(path, init = {}, apiKeyOverride) {
26
+ const headers = new Headers(init.headers);
27
+ const apiKey = apiKeyOverride ?? options.apiKey;
28
+ if (apiKey) headers.set("Authorization", `Bearer ${apiKey}`);
29
+ const response = await fetchImpl(joinApiUrl(baseUrl, path), {
30
+ ...init,
31
+ headers
32
+ });
33
+ const data = await parseJson(response);
34
+ if (!response.ok) throw new StudioApiError(typeof data === "object" && data !== null && "error" in data && typeof data.error === "string" ? data.error : `HTTP ${response.status}`, response.status);
35
+ return data;
36
+ }
37
+ return {
38
+ auth: { verify(apiKey) {
39
+ return request("/verify", { method: "GET" }, apiKey);
40
+ } },
41
+ projects: { get(projectId) {
42
+ return request(`/projects/${encodeURIComponent(projectId)}`, { method: "GET" });
43
+ } },
44
+ machines: { get(machineId, getOptions = {}) {
45
+ const search = new URLSearchParams();
46
+ if (getOptions.version) search.set("version", getOptions.version);
47
+ const suffix = search.size > 0 ? `?${search.toString()}` : "";
48
+ return request(`/machines/${encodeURIComponent(machineId)}${suffix}`, { method: "GET" });
49
+ } },
50
+ code: { extractMachines(code, extractOptions = {}) {
51
+ const apiKey = extractOptions.apiKey ?? options.apiKey ?? "anonymous";
52
+ return request("/code", {
53
+ method: "POST",
54
+ headers: { "Content-Type": "application/json" },
55
+ body: JSON.stringify({ code })
56
+ }, apiKey);
57
+ } }
58
+ };
59
+ }
60
+
61
+ //#endregion
62
+ export { StudioApiError, createStatelyClient };