@statelyai/sdk 0.10.2 → 0.12.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 CHANGED
@@ -28,11 +28,35 @@ embed.init({
28
28
  });
29
29
  ```
30
30
 
31
+ Restrict an embed by passing a resolved access policy:
32
+
33
+ ```ts
34
+ embed.init({
35
+ machine: myMachineConfig,
36
+ mode: 'viewing',
37
+ readOnly: true,
38
+ capabilities: {
39
+ edit: false,
40
+ export: false,
41
+ ai: false,
42
+ simulate: false,
43
+ navigateHierarchy: false,
44
+ maxDepth: 1,
45
+ panels: ['structure', 'details', 'validations'],
46
+ },
47
+ });
48
+
49
+ embed.on('capabilityDenied', (event) => {
50
+ console.warn(event.message);
51
+ });
52
+ ```
53
+
31
54
  Key capabilities:
32
55
 
33
56
  - **Mount or attach** to any container element or existing iframe
34
57
  - **Two-way sync** - push machine configs in, get changes and saves back via event callbacks
35
58
  - **Export** to multiple formats: XState v5, XState JSON, Mermaid, Redux, Zustand, ASL, SCXML, and more
59
+ - **Access policies** for read-only, no-export, no-AI, shallow-viewer embeds
36
60
  - **Comments** via Liveblocks integration (optional)
37
61
  - **Asset uploads** with built-in S3 and Supabase adapters, or bring your own upload handler
38
62
  - **Runtime settings** - toggle color mode, grid, snap lines, autolayout, and view mode on the fly
@@ -69,7 +93,10 @@ Programmatic access to Stately Studio for managing projects and machines, extrac
69
93
  import { createStatelyClient } from '@statelyai/sdk';
70
94
 
71
95
  const studio = createStatelyClient({
72
- apiKey: process.env.STATELY_API_KEY,
96
+ credential: {
97
+ type: 'oauth',
98
+ accessToken: process.env.STATELY_ACCESS_TOKEN!,
99
+ },
73
100
  });
74
101
 
75
102
  const projects = await studio.projects.list();
@@ -77,6 +104,10 @@ const machine = await studio.machines.get('machine-id');
77
104
  const extracted = await studio.code.extractMachines(sourceCode);
78
105
  ```
79
106
 
107
+ Legacy `apiKey` is still accepted as an alias for
108
+ `credential: { type: 'api_key', token }`. Use `authMode: 'none'` only for
109
+ self-hosted deployments that intentionally accept unauthenticated calls.
110
+
80
111
  ### Inspector
81
112
 
82
113
  Stream live actor-system state to the Stately inspector over WebSockets, with support for automatic XState actor adoption and manual actor registration.
@@ -85,10 +116,11 @@ Stream live actor-system state to the Stately inspector over WebSockets, with su
85
116
  import { createActor } from 'xstate';
86
117
  import { createStatelyInspector } from '@statelyai/sdk';
87
118
 
88
- const inspector = createStatelyInspector({
89
- actor: createActor(machine),
90
- autoOpen: true,
91
- });
119
+ const actor = createActor(machine);
120
+ const inspector = createStatelyInspector({ autoOpen: true });
121
+
122
+ inspector.inspect(actor);
123
+ actor.start();
92
124
  ```
93
125
 
94
126
  ### CLI and sync
@@ -0,0 +1,15 @@
1
+ //#region src/auth.d.ts
2
+ type StatelyCredential = {
3
+ type: 'api_key';
4
+ token: string;
5
+ } | {
6
+ type: 'oauth';
7
+ accessToken: string;
8
+ refreshToken?: string;
9
+ expiresAt?: number;
10
+ };
11
+ type StatelyAuthMode = 'auto' | 'none' | 'bearer';
12
+ declare function getCredentialToken(credential: StatelyCredential | string | null | undefined): string | undefined;
13
+ declare function createAuthorizationHeader(credential: StatelyCredential | string): string;
14
+ //#endregion
15
+ export { getCredentialToken as i, StatelyCredential as n, createAuthorizationHeader as r, StatelyAuthMode as t };
@@ -0,0 +1,2 @@
1
+ import { i as getCredentialToken, n as StatelyCredential, r as createAuthorizationHeader, t as StatelyAuthMode } from "./auth-DO1-eQcU.mjs";
2
+ export { StatelyAuthMode, StatelyCredential, createAuthorizationHeader, getCredentialToken };
package/dist/auth.mjs ADDED
@@ -0,0 +1,11 @@
1
+ //#region src/auth.ts
2
+ function getCredentialToken(credential) {
3
+ if (!credential) return;
4
+ return typeof credential === "string" ? credential : credential.type === "oauth" ? credential.accessToken : credential.token;
5
+ }
6
+ function createAuthorizationHeader(credential) {
7
+ return `Bearer ${getCredentialToken(credential)}`;
8
+ }
9
+
10
+ //#endregion
11
+ export { createAuthorizationHeader, getCredentialToken };
package/dist/embed.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { CommentsConfig, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap, InitOptions, MachineInitOptions, MachineSourceLocations, ProjectEmbedMachine, UploadResult } from "./protocol.mjs";
1
+ import { CapabilityDeniedEvent, CommentsConfig, EditorCapabilities, 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
@@ -56,6 +56,7 @@ interface StatelyEmbedOptions extends Partial<MachineInitOptions> {
56
56
  code: string;
57
57
  message: string;
58
58
  }) => void;
59
+ onCapabilityDenied?: (event: CapabilityDeniedEvent) => void;
59
60
  }
60
61
  interface StatelyEmbed {
61
62
  /** Attach to an existing iframe element. Sets src and begins handshake. */
@@ -89,4 +90,4 @@ interface StatelyEmbed {
89
90
  }
90
91
  declare function createStatelyEmbed(options: StatelyEmbedOptions): StatelyEmbed;
91
92
  //#endregion
92
- export { AssetConfig, type CommentsConfig, type EmbedEventHandler, type EmbedEventMap, type EmbedEventName, type EmbedMode, type ExportCallOptions, type ExportFormat, type ExportFormatMap, type InitOptions, type MachineInitOptions, type MachineSourceLocations, type ProjectEmbedMachine, StatelyEmbed, StatelyEmbedOptions, type UploadResult, createStatelyEmbed };
93
+ export { AssetConfig, type CapabilityDeniedEvent, type CommentsConfig, type EditorCapabilities, type EmbedEventHandler, type EmbedEventMap, type EmbedEventName, type EmbedMode, type ExportCallOptions, type ExportFormat, type ExportFormatMap, type InitOptions, type MachineInitOptions, type MachineSourceLocations, type ProjectEmbedMachine, StatelyEmbed, StatelyEmbedOptions, type UploadResult, createStatelyEmbed };
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-CVZGF0w9.mjs";
1
+ import { a as toInitMessage, i as createPendingExportManager, r as createEventRegistry, t as createPostMessageTransport } from "./transport-D0nlFaLn.mjs";
2
2
 
3
3
  //#region src/embed.ts
4
4
  function buildEmbedUrl(options) {
@@ -15,6 +15,7 @@ function extractInitOptions(options) {
15
15
  theme: options.theme,
16
16
  readOnly: options.readOnly,
17
17
  depth: options.depth,
18
+ capabilities: options.capabilities,
18
19
  panels: options.panels,
19
20
  commentsByMachineId: options.commentsByMachineId,
20
21
  unsavedIndicator: options.unsavedIndicator
@@ -26,6 +27,7 @@ function extractInitOptions(options) {
26
27
  theme: options.theme,
27
28
  readOnly: options.readOnly,
28
29
  depth: options.depth,
30
+ capabilities: options.capabilities,
29
31
  panels: options.panels,
30
32
  comments: options.comments,
31
33
  sourceLocations: options.sourceLocations,
@@ -134,6 +136,12 @@ function createStatelyEmbed(options) {
134
136
  events.emit("error", err);
135
137
  break;
136
138
  }
139
+ case "@statelyai.capabilityDenied": {
140
+ const { type: _type, ...event } = data;
141
+ options.onCapabilityDenied?.(event);
142
+ events.emit("capabilityDenied", event);
143
+ break;
144
+ }
137
145
  case "@statelyai.uploadRequest": {
138
146
  const req = data;
139
147
  if (!uploadAsset) {
@@ -181,9 +181,10 @@ interface CodeGenInvoke {
181
181
  interface CodeGenNodeData {
182
182
  nodeId?: string | null;
183
183
  key: string;
184
- type?: 'normal' | 'parallel' | 'final' | 'history' | null;
184
+ type?: 'normal' | 'parallel' | 'final' | 'history' | 'choice' | null;
185
185
  initialId?: string | null;
186
186
  history?: 'shallow' | 'deep' | boolean;
187
+ output?: Record<string, unknown> | CodeExpression;
187
188
  entry?: CodeGenAction[];
188
189
  exit?: CodeGenAction[];
189
190
  invokes?: CodeGenInvoke[];
@@ -200,6 +201,7 @@ interface CodeGenEdgeData {
200
201
  eventType: string;
201
202
  transitionType?: 'normal' | 'targetless' | 'reenter';
202
203
  guard?: CodeGenGuard | null;
204
+ context?: Record<string, unknown> | CodeExpression;
203
205
  actions?: CodeGenAction[];
204
206
  description?: string | null;
205
207
  color?: string;
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-GeuH-mFK.mjs";
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-CszT5J6W.mjs";
2
2
  export { StatelyAction, StatelyActorImplementation, StatelyEdgeData, StatelyGraph, StatelyGraphData, StatelyGuard, StatelyImplementation, StatelyInvoke, StatelyNodeData, StatelyTagImplementation, StudioAction, StudioEdge, StudioEventTypeData, StudioMachine, StudioNode, fromStudioMachine, studioMachineConverter, toStudioMachine };
@@ -4668,6 +4668,7 @@ function deepSimplify(config) {
4668
4668
  return config;
4669
4669
  }
4670
4670
  function buildMeta(meta, color) {
4671
+ if (isCodeExpression(meta)) return meta;
4671
4672
  const result = {};
4672
4673
  if (meta) {
4673
4674
  for (const [k, v] of Object.entries(meta)) if (v !== void 0 && v !== null) result[k] = v;
@@ -4675,6 +4676,9 @@ function buildMeta(meta, color) {
4675
4676
  if (color) result["@statelyai.color"] = color;
4676
4677
  return Object.keys(result).length > 0 ? result : void 0;
4677
4678
  }
4679
+ function isCodeExpression(value) {
4680
+ return Boolean(value && typeof value === "object" && !Array.isArray(value) && value["@type"] === "code" && typeof value.expr === "string");
4681
+ }
4678
4682
  /** Format event param — supports { type: string } (new) and plain string (legacy) */
4679
4683
  function formatEventParam(event) {
4680
4684
  if (event && typeof event === "object" && "type" in event) return formatInlineObject(event);
@@ -4693,6 +4697,10 @@ function formatObjectKey(key) {
4693
4697
  const eventParamSchema = union([string(), object({ type: string() }).catchall(unknown())]);
4694
4698
  const delayParamSchema = union([number(), string()]);
4695
4699
  const builtInActionParamSchemas = {
4700
+ "xstate.enqueue": object({
4701
+ code: string().optional(),
4702
+ lang: string().optional()
4703
+ }),
4696
4704
  "xstate.raise": object({
4697
4705
  event: eventParamSchema.optional(),
4698
4706
  id: string().optional(),
@@ -4716,6 +4724,16 @@ const builtInActionParamSchemas = {
4716
4724
  "xstate.assign": object({ assignment: record(string(), unknown()).optional() }).catchall(unknown())
4717
4725
  };
4718
4726
  const XSTATE_BUILT_IN_ACTIONS = {
4727
+ "xstate.enqueue": {
4728
+ package: "xstate",
4729
+ version: "^6",
4730
+ import: "enqueue",
4731
+ importKind: "named",
4732
+ paramsSchema: builtInActionParamSchemas["xstate.enqueue"],
4733
+ emit(params) {
4734
+ return typeof params?.code === "string" ? stripExportDefault$1(params.code) : "";
4735
+ }
4736
+ },
4719
4737
  "xstate.raise": {
4720
4738
  package: "xstate",
4721
4739
  version: "^5",
@@ -4858,6 +4876,7 @@ function serializeGuard(guard, asTypeRef) {
4858
4876
  */
4859
4877
  function serializeActionItem(action) {
4860
4878
  const { type, params } = action;
4879
+ if (type === "xstate.enqueue" && typeof params?.code === "string") return inlineCodeExpression(params.code);
4861
4880
  const exprCode = type === "xstate.expr" && typeof params?.code === "string" ? params.code : void 0;
4862
4881
  if (isBuiltInActionType(type)) {
4863
4882
  const builtInAction = XSTATE_BUILT_IN_ACTIONS[type];
@@ -4890,7 +4909,8 @@ function graphToMachineConfig(graph, options = {}) {
4890
4909
  const nodeType = [
4891
4910
  "final",
4892
4911
  "history",
4893
- "parallel"
4912
+ "parallel",
4913
+ "choice"
4894
4914
  ].includes(node.data.type) ? node.data.type : void 0;
4895
4915
  const tags = node.data.tags;
4896
4916
  Object.assign(nodeConfig, {
@@ -4905,6 +4925,7 @@ function graphToMachineConfig(graph, options = {}) {
4905
4925
  ...inv.input ? { input: inv.input } : void 0,
4906
4926
  ...inv.output ? { output: inv.output } : void 0
4907
4927
  })) } : void 0,
4928
+ ...node.data.output !== void 0 ? { output: node.data.output } : void 0,
4908
4929
  ...tags?.length ? { tags: tags.map(tagToString) } : void 0,
4909
4930
  ...showDescriptions && node.data.description ? { description: node.data.description } : void 0,
4910
4931
  ...showMeta && node.data.meta && Object.keys(node.data.meta).length > 0 ? { meta: node.data.meta } : void 0,
@@ -4916,6 +4937,7 @@ function graphToMachineConfig(graph, options = {}) {
4916
4937
  const on = {};
4917
4938
  const after = {};
4918
4939
  const alwaysArr = [];
4940
+ const choiceArr = [];
4919
4941
  const onDone = {};
4920
4942
  const invokeMap = {};
4921
4943
  for (const edge of edges) {
@@ -4927,6 +4949,7 @@ function graphToMachineConfig(graph, options = {}) {
4927
4949
  target: edge.data.transitionType === "targetless" ? void 0 : `${resolvedTarget}`,
4928
4950
  ...edge.data.transitionType === "reenter" ? { reenter: true } : void 0,
4929
4951
  guard: edge.data.guard ? serializeGuard(edge.data.guard, inlineGuardsAsTypeRef) : void 0,
4952
+ ...edge.data.context !== void 0 ? { context: edge.data.context } : void 0,
4930
4953
  actions: edge.data.actions?.length ? edge.data.actions.map(serializeActionItem) : void 0,
4931
4954
  description: edge.data.description ?? void 0,
4932
4955
  ...transitionMeta ? { meta: transitionMeta } : void 0
@@ -4949,6 +4972,7 @@ function graphToMachineConfig(graph, options = {}) {
4949
4972
  if (!onDone[type]) onDone[type] = [];
4950
4973
  onDone[type].push(transitionObject);
4951
4974
  } else pushOn(`xstate.${ref.kind === "actionDone" ? "done" : "error"}.actor.${resolveSpawnActorId(node, ref.blockId)}`);
4975
+ else if (type === "" && node.data.type === "choice") choiceArr.push(transitionObject);
4952
4976
  else if (type === "") alwaysArr.push(transitionObject);
4953
4977
  else if (type.startsWith("xstate.after.")) {
4954
4978
  const delayKey = type.slice(13).split(".")[0];
@@ -4968,6 +4992,7 @@ function graphToMachineConfig(graph, options = {}) {
4968
4992
  if (Object.keys(on).length > 0) nodeConfig.on = singleOrArrayRecord(on);
4969
4993
  if (Object.keys(after).length > 0) nodeConfig.after = singleOrArrayRecord(after);
4970
4994
  if (alwaysArr.length > 0) nodeConfig.always = singleOrArray(alwaysArr);
4995
+ if (choiceArr.length > 0) nodeConfig.choice = singleOrArray(choiceArr);
4971
4996
  if (Object.keys(onDone).length > 0) nodeConfig.onDone = singleOrArray(Object.values(onDone).flat());
4972
4997
  if (Object.keys(invokeMap).length > 0 && Array.isArray(nodeConfig.invoke)) nodeConfig.invoke = nodeConfig.invoke.map((inv, index) => {
4973
4998
  const mapped = invokeMap[node.data.invokes?.[index]?.id ?? inv.id];
package/dist/index.d.mts CHANGED
@@ -1,10 +1,12 @@
1
1
  import { StatelyApiClientOptions, StatelyApiError, StatelyApiUrlOptions, createStatelyApiClient, createStatelyApiUrl } from "./api.mjs";
2
- import { CommentsConfig, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap, InitOptions, ProjectEmbedMachine, UploadResult } from "./protocol.mjs";
2
+ import { CapabilityDeniedCapability, CapabilityDeniedEvent, CommentsConfig, EditorCapabilities, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap, InitOptions, ProjectEmbedMachine, UploadResult } from "./protocol.mjs";
3
3
  import { AssetUploadAdapter, AssetUploadContext, AssetUploadRequest, CreateS3AssetUploadAdapterOptions, CreateSupabaseAssetUploadAdapterOptions, S3UploadTarget, SupabaseStorageClient, createS3AssetUploadAdapter, createSupabaseAssetUploadAdapter } from "./assetStorage.mjs";
4
+ import { i as getCredentialToken, n as StatelyCredential, r as createAuthorizationHeader, t as StatelyAuthMode } from "./auth-DO1-eQcU.mjs";
4
5
  import { AssetConfig, StatelyEmbed, StatelyEmbedOptions, createStatelyEmbed } from "./embed.mjs";
5
- import { C as EventTypeData, E as JSONSchema7, S as DigraphNodeConfig, T as CodeGenGraph, _ as studioMachineConverter, a as StatelyGraphData, b as DigraphConfig, c as StatelyInvoke, d as StudioAction, f as StudioEdge, g as fromStudioMachine, h as StudioNode, i as StatelyGraph, l as StatelyNodeData, m as StudioMachine, o as StatelyGuard, r as StatelyEdgeData, t as StatelyAction, v as toStudioMachine, w as StateNodeJSONData, x as DigraphEdgeConfig, y as DigraphAction } from "./graph-GeuH-mFK.mjs";
6
- import { a as ManualActorOptions, c as createPostMessageTransport, i as InspectorEvents, l as createWebSocketTransport, n as CreateInspectorOptions, o as createStatelyInspector, r as Inspector, s as Transport, t as AdoptedActor } from "./inspect-BLlM3qKf.mjs";
6
+ import { C as EventTypeData, E as JSONSchema7, S as DigraphNodeConfig, T as CodeGenGraph, _ as studioMachineConverter, a as StatelyGraphData, b as DigraphConfig, c as StatelyInvoke, d as StudioAction, f as StudioEdge, g as fromStudioMachine, h as StudioNode, i as StatelyGraph, l as StatelyNodeData, m as StudioMachine, o as StatelyGuard, r as StatelyEdgeData, t as StatelyAction, v as toStudioMachine, w as StateNodeJSONData, x as DigraphEdgeConfig, y as DigraphAction } from "./graph-CszT5J6W.mjs";
7
+ import { a as ManualActorOptions, c as createPostMessageTransport, i as InspectorEvents, l as createWebSocketTransport, n as CreateInspectorOptions, o as createStatelyInspector, r as Inspector, s as Transport, t as AdoptedActor } from "./inspect-BibyPhFj.mjs";
7
8
  import { ConnectedRepo, CreateMachineFromDefinitionInput, CreateMachineFromTemplateInput, CreateMachineInput, CreateMachineTemplate, CreateProjectInput, EnsureProjectInput, ExtractMachinesResponse, ExtractedMachine, GetMachineOptions, ProjectData, ProjectMachine, ProjectVisibility, RepoType, StudioApiError, StudioClient, StudioClientOptions, StudioMachineRecord, UpdateMachineInput, VerifyApiKeyResponse, XStateVersion, createStatelyClient } from "./studio.mjs";
9
+ import { OAuthAuthorizationServerMetadata, OAuthProtectedResourceMetadata, OAuthTokenResponse, PkcePair, buildAuthorizeUrl, createPkcePair, discoverAuthorizationServer, discoverProtectedResource, exchangeCodeForToken, refreshToken } from "./oauth.mjs";
8
10
  import { PlanSyncOptions, PullSyncResult, PushLocalMachineLinksResult, PushSyncOptions, PushSyncProjectOptions, PushSyncResult, ResolvedSyncInput, SyncInputFormat, SyncPlan, SyncPlanSummary } from "./sync.mjs";
9
11
  import { ActionLocation, GraphPatch } from "./patchTypes.mjs";
10
12
  import { UnknownMachineConfig } from "xstate";
@@ -83,4 +85,4 @@ declare function contextSchemaToTSType(context: Record<string, JSONSchema7> | nu
83
85
  */
84
86
  declare function eventsSchemaToTSType(events: Record<string, JSONSchema7> | null | undefined): string | null;
85
87
  //#endregion
86
- export { type ActionLocation, type AdoptedActor, type AssetConfig, type AssetUploadAdapter, type AssetUploadContext, type AssetUploadRequest, type CodeGenGraph, type CommentsConfig, type ConnectedRepo, type CreateInspectorOptions, type CreateMachineFromDefinitionInput, type CreateMachineFromTemplateInput, type CreateMachineInput, type CreateMachineTemplate, type CreateProjectInput, type CreateS3AssetUploadAdapterOptions, type CreateSupabaseAssetUploadAdapterOptions, type DigraphAction, type DigraphConfig, type DigraphEdgeConfig, type DigraphNodeConfig, type EmbedEventHandler, type EmbedEventMap, type EmbedEventName, type EmbedMode, type EnsureProjectInput, type EventTypeData, type ExportCallOptions, type ExportFormat, type ExportFormatMap, type ExtractMachinesResponse, type ExtractedMachine, type GetMachineOptions, type GraphPatch, type InitOptions, type Inspector, type InspectorEvents, type MachineConfigOptions, type ManualActorOptions, type PlanSyncOptions, type ProjectData, type ProjectEmbedMachine, type ProjectMachine, type ProjectVisibility, type PullSyncResult, type PushLocalMachineLinksResult, type PushSyncOptions, type PushSyncProjectOptions, type PushSyncResult, RawCode, type RepoType, type ResolvedSyncInput, type S3UploadTarget, type StateNodeJSONData, type StatelyAction, type StatelyApiClientOptions, StatelyApiError, type StatelyApiUrlOptions, type StatelyEdgeData, type StatelyEmbed, type StatelyEmbedOptions, type StatelyGraph, type StatelyGraphData, type StatelyGuard, type StatelyInvoke, type StatelyNodeData, type StatelyPragma, type StatelyPragmaAttachment, type StudioAction, StudioApiError, type StudioClient, type StudioClientOptions, type StudioEdge, type StudioMachine, type StudioMachineRecord, type StudioNode, type SupabaseStorageClient, type SyncInputFormat, type SyncPlan, type SyncPlanSummary, type Transport, type UpdateMachineInput, type UploadResult, type UpsertStatelyPragmaOptions, type VerifyApiKeyResponse, type XStateTSOptions, type XStateVersion, contextSchemaToTSType, createPostMessageTransport, createS3AssetUploadAdapter, createStatelyApiClient, createStatelyApiUrl, createStatelyClient, createStatelyEmbed, createStatelyInspector, createSupabaseAssetUploadAdapter, createWebSocketTransport, eventsSchemaToTSType, findStatelyPragmaAttachments, fromStudioMachine, getStatelyPragma, graphToMachineConfig, graphToXStateTS, jsonSchemaToTSType, raw, serializeJS, studioMachineConverter, toStudioMachine, upsertStatelyPragma };
88
+ export { type ActionLocation, type AdoptedActor, type AssetConfig, type AssetUploadAdapter, type AssetUploadContext, type AssetUploadRequest, type CapabilityDeniedCapability, type CapabilityDeniedEvent, type CodeGenGraph, type CommentsConfig, type ConnectedRepo, type CreateInspectorOptions, type CreateMachineFromDefinitionInput, type CreateMachineFromTemplateInput, type CreateMachineInput, type CreateMachineTemplate, type CreateProjectInput, type CreateS3AssetUploadAdapterOptions, type CreateSupabaseAssetUploadAdapterOptions, type DigraphAction, type DigraphConfig, type DigraphEdgeConfig, type DigraphNodeConfig, type EditorCapabilities, type EmbedEventHandler, type EmbedEventMap, type EmbedEventName, type EmbedMode, type EnsureProjectInput, type EventTypeData, type ExportCallOptions, type ExportFormat, type ExportFormatMap, type ExtractMachinesResponse, type ExtractedMachine, type GetMachineOptions, type GraphPatch, type InitOptions, type Inspector, type InspectorEvents, type MachineConfigOptions, type ManualActorOptions, type OAuthAuthorizationServerMetadata, type OAuthProtectedResourceMetadata, type OAuthTokenResponse, type PkcePair, type PlanSyncOptions, type ProjectData, type ProjectEmbedMachine, type ProjectMachine, type ProjectVisibility, type PullSyncResult, type PushLocalMachineLinksResult, type PushSyncOptions, type PushSyncProjectOptions, type PushSyncResult, RawCode, type RepoType, type ResolvedSyncInput, type S3UploadTarget, type StateNodeJSONData, type StatelyAction, type StatelyApiClientOptions, StatelyApiError, type StatelyApiUrlOptions, type StatelyAuthMode, type StatelyCredential, type StatelyEdgeData, type StatelyEmbed, type StatelyEmbedOptions, type StatelyGraph, type StatelyGraphData, type StatelyGuard, type StatelyInvoke, type StatelyNodeData, type StatelyPragma, type StatelyPragmaAttachment, type StudioAction, StudioApiError, type StudioClient, type StudioClientOptions, type StudioEdge, type StudioMachine, type StudioMachineRecord, type StudioNode, type SupabaseStorageClient, type SyncInputFormat, type SyncPlan, type SyncPlanSummary, type Transport, type UpdateMachineInput, type UploadResult, type UpsertStatelyPragmaOptions, type VerifyApiKeyResponse, type XStateTSOptions, type XStateVersion, buildAuthorizeUrl, contextSchemaToTSType, createAuthorizationHeader, createPkcePair, createPostMessageTransport, createS3AssetUploadAdapter, createStatelyApiClient, createStatelyApiUrl, createStatelyClient, createStatelyEmbed, createStatelyInspector, createSupabaseAssetUploadAdapter, createWebSocketTransport, discoverAuthorizationServer, discoverProtectedResource, eventsSchemaToTSType, exchangeCodeForToken, findStatelyPragmaAttachments, fromStudioMachine, getCredentialToken, getStatelyPragma, graphToMachineConfig, graphToXStateTS, jsonSchemaToTSType, raw, refreshToken, serializeJS, studioMachineConverter, toStudioMachine, upsertStatelyPragma };
package/dist/index.mjs CHANGED
@@ -1,10 +1,12 @@
1
- import { n as createWebSocketTransport, t as createPostMessageTransport } from "./transport-CVZGF0w9.mjs";
1
+ import { n as createWebSocketTransport, t as createPostMessageTransport } from "./transport-D0nlFaLn.mjs";
2
2
  import { createStatelyEmbed } from "./embed.mjs";
3
3
  import { createS3AssetUploadAdapter, createSupabaseAssetUploadAdapter } from "./assetStorage.mjs";
4
4
  import { createStatelyInspector } from "./inspect.mjs";
5
+ import { createAuthorizationHeader, getCredentialToken } from "./auth.mjs";
5
6
  import { StudioApiError, createStatelyClient } from "./studio.mjs";
7
+ import { buildAuthorizeUrl, createPkcePair, discoverAuthorizationServer, discoverProtectedResource, exchangeCodeForToken, refreshToken } from "./oauth.mjs";
6
8
  import { StatelyApiError, createStatelyApiClient, createStatelyApiUrl } from "./api.mjs";
7
- import { S as upsertStatelyPragma, a as graphToMachineConfig, b as findStatelyPragmaAttachments, c as serializeJS, i as jsonSchemaToTSType, n as contextSchemaToTSType, o as RawCode, r as eventsSchemaToTSType, s as raw, t as graphToXStateTS, x as getStatelyPragma } from "./graphToXStateTS-DOaLOySy.mjs";
9
+ import { S as upsertStatelyPragma, a as graphToMachineConfig, b as findStatelyPragmaAttachments, c as serializeJS, i as jsonSchemaToTSType, n as contextSchemaToTSType, o as RawCode, r as eventsSchemaToTSType, s as raw, t as graphToXStateTS, x as getStatelyPragma } from "./graphToXStateTS-D12GTMBp.mjs";
8
10
  import { fromStudioMachine, studioMachineConverter, toStudioMachine } from "./graph.mjs";
9
11
 
10
- export { RawCode, StatelyApiError, StudioApiError, contextSchemaToTSType, createPostMessageTransport, createS3AssetUploadAdapter, createStatelyApiClient, createStatelyApiUrl, createStatelyClient, createStatelyEmbed, createStatelyInspector, createSupabaseAssetUploadAdapter, createWebSocketTransport, eventsSchemaToTSType, findStatelyPragmaAttachments, fromStudioMachine, getStatelyPragma, graphToMachineConfig, graphToXStateTS, jsonSchemaToTSType, raw, serializeJS, studioMachineConverter, toStudioMachine, upsertStatelyPragma };
12
+ export { RawCode, StatelyApiError, StudioApiError, buildAuthorizeUrl, contextSchemaToTSType, createAuthorizationHeader, createPkcePair, createPostMessageTransport, createS3AssetUploadAdapter, createStatelyApiClient, createStatelyApiUrl, createStatelyClient, createStatelyEmbed, createStatelyInspector, createSupabaseAssetUploadAdapter, createWebSocketTransport, discoverAuthorizationServer, discoverProtectedResource, eventsSchemaToTSType, exchangeCodeForToken, findStatelyPragmaAttachments, fromStudioMachine, getCredentialToken, getStatelyPragma, graphToMachineConfig, graphToXStateTS, jsonSchemaToTSType, raw, refreshToken, serializeJS, studioMachineConverter, toStudioMachine, upsertStatelyPragma };
@@ -1,4 +1,4 @@
1
- import { EmbedEventMap, ExportCallOptions, ExportFormat, ExportFormatMap, ProtocolMessage } from "./protocol.mjs";
1
+ import { EditorCapabilities, EmbedEventMap, ExportCallOptions, ExportFormat, ExportFormatMap, ProtocolMessage } from "./protocol.mjs";
2
2
 
3
3
  //#region src/transport.d.ts
4
4
  interface Transport {
@@ -120,19 +120,13 @@ interface ManualActorOptions {
120
120
  systemId?: string;
121
121
  }
122
122
  interface CreateInspectorOptions {
123
- /**
124
- * Root xstate actor to adopt. The inspector walks its `system`.
125
- * Omit this for manual-only mode where you call `.actor()` / `.snapshot()`.
126
- */
127
- actor?: any;
128
123
  /** WebSocket URL of the devtools server. Default: `'ws://localhost:4242'`. */
129
124
  url?: string;
130
125
  /** Auto-open browser to visualizer. Default: `true`. */
131
126
  autoOpen?: boolean;
132
127
  /**
133
- * Relay session id. Defaults to the root actor's `sessionId` (auto mode)
134
- * or a random id (manual mode). This is the `?session=<id>` value the viz
135
- * iframe connects with.
128
+ * Relay session id. Defaults to a random id. This is the `?session=<id>`
129
+ * value the viz iframe connects with.
136
130
  */
137
131
  sessionId?: string;
138
132
  /** Display name for this system in the visualizer. */
@@ -148,7 +142,7 @@ interface CreateInspectorOptions {
148
142
  * `actor.logic.config`. Return `null` for non-machine actors.
149
143
  */
150
144
  extractMachineConfig?: (actor: any) => unknown;
151
- /** Selected actor id to focus on first. Defaults to the root actor. */
145
+ /** Selected actor id to focus on first. Defaults to the first inspected root. */
152
146
  selectedActorId?: string;
153
147
  /** Panel layout forwarded into the system init message. */
154
148
  panels?: {
@@ -159,6 +153,7 @@ interface CreateInspectorOptions {
159
153
  theme?: 'light' | 'dark';
160
154
  readOnly?: boolean;
161
155
  depth?: number;
156
+ capabilities?: EditorCapabilities;
162
157
  /**
163
158
  * Advanced: inject a pre-built transport (e.g. a channel from a
164
159
  * multiplexed connection). When provided, `url`/`name` are ignored and the
@@ -171,6 +166,10 @@ interface Inspector {
171
166
  readonly actors: ReadonlyMap<string, AdoptedActor>;
172
167
  /** The relay sessionId this inspector registered under. */
173
168
  readonly sessionId: string;
169
+ /** Adopt an xstate actor system. Existing actors are backfilled immediately. */
170
+ inspect(actor: any): {
171
+ unsubscribe(): void;
172
+ };
174
173
  /** Subscribe to lifecycle / error events. Returns an unsubscribe function. */
175
174
  on<E extends EventName>(event: E, handler: Handler<E>): () => void;
176
175
  off<E extends EventName>(event: E, handler: Handler<E>): void;
@@ -201,6 +200,6 @@ interface Inspector {
201
200
  /** Tear down the WebSocket + xstate subscription. */
202
201
  destroy(): void;
203
202
  }
204
- declare function createStatelyInspector(options: CreateInspectorOptions): Inspector;
203
+ declare function createStatelyInspector(options?: CreateInspectorOptions): Inspector;
205
204
  //#endregion
206
205
  export { ManualActorOptions as a, createPostMessageTransport as c, InspectorEvents as i, createWebSocketTransport as l, CreateInspectorOptions as n, createStatelyInspector as o, Inspector as r, Transport as s, AdoptedActor as t };
@@ -1,3 +1,3 @@
1
- import { EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap } from "./protocol.mjs";
2
- import { a as ManualActorOptions, i as InspectorEvents, n as CreateInspectorOptions, o as createStatelyInspector, r as Inspector, s as Transport, t as AdoptedActor } from "./inspect-BLlM3qKf.mjs";
3
- export { AdoptedActor, CreateInspectorOptions, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap, Inspector, InspectorEvents, ManualActorOptions, Transport, createStatelyInspector };
1
+ import { EditorCapabilities, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap } from "./protocol.mjs";
2
+ import { a as ManualActorOptions, i as InspectorEvents, n as CreateInspectorOptions, o as createStatelyInspector, r as Inspector, s as Transport, t as AdoptedActor } from "./inspect-BibyPhFj.mjs";
3
+ export { AdoptedActor, CreateInspectorOptions, EditorCapabilities, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap, Inspector, InspectorEvents, ManualActorOptions, Transport, createStatelyInspector };
package/dist/inspect.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { i as createPendingExportManager, n as createWebSocketTransport, r as createEventRegistry } from "./transport-CVZGF0w9.mjs";
1
+ import { i as createPendingExportManager, n as createWebSocketTransport, r as createEventRegistry } from "./transport-D0nlFaLn.mjs";
2
2
 
3
3
  //#region src/inspect.ts
4
4
  const defaultSerializeSnapshot = (snapshot) => ({
@@ -10,12 +10,10 @@ let nextManualId = 0;
10
10
  function generateSessionId() {
11
11
  return `manual-${Date.now()}-${nextManualId++}`;
12
12
  }
13
- function createStatelyInspector(options) {
14
- const { url = "ws://localhost:4242", autoOpen = true, actor: rootActor, name, serializeSnapshot = defaultSerializeSnapshot, extractMachineConfig = defaultExtractMachineConfig, selectedActorId, panels, theme, readOnly, depth, transport: injectedTransport } = options;
15
- const root = rootActor ? rootActor : null;
16
- const rootActorId = root?.sessionId ?? generateSessionId();
17
- const sessionId = options.sessionId ?? rootActorId;
18
- const displayName = name ?? (root ? `system:${root.id}` : "system:manual");
13
+ function createStatelyInspector(options = {}) {
14
+ const { url = "ws://localhost:4242", autoOpen = true, name, serializeSnapshot = defaultSerializeSnapshot, extractMachineConfig = defaultExtractMachineConfig, selectedActorId, panels, theme, readOnly, depth, capabilities, transport: injectedTransport } = options;
15
+ const sessionId = options.sessionId ?? generateSessionId();
16
+ const displayName = name ?? "system:manual";
19
17
  let destroyed = false;
20
18
  let initSent = false;
21
19
  const pendingMessages = [];
@@ -92,7 +90,7 @@ function createStatelyInspector(options) {
92
90
  return null;
93
91
  }
94
92
  }
95
- function toEntry(actorRef) {
93
+ function toEntry(actorRef, rootActorId) {
96
94
  return {
97
95
  actorId: actorRef.sessionId,
98
96
  parentActorId: actorRef._parent?.sessionId ?? null,
@@ -116,34 +114,36 @@ function createStatelyInspector(options) {
116
114
  * Walk the actor tree and populate the local `actors` map. Idempotent —
117
115
  * existing entries stay in place but have their snapshot refreshed.
118
116
  */
119
- function backfillActorTree(actorRef) {
117
+ function backfillActorTree(actorRef, rootActorId) {
120
118
  const existing = actors.get(actorRef.sessionId);
121
- const entry = existing ?? toEntry(actorRef);
119
+ const entry = existing ?? toEntry(actorRef, rootActorId);
122
120
  if (existing) existing.snapshot = snapshotValue(actorRef);
123
121
  else actors.set(entry.actorId, entry);
124
122
  emitRegisterOnce(entry);
125
123
  const children = actorRef.getSnapshot()?.children ?? {};
126
- for (const child of Object.values(children)) if (child) backfillActorTree(child);
124
+ for (const child of Object.values(children)) if (child) backfillActorTree(child, rootActorId);
127
125
  }
126
+ const inspectedRoots = /* @__PURE__ */ new Map();
128
127
  function sendInit() {
129
- if (root) backfillActorTree(root);
128
+ for (const [rootActorId, { actor }] of inspectedRoots) backfillActorTree(actor, rootActorId);
130
129
  send({
131
130
  type: "@statelyai.system.init",
132
131
  mode: "inspecting",
133
132
  actors: Array.from(actors.values()).map(toSystemEntry),
134
- selectedActorId: selectedActorId ?? rootActorId,
133
+ selectedActorId: selectedActorId ?? inspectedRoots.keys().next().value ?? sessionId,
135
134
  ...theme && { theme },
136
135
  ...readOnly !== void 0 && { readOnly },
137
136
  ...depth !== void 0 && { depth },
137
+ ...capabilities !== void 0 && { capabilities },
138
138
  ...panels?.leftPanels && { leftPanels: panels.leftPanels },
139
139
  ...panels?.rightPanels && { rightPanels: panels.rightPanels },
140
140
  ...panels?.activePanels && { activePanels: panels.activePanels }
141
141
  });
142
142
  initSent = true;
143
143
  }
144
- function handleActor(actorRef) {
144
+ function handleActor(actorRef, rootActorId) {
145
145
  if (actors.has(actorRef.sessionId)) return;
146
- const entry = toEntry(actorRef);
146
+ const entry = toEntry(actorRef, rootActorId);
147
147
  actors.set(entry.actorId, entry);
148
148
  if (!initSent) return;
149
149
  send({
@@ -156,8 +156,8 @@ function createStatelyInspector(options) {
156
156
  });
157
157
  emitRegisterOnce(entry);
158
158
  }
159
- function handleSnapshot(actorRef, snapshot, triggeringEvent) {
160
- if (!actors.has(actorRef.sessionId)) handleActor(actorRef);
159
+ function handleSnapshot(actorRef, snapshot, triggeringEvent, rootActorId) {
160
+ if (!actors.has(actorRef.sessionId)) handleActor(actorRef, rootActorId);
161
161
  const entry = actors.get(actorRef.sessionId);
162
162
  if (!entry) return;
163
163
  const serialized = serializeSnapshot(snapshot);
@@ -183,28 +183,43 @@ function createStatelyInspector(options) {
183
183
  emitLocal("stopped", { actorId: entry.actorId });
184
184
  }
185
185
  }
186
- if (root) backfillActorTree(root);
187
- const subscription = root ? root.system.inspect((inspectionEvent) => {
188
- if (destroyed) return;
189
- switch (inspectionEvent.type) {
190
- case "@xstate.actor":
191
- handleActor(inspectionEvent.actorRef);
192
- break;
193
- case "@xstate.event":
194
- if (inspectionEvent.sourceRef) pendingEventSource.set(inspectionEvent.actorRef.sessionId, inspectionEvent.sourceRef.sessionId);
195
- break;
196
- case "@xstate.snapshot":
197
- handleSnapshot(inspectionEvent.actorRef, inspectionEvent.snapshot, inspectionEvent.event);
198
- break;
199
- default: break;
200
- }
201
- }) : null;
186
+ function inspectActor(actor) {
187
+ const root = actor;
188
+ const rootActorId = root.sessionId;
189
+ const existing = inspectedRoots.get(rootActorId);
190
+ if (existing) return existing.subscription;
191
+ const subscription = root.system.inspect((inspectionEvent) => {
192
+ if (destroyed) return;
193
+ switch (inspectionEvent.type) {
194
+ case "@xstate.actor":
195
+ handleActor(inspectionEvent.actorRef, rootActorId);
196
+ break;
197
+ case "@xstate.event":
198
+ if (inspectionEvent.sourceRef) pendingEventSource.set(inspectionEvent.actorRef.sessionId, inspectionEvent.sourceRef.sessionId);
199
+ break;
200
+ case "@xstate.snapshot":
201
+ handleSnapshot(inspectionEvent.actorRef, inspectionEvent.snapshot, inspectionEvent.event, rootActorId);
202
+ break;
203
+ default: break;
204
+ }
205
+ });
206
+ inspectedRoots.set(rootActorId, {
207
+ actor: root,
208
+ subscription
209
+ });
210
+ backfillActorTree(root, rootActorId);
211
+ if (initSent) sendInit();
212
+ return { unsubscribe() {
213
+ subscription.unsubscribe();
214
+ inspectedRoots.delete(rootActorId);
215
+ } };
216
+ }
202
217
  function manualRegister(id, opts) {
203
218
  if (actors.has(id)) return;
204
219
  const entry = {
205
220
  actorId: id,
206
221
  parentActorId: opts?.parent ?? null,
207
- rootId: rootActorId,
222
+ rootId: sessionId,
208
223
  id,
209
224
  systemId: opts?.systemId,
210
225
  snapshot: opts?.snapshot ?? null,
@@ -252,6 +267,7 @@ function createStatelyInspector(options) {
252
267
  get sessionId() {
253
268
  return sessionId;
254
269
  },
270
+ inspect: inspectActor,
255
271
  on(event, handler) {
256
272
  if (!localListeners[event]) localListeners[event] = /* @__PURE__ */ new Set();
257
273
  localListeners[event].add(handler);
@@ -273,12 +289,13 @@ function createStatelyInspector(options) {
273
289
  if (destroyed) return;
274
290
  destroyed = true;
275
291
  try {
276
- subscription?.unsubscribe();
292
+ for (const { subscription } of inspectedRoots.values()) subscription.unsubscribe();
277
293
  } catch {}
278
294
  if (ownsTransport) transport.destroy();
279
295
  exportManager.clear("Inspector destroyed");
280
296
  events.clear();
281
297
  actors.clear();
298
+ inspectedRoots.clear();
282
299
  pendingMessages.length = 0;
283
300
  for (const set of Object.values(localListeners)) set?.clear();
284
301
  }
@@ -0,0 +1,60 @@
1
+ //#region src/oauth.d.ts
2
+ interface OAuthProtectedResourceMetadata {
3
+ resource: string;
4
+ authorization_servers?: string[];
5
+ bearer_methods_supported?: string[];
6
+ scopes_supported?: string[];
7
+ [key: string]: unknown;
8
+ }
9
+ interface OAuthAuthorizationServerMetadata {
10
+ issuer: string;
11
+ authorization_endpoint?: string;
12
+ token_endpoint?: string;
13
+ code_challenge_methods_supported?: string[];
14
+ scopes_supported?: string[];
15
+ [key: string]: unknown;
16
+ }
17
+ interface PkcePair {
18
+ codeVerifier: string;
19
+ codeChallenge: string;
20
+ }
21
+ interface OAuthTokenResponse {
22
+ access_token: string;
23
+ refresh_token?: string;
24
+ expires_in?: number;
25
+ expires_at?: number;
26
+ token_type?: string;
27
+ scope?: string;
28
+ [key: string]: unknown;
29
+ }
30
+ declare function discoverProtectedResource(resourceUrl: string | URL, options?: {
31
+ fetch?: typeof fetch;
32
+ }): Promise<OAuthProtectedResourceMetadata>;
33
+ declare function discoverAuthorizationServer(issuer: string | URL, options?: {
34
+ fetch?: typeof fetch;
35
+ }): Promise<OAuthAuthorizationServerMetadata>;
36
+ declare function createPkcePair(): Promise<PkcePair>;
37
+ declare function buildAuthorizeUrl(options: {
38
+ authorizationEndpoint: string | URL;
39
+ clientId: string;
40
+ redirectUri: string;
41
+ codeChallenge: string;
42
+ state: string;
43
+ scopes?: string[];
44
+ }): string;
45
+ declare function exchangeCodeForToken(options: {
46
+ tokenEndpoint: string | URL;
47
+ code: string;
48
+ codeVerifier: string;
49
+ redirectUri: string;
50
+ clientId: string;
51
+ fetch?: typeof fetch;
52
+ }): Promise<OAuthTokenResponse>;
53
+ declare function refreshToken(options: {
54
+ tokenEndpoint: string | URL;
55
+ refreshToken: string;
56
+ clientId: string;
57
+ fetch?: typeof fetch;
58
+ }): Promise<OAuthTokenResponse>;
59
+ //#endregion
60
+ export { OAuthAuthorizationServerMetadata, OAuthProtectedResourceMetadata, OAuthTokenResponse, PkcePair, buildAuthorizeUrl, createPkcePair, discoverAuthorizationServer, discoverProtectedResource, exchangeCodeForToken, refreshToken };