@statelyai/sdk 0.6.1 → 0.7.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 +16 -15
- package/dist/assetStorage.d.mts +1 -1
- package/dist/cli.d.mts +33 -8
- package/dist/cli.mjs +327 -23
- package/dist/embed.d.mts +1 -1
- package/dist/embed.mjs +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +1 -1
- package/dist/{inspect-BMIJcsFh.d.mts → inspect-Bg9FTvb3.d.mts} +1 -1
- package/dist/inspect.d.mts +2 -2
- package/dist/inspect.mjs +1 -1
- package/dist/{protocol-CDoCcaIP.d.mts → protocol-DN4mH4jR.d.mts} +1 -2
- package/dist/studio.d.mts +7 -1
- package/dist/studio.mjs +7 -0
- package/dist/sync.d.mts +19 -1
- package/dist/sync.mjs +99 -7
- package/dist/{transport-C0eTgNNu.mjs → transport-C8UTS3Fa.mjs} +1 -1
- package/package.json +4 -2
- package/schemas/statelyai.schema.json +1 -1
- package/schemas/xstate-json.schema.json +214 -0
package/README.md
CHANGED
|
@@ -206,12 +206,15 @@ Available client methods:
|
|
|
206
206
|
| `studio.projects.get(projectId)` | Fetch a project and its machines |
|
|
207
207
|
| `studio.machines.create({ projectVersionId, ... })` | Create a machine through the published REST API |
|
|
208
208
|
| `studio.machines.createMany({ projectVersionId, ... })` | Compatibility wrapper around `create()` that returns a one-item array |
|
|
209
|
+
| `studio.machines.update({ id, ... })` | Update a machine through the published REST API |
|
|
209
210
|
| `studio.machines.get(machineId, { version? })` | Fetch a machine, optionally pinned to a version |
|
|
210
211
|
| `studio.code.extractMachines(code, { apiKey? })` | Extract machine configs from source text |
|
|
211
212
|
|
|
212
213
|
## Sync Helpers
|
|
213
214
|
|
|
214
|
-
`pushSync()` complements `planSync()` and `pullSync()` for local-to-Studio flows. It resolves a local source file, ensures there is a target project,
|
|
215
|
+
`pushSync()` complements `planSync()` and `pullSync()` for local-to-Studio flows. It resolves a local source file, ensures there is a target project, updates the linked remote machine when `// @statelyai id=...` is present, otherwise creates one, and writes the pragma back into XState source files when needed.
|
|
216
|
+
|
|
217
|
+
For project-scoped discovery flows, `statelyai.json` defines which local files should be scanned. The CLI `statelyai push` command uses that config to find local XState sources, creates remote Studio machines for unlabeled ones, updates already-linked ones, and writes returned `// @statelyai id=...` pragmas back into source.
|
|
215
218
|
|
|
216
219
|
```ts
|
|
217
220
|
import { pushSync } from '@statelyai/sdk/sync';
|
|
@@ -232,7 +235,7 @@ const result = await pushSync({
|
|
|
232
235
|
});
|
|
233
236
|
```
|
|
234
237
|
|
|
235
|
-
Projects can also check in a `statelyai.json` file to describe which local sources belong to a Studio project. The published schema lives at `@statelyai/sdk/statelyai.schema.json` and the canonical schema id is `https://stately.ai/schemas/statelyai.json`.
|
|
238
|
+
Projects can also check in a `statelyai.json` file to describe which local sources belong to a Studio project. The published schema lives at `@statelyai/sdk/statelyai.schema.json` and the canonical schema id is `https://stately.ai/schemas/statelyai.json`. The strict XState JSON export schema is published at `@statelyai/sdk/xstate-json.schema.json`.
|
|
236
239
|
|
|
237
240
|
```json
|
|
238
241
|
{
|
|
@@ -241,17 +244,7 @@ Projects can also check in a `statelyai.json` file to describe which local sourc
|
|
|
241
244
|
"projectId": "project_123",
|
|
242
245
|
"studioUrl": "https://stately.ai",
|
|
243
246
|
"defaultXStateVersion": 5,
|
|
244
|
-
"sources": [
|
|
245
|
-
{
|
|
246
|
-
"include": ["src/**/*.ts", "src/**/*.tsx"],
|
|
247
|
-
"exclude": ["**/*.test.ts", "**/dist/**"],
|
|
248
|
-
"format": "xstate"
|
|
249
|
-
},
|
|
250
|
-
{
|
|
251
|
-
"include": ["docs/**/*.mmd"],
|
|
252
|
-
"format": "mermaid"
|
|
253
|
-
}
|
|
254
|
-
]
|
|
247
|
+
"sources": []
|
|
255
248
|
}
|
|
256
249
|
```
|
|
257
250
|
|
|
@@ -423,7 +416,7 @@ const aslYaml = await embed.export('asl-yaml');
|
|
|
423
416
|
|
|
424
417
|
<!-- supported export formats from ExportFormatMap in src/protocol.ts -->
|
|
425
418
|
|
|
426
|
-
Supported formats: `xstate`, `json`, `xgraph`, `digraph`, `mermaid`, `redux`, `zustand`, `asl-json`, `asl-yaml`, `scxml`
|
|
419
|
+
Supported formats: `xstate`, `xstate-json`, `xgraph`, `digraph`, `mermaid`, `redux`, `zustand`, `asl-json`, `asl-yaml`, `scxml`
|
|
427
420
|
|
|
428
421
|
#### `embed.on(event, handler)` / `embed.off(event, handler)`
|
|
429
422
|
|
|
@@ -605,11 +598,15 @@ Installing the package also exposes a `statelyai` binary:
|
|
|
605
598
|
npx statelyai open ./checkout.machine.ts
|
|
606
599
|
|
|
607
600
|
statelyai init
|
|
601
|
+
statelyai init --scan
|
|
608
602
|
statelyai login
|
|
609
603
|
statelyai auth status
|
|
610
604
|
statelyai plan ./checkout.machine.ts machine-id
|
|
611
605
|
statelyai diff ./checkout.machine.ts machine-id --fail-on-changes
|
|
606
|
+
statelyai push
|
|
607
|
+
statelyai push ./checkout.machine.ts
|
|
612
608
|
statelyai pull machine-id ./checkout.machine.ts
|
|
609
|
+
statelyai pull ./checkout.machine.ts
|
|
613
610
|
statelyai open ./checkout.machine.ts
|
|
614
611
|
```
|
|
615
612
|
|
|
@@ -619,13 +616,15 @@ Available commands:
|
|
|
619
616
|
|
|
620
617
|
| Command | Description |
|
|
621
618
|
| ---------------------------------- | --------------------------------------------------------------------------- |
|
|
622
|
-
| `statelyai init` | Create or reuse a Studio project for the current directory and write `statelyai.json` |
|
|
619
|
+
| `statelyai init` | Create or reuse a Studio project for the current directory and write `statelyai.json` with an empty `sources` array |
|
|
623
620
|
| `statelyai login` | Store an API key for future CLI use |
|
|
624
621
|
| `statelyai logout` | Remove a stored API key |
|
|
625
622
|
| `statelyai auth status` | Show whether the CLI would use an environment variable or stored credential |
|
|
626
623
|
| `statelyai plan <source> <target>` | Print a semantic sync summary |
|
|
627
624
|
| `statelyai diff <source> <target>` | Diff two locators and optionally fail on changes |
|
|
625
|
+
| `statelyai push [file]` | Discover local machine sources, create remote Studio machines for unlabeled files, update linked ones, and persist returned ids |
|
|
628
626
|
| `statelyai pull <source> <target>` | Materialize a source into a local target file |
|
|
627
|
+
| `statelyai pull <linked-file>` | Refresh a linked local file from the `@statelyai id=...` pragma |
|
|
629
628
|
| `statelyai open <file>` | Open a local file in a browser-backed visual editor session |
|
|
630
629
|
|
|
631
630
|
Common flags:
|
|
@@ -636,6 +635,8 @@ Common flags:
|
|
|
636
635
|
|
|
637
636
|
The CLI resolves credentials in this order: `--api-key`, then `STATELY_API_KEY`/`NEXT_PUBLIC_STATELY_API_KEY`, then the key stored by `statelyai login`. `login` stores the key in the OS credential store when available, with a private file fallback.
|
|
638
637
|
|
|
638
|
+
`statelyai init --scan` walks local code files, detects machine-bearing files from their contents, and suggests `sources` globs to save into `statelyai.json`. Without `--scan`, `init` leaves `sources` empty so you can opt in explicitly before running `statelyai push`.
|
|
639
|
+
|
|
639
640
|
`statelyai open` also supports `--api-key`, `--editor-url`, `--host`, `--port`, `--no-open`, and `--debug`. It watches the local file on disk and sends source snapshots to `/api/editor-sync/*` endpoints, which return the text replacements to apply locally. When the source file contains `// @statelyai id=...` and an API key is available, the editor session also reuses the referenced remote machine layout while continuing to treat the local source as the semantic source of truth. Pass `--api-key`, set `STATELY_API_KEY`, or run `statelyai login` when the editor server requires auth. Self-hosted servers can disable editor-sync API-key checks with `EDITOR_SYNC_AUTH_REQUIRED=false`. The private source reconciliation engine is not bundled into the published CLI.
|
|
640
641
|
|
|
641
642
|
## Transport Helpers
|
package/dist/assetStorage.d.mts
CHANGED
package/dist/cli.d.mts
CHANGED
|
@@ -4,11 +4,11 @@ import { SyncPlan } from "./sync.mjs";
|
|
|
4
4
|
import { Command } from "@oclif/core";
|
|
5
5
|
import * as _oclif_core_interfaces0 from "@oclif/core/interfaces";
|
|
6
6
|
|
|
7
|
-
//#region src/
|
|
7
|
+
//#region src/projectConfig.d.ts
|
|
8
8
|
interface StatelySourceConfig {
|
|
9
9
|
include: string[];
|
|
10
10
|
exclude?: string[];
|
|
11
|
-
format: 'xstate' | 'redux' | 'zustand' | 'xgraph' | 'digraph' | 'mermaid' | 'scxml' | 'json' | 'asl-json' | 'asl-yaml' | 'auto';
|
|
11
|
+
format: 'xstate' | 'redux' | 'zustand' | 'xgraph' | 'digraph' | 'mermaid' | 'scxml' | 'xstate-json' | 'asl-json' | 'asl-yaml' | 'auto';
|
|
12
12
|
xstateVersion?: number;
|
|
13
13
|
}
|
|
14
14
|
interface StatelyProjectConfig {
|
|
@@ -19,6 +19,13 @@ interface StatelyProjectConfig {
|
|
|
19
19
|
defaultXStateVersion: number;
|
|
20
20
|
sources: StatelySourceConfig[];
|
|
21
21
|
}
|
|
22
|
+
declare function createStatelyProjectConfig(options: {
|
|
23
|
+
projectId: string;
|
|
24
|
+
studioUrl: string;
|
|
25
|
+
defaultXStateVersion?: number;
|
|
26
|
+
}): StatelyProjectConfig;
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/cli.d.ts
|
|
22
29
|
interface InitProjectOptions {
|
|
23
30
|
apiKey: string;
|
|
24
31
|
baseUrl?: string;
|
|
@@ -34,11 +41,11 @@ interface InitProjectResult {
|
|
|
34
41
|
configPath: string;
|
|
35
42
|
project: ProjectData;
|
|
36
43
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
interface ScanProjectSourcesOptions {
|
|
45
|
+
cwd?: string;
|
|
46
|
+
client: StudioClient;
|
|
40
47
|
defaultXStateVersion?: number;
|
|
41
|
-
}
|
|
48
|
+
}
|
|
42
49
|
type ApiKeyResolution = {
|
|
43
50
|
apiKey: string;
|
|
44
51
|
detail: string;
|
|
@@ -55,6 +62,7 @@ declare function getEnvApiKey(): {
|
|
|
55
62
|
declare function resolveApiKey(explicitApiKey?: string): Promise<ApiKeyResolution>;
|
|
56
63
|
declare function inferInitProjectName(cwd: string, repo?: ConnectedRepo): string;
|
|
57
64
|
declare function initProject(options: InitProjectOptions): Promise<InitProjectResult>;
|
|
65
|
+
declare function scanProjectSources(options: ScanProjectSourcesOptions): Promise<StatelySourceConfig[]>;
|
|
58
66
|
declare function formatPlanSummary(plan: SyncPlan): string;
|
|
59
67
|
declare abstract class BaseSyncCommand extends Command {
|
|
60
68
|
static enableJsonFlag: boolean;
|
|
@@ -100,7 +108,22 @@ declare class PullCommand extends ParsedSyncCommand {
|
|
|
100
108
|
static description: string;
|
|
101
109
|
static args: {
|
|
102
110
|
source: _oclif_core_interfaces0.Arg<string, Record<string, unknown>>;
|
|
103
|
-
target: _oclif_core_interfaces0.Arg<string, Record<string, unknown>>;
|
|
111
|
+
target: _oclif_core_interfaces0.Arg<string | undefined, Record<string, unknown>>;
|
|
112
|
+
};
|
|
113
|
+
run(): Promise<void>;
|
|
114
|
+
}
|
|
115
|
+
declare class PushCommand extends Command {
|
|
116
|
+
static enableJsonFlag: boolean;
|
|
117
|
+
static summary: string;
|
|
118
|
+
static description: string;
|
|
119
|
+
static args: {
|
|
120
|
+
file: _oclif_core_interfaces0.Arg<string | undefined, Record<string, unknown>>;
|
|
121
|
+
};
|
|
122
|
+
static flags: {
|
|
123
|
+
help: _oclif_core_interfaces0.BooleanFlag<void>;
|
|
124
|
+
'api-key': _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
125
|
+
'base-url': _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
126
|
+
config: _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
104
127
|
};
|
|
105
128
|
run(): Promise<void>;
|
|
106
129
|
}
|
|
@@ -133,6 +156,7 @@ declare class InitCommand extends Command {
|
|
|
133
156
|
name: _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
134
157
|
visibility: _oclif_core_interfaces0.OptionFlag<string, _oclif_core_interfaces0.CustomOptions>;
|
|
135
158
|
force: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
159
|
+
scan: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
136
160
|
};
|
|
137
161
|
run(): Promise<void>;
|
|
138
162
|
}
|
|
@@ -169,6 +193,7 @@ declare const COMMANDS: {
|
|
|
169
193
|
plan: typeof PlanCommand;
|
|
170
194
|
diff: typeof DiffCommand;
|
|
171
195
|
pull: typeof PullCommand;
|
|
196
|
+
push: typeof PushCommand;
|
|
172
197
|
open: typeof OpenCommand;
|
|
173
198
|
init: typeof InitCommand;
|
|
174
199
|
login: typeof LoginCommand;
|
|
@@ -177,4 +202,4 @@ declare const COMMANDS: {
|
|
|
177
202
|
};
|
|
178
203
|
declare function run(argv?: string[], entryUrl?: string): Promise<void>;
|
|
179
204
|
//#endregion
|
|
180
|
-
export { ApiKeyResolution, COMMANDS, InitProjectOptions, InitProjectResult,
|
|
205
|
+
export { ApiKeyResolution, COMMANDS, InitProjectOptions, InitProjectResult, ScanProjectSourcesOptions, createStatelyProjectConfig, formatPlanSummary, getEnvApiKey, inferInitProjectName, initProject, resolveApiKey, run, scanProjectSources };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createStatelyClient } from "./studio.mjs";
|
|
3
|
-
import "./graphToXStateTS-Gzh0ZqbN.mjs";
|
|
4
|
-
import { planSync, pullSync } from "./sync.mjs";
|
|
3
|
+
import { u as getStatelyPragma } from "./graphToXStateTS-Gzh0ZqbN.mjs";
|
|
4
|
+
import { planSync, pullSync, pushLocalMachineLinks } from "./sync.mjs";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
6
6
|
import * as path$1 from "node:path";
|
|
7
7
|
import path from "node:path";
|
|
@@ -931,24 +931,26 @@ function describeCredentialBackend(backend, location) {
|
|
|
931
931
|
}
|
|
932
932
|
|
|
933
933
|
//#endregion
|
|
934
|
-
//#region src/
|
|
935
|
-
const execFileAsync = promisify(execFile);
|
|
934
|
+
//#region src/projectConfig.ts
|
|
936
935
|
const STATELY_CONFIG_FILE = "statelyai.json";
|
|
937
936
|
const STATELY_CONFIG_SCHEMA_URL = "https://stately.ai/schemas/statelyai.json";
|
|
938
937
|
const STATELY_CONFIG_VERSION = "1.0.0";
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
938
|
+
const DEFAULT_SOURCE_EXCLUDES = [
|
|
939
|
+
"**/*.test.*",
|
|
940
|
+
"**/*.spec.*",
|
|
941
|
+
"**/dist/**",
|
|
942
|
+
"**/node_modules/**"
|
|
943
|
+
];
|
|
944
|
+
const CODE_SOURCE_EXTENSIONS = new Set([
|
|
945
|
+
".ts",
|
|
946
|
+
".tsx",
|
|
947
|
+
".js",
|
|
948
|
+
".jsx",
|
|
949
|
+
".mts",
|
|
950
|
+
".cts",
|
|
951
|
+
".mjs",
|
|
952
|
+
".cjs"
|
|
953
|
+
]);
|
|
952
954
|
function createStatelyProjectConfig(options) {
|
|
953
955
|
const defaultXStateVersion = options.defaultXStateVersion ?? 5;
|
|
954
956
|
return {
|
|
@@ -957,9 +959,145 @@ function createStatelyProjectConfig(options) {
|
|
|
957
959
|
projectId: options.projectId,
|
|
958
960
|
studioUrl: options.studioUrl,
|
|
959
961
|
defaultXStateVersion,
|
|
960
|
-
sources:
|
|
962
|
+
sources: []
|
|
961
963
|
};
|
|
962
964
|
}
|
|
965
|
+
async function readStatelyProjectConfig(options = {}) {
|
|
966
|
+
const rootDir = path.resolve(options.cwd ?? process.cwd());
|
|
967
|
+
const configPath = path.resolve(rootDir, options.configPath ?? STATELY_CONFIG_FILE);
|
|
968
|
+
const raw = await fs.readFile(configPath, "utf8");
|
|
969
|
+
return {
|
|
970
|
+
config: JSON.parse(raw),
|
|
971
|
+
configPath,
|
|
972
|
+
rootDir
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
async function walkFiles(rootDir, currentDir = rootDir) {
|
|
976
|
+
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
977
|
+
const files = [];
|
|
978
|
+
for (const entry of entries) {
|
|
979
|
+
if (entry.name === ".git") continue;
|
|
980
|
+
const absolutePath = path.join(currentDir, entry.name);
|
|
981
|
+
if (entry.isDirectory()) {
|
|
982
|
+
files.push(...await walkFiles(rootDir, absolutePath));
|
|
983
|
+
continue;
|
|
984
|
+
}
|
|
985
|
+
if (!entry.isFile()) continue;
|
|
986
|
+
files.push(path.relative(rootDir, absolutePath).replace(/\\/g, "/"));
|
|
987
|
+
}
|
|
988
|
+
return files;
|
|
989
|
+
}
|
|
990
|
+
function isCodeSourceFile(relativePath) {
|
|
991
|
+
return CODE_SOURCE_EXTENSIONS.has(path.extname(relativePath).toLowerCase());
|
|
992
|
+
}
|
|
993
|
+
function expandBraces(pattern) {
|
|
994
|
+
const match = pattern.match(/\{([^{}]+)\}/);
|
|
995
|
+
if (!match || match.index == null) return [pattern];
|
|
996
|
+
const [token, inner] = match;
|
|
997
|
+
return inner.split(",").flatMap((variant) => expandBraces(`${pattern.slice(0, match.index)}${variant}${pattern.slice(match.index + token.length)}`));
|
|
998
|
+
}
|
|
999
|
+
function globToRegExp(pattern) {
|
|
1000
|
+
let regex = "^";
|
|
1001
|
+
for (let index = 0; index < pattern.length; index += 1) {
|
|
1002
|
+
const char = pattern[index];
|
|
1003
|
+
const next = pattern[index + 1];
|
|
1004
|
+
if (char === "*") {
|
|
1005
|
+
if (next === "*") {
|
|
1006
|
+
const slashAfterGlobstar = pattern[index + 2] === "/";
|
|
1007
|
+
regex += slashAfterGlobstar ? "(?:.*/)?" : ".*";
|
|
1008
|
+
index += slashAfterGlobstar ? 2 : 1;
|
|
1009
|
+
continue;
|
|
1010
|
+
}
|
|
1011
|
+
regex += "[^/]*";
|
|
1012
|
+
continue;
|
|
1013
|
+
}
|
|
1014
|
+
if (char === "?") {
|
|
1015
|
+
regex += "[^/]";
|
|
1016
|
+
continue;
|
|
1017
|
+
}
|
|
1018
|
+
if ("\\.[]{}()+-^$|".includes(char)) {
|
|
1019
|
+
regex += `\\${char}`;
|
|
1020
|
+
continue;
|
|
1021
|
+
}
|
|
1022
|
+
regex += char;
|
|
1023
|
+
}
|
|
1024
|
+
regex += "$";
|
|
1025
|
+
return new RegExp(regex);
|
|
1026
|
+
}
|
|
1027
|
+
function matchesGlob(relativePath, pattern) {
|
|
1028
|
+
return expandBraces(pattern).some((expanded) => globToRegExp(expanded).test(relativePath));
|
|
1029
|
+
}
|
|
1030
|
+
function matchesAny(patterns, relativePath) {
|
|
1031
|
+
return (patterns ?? []).some((pattern) => matchesGlob(relativePath, pattern));
|
|
1032
|
+
}
|
|
1033
|
+
async function discoverCodeSourceFiles(options = {}) {
|
|
1034
|
+
return (await walkFiles(path.resolve(options.cwd ?? process.cwd()))).filter((relativePath) => isCodeSourceFile(relativePath)).filter((relativePath) => !matchesAny(DEFAULT_SOURCE_EXCLUDES, relativePath)).sort((left, right) => left.localeCompare(right));
|
|
1035
|
+
}
|
|
1036
|
+
function createSuggestedSource(include) {
|
|
1037
|
+
return {
|
|
1038
|
+
include: [include],
|
|
1039
|
+
exclude: [...DEFAULT_SOURCE_EXCLUDES],
|
|
1040
|
+
format: "xstate",
|
|
1041
|
+
xstateVersion: 5
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
function suggestStatelySourceConfigs(relativePaths, defaultXStateVersion = 5) {
|
|
1045
|
+
const pending = new Set(relativePaths.map((relativePath) => relativePath.replace(/\\/g, "/")).filter(Boolean));
|
|
1046
|
+
const suggestions = [];
|
|
1047
|
+
const addSuggestion = (include, predicate) => {
|
|
1048
|
+
const matched = [...pending].filter(predicate);
|
|
1049
|
+
if (matched.length === 0) return;
|
|
1050
|
+
suggestions.push({
|
|
1051
|
+
...createSuggestedSource(include),
|
|
1052
|
+
xstateVersion: defaultXStateVersion
|
|
1053
|
+
});
|
|
1054
|
+
for (const matchedPath of matched) pending.delete(matchedPath);
|
|
1055
|
+
};
|
|
1056
|
+
addSuggestion("**/*.machine.ts", (relativePath) => relativePath.endsWith(".machine.ts"));
|
|
1057
|
+
addSuggestion("src/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}", (relativePath) => relativePath.startsWith("src/"));
|
|
1058
|
+
addSuggestion("packages/*/src/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}", (relativePath) => /^packages\/[^/]+\/src\//.test(relativePath));
|
|
1059
|
+
addSuggestion("apps/*/src/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}", (relativePath) => /^apps\/[^/]+\/src\//.test(relativePath));
|
|
1060
|
+
const byDirectory = /* @__PURE__ */ new Map();
|
|
1061
|
+
for (const relativePath of pending) {
|
|
1062
|
+
const directory = path.posix.dirname(relativePath);
|
|
1063
|
+
const key = directory === "." ? relativePath : directory;
|
|
1064
|
+
const bucket = byDirectory.get(key) ?? [];
|
|
1065
|
+
bucket.push(relativePath);
|
|
1066
|
+
byDirectory.set(key, bucket);
|
|
1067
|
+
}
|
|
1068
|
+
for (const [key, matchedPaths] of [...byDirectory.entries()].sort((left, right) => left[0].localeCompare(right[0]))) {
|
|
1069
|
+
if (matchedPaths.length > 1 && key !== "." && key !== matchedPaths[0]) {
|
|
1070
|
+
addSuggestion(`${key}/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}`, (relativePath) => relativePath.startsWith(`${key}/`));
|
|
1071
|
+
continue;
|
|
1072
|
+
}
|
|
1073
|
+
const exactPath = matchedPaths[0];
|
|
1074
|
+
addSuggestion(exactPath, (relativePath) => relativePath === exactPath);
|
|
1075
|
+
}
|
|
1076
|
+
return suggestions;
|
|
1077
|
+
}
|
|
1078
|
+
async function discoverStatelySourceFiles(options = {}) {
|
|
1079
|
+
const { config, rootDir } = options.config ? {
|
|
1080
|
+
config: options.config,
|
|
1081
|
+
rootDir: path.resolve(options.cwd ?? process.cwd())
|
|
1082
|
+
} : await readStatelyProjectConfig(options);
|
|
1083
|
+
const relativeFiles = await walkFiles(rootDir);
|
|
1084
|
+
const discovered = /* @__PURE__ */ new Map();
|
|
1085
|
+
for (const source of config.sources) for (const relativePath of relativeFiles) {
|
|
1086
|
+
if (!matchesAny(source.include, relativePath)) continue;
|
|
1087
|
+
if (matchesAny(source.exclude, relativePath)) continue;
|
|
1088
|
+
const filePath = path.join(rootDir, relativePath);
|
|
1089
|
+
if (!discovered.has(filePath)) discovered.set(filePath, {
|
|
1090
|
+
filePath,
|
|
1091
|
+
relativePath,
|
|
1092
|
+
source
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
return [...discovered.values()].sort((left, right) => left.relativePath.localeCompare(right.relativePath));
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
//#endregion
|
|
1099
|
+
//#region src/cli.ts
|
|
1100
|
+
const execFileAsync = promisify(execFile);
|
|
963
1101
|
function loadLocalEnv() {
|
|
964
1102
|
if (typeof process.loadEnvFile !== "function") return;
|
|
965
1103
|
const cwdEnvPath = path.join(process.cwd(), ".env.local");
|
|
@@ -1090,6 +1228,22 @@ async function promptForApiKey() {
|
|
|
1090
1228
|
rl.close();
|
|
1091
1229
|
}
|
|
1092
1230
|
}
|
|
1231
|
+
async function promptYesNo(question, defaultValue = true) {
|
|
1232
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) throw new Error("No interactive terminal available.");
|
|
1233
|
+
const rl = createInterface({
|
|
1234
|
+
input: process.stdin,
|
|
1235
|
+
output: process.stdout,
|
|
1236
|
+
terminal: true
|
|
1237
|
+
});
|
|
1238
|
+
try {
|
|
1239
|
+
const suffix = defaultValue ? " [Y/n] " : " [y/N] ";
|
|
1240
|
+
const answer = (await rl.question(`${question}${suffix}`)).trim().toLowerCase();
|
|
1241
|
+
if (!answer) return defaultValue;
|
|
1242
|
+
return answer === "y" || answer === "yes";
|
|
1243
|
+
} finally {
|
|
1244
|
+
rl.close();
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1093
1247
|
function normalizeApiKey(value) {
|
|
1094
1248
|
const trimmed = value?.trim();
|
|
1095
1249
|
return trimmed ? trimmed : void 0;
|
|
@@ -1133,6 +1287,45 @@ async function initProject(options) {
|
|
|
1133
1287
|
project
|
|
1134
1288
|
};
|
|
1135
1289
|
}
|
|
1290
|
+
async function scanProjectSources(options) {
|
|
1291
|
+
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
1292
|
+
const candidateRelativePaths = await discoverCodeSourceFiles({ cwd });
|
|
1293
|
+
const machineRelativePaths = [];
|
|
1294
|
+
for (const relativePath of candidateRelativePaths) {
|
|
1295
|
+
const filePath = path.join(cwd, relativePath);
|
|
1296
|
+
const contents = await fs.readFile(filePath, "utf8");
|
|
1297
|
+
let extracted;
|
|
1298
|
+
try {
|
|
1299
|
+
extracted = await options.client.code.extractMachines(contents);
|
|
1300
|
+
} catch {
|
|
1301
|
+
continue;
|
|
1302
|
+
}
|
|
1303
|
+
if (extracted.machines.length > 0) machineRelativePaths.push(relativePath);
|
|
1304
|
+
}
|
|
1305
|
+
return suggestStatelySourceConfigs(machineRelativePaths, Math.max(5, options.defaultXStateVersion ?? 5));
|
|
1306
|
+
}
|
|
1307
|
+
function supportsMachineDiscovery(file) {
|
|
1308
|
+
return file.source.format === "xstate" || file.source.format === "auto";
|
|
1309
|
+
}
|
|
1310
|
+
async function resolveConfiguredProject(options) {
|
|
1311
|
+
const { config, configPath, rootDir } = await readStatelyProjectConfig({
|
|
1312
|
+
cwd: options.cwd,
|
|
1313
|
+
configPath: options.configPath
|
|
1314
|
+
});
|
|
1315
|
+
const studioUrl = options.baseUrl ?? config.studioUrl;
|
|
1316
|
+
return {
|
|
1317
|
+
client: options.client ?? createStatelyClient({
|
|
1318
|
+
apiKey: options.apiKey,
|
|
1319
|
+
baseUrl: studioUrl
|
|
1320
|
+
}),
|
|
1321
|
+
config,
|
|
1322
|
+
configPath,
|
|
1323
|
+
files: await discoverStatelySourceFiles({
|
|
1324
|
+
cwd: rootDir,
|
|
1325
|
+
config
|
|
1326
|
+
})
|
|
1327
|
+
};
|
|
1328
|
+
}
|
|
1136
1329
|
const sharedFlags = {
|
|
1137
1330
|
help: Flags.help({ char: "h" }),
|
|
1138
1331
|
"fail-on-changes": Flags.boolean({
|
|
@@ -1225,19 +1418,99 @@ var DiffCommand = class DiffCommand extends ParsedSyncCommand {
|
|
|
1225
1418
|
var PullCommand = class PullCommand extends ParsedSyncCommand {
|
|
1226
1419
|
static summary = "Pull a source locator into a local target file.";
|
|
1227
1420
|
static description = "Resolves the source, materializes it in the target format inferred from the target file, and writes the result locally.";
|
|
1228
|
-
static args =
|
|
1421
|
+
static args = {
|
|
1422
|
+
source: Args.string({
|
|
1423
|
+
required: true,
|
|
1424
|
+
description: "Source locator. Supports a local linked file, machine ID, URL, or local file path."
|
|
1425
|
+
}),
|
|
1426
|
+
target: Args.string({
|
|
1427
|
+
required: false,
|
|
1428
|
+
description: "Optional local target path. Defaults to the source file when pulling a linked local file."
|
|
1429
|
+
})
|
|
1430
|
+
};
|
|
1229
1431
|
async run() {
|
|
1230
1432
|
const { args, flags } = await this.parseSync(PullCommand);
|
|
1231
1433
|
const apiKey = (await resolveApiKey(flags["api-key"])).apiKey;
|
|
1434
|
+
const localCandidate = path.resolve(process.cwd(), args.source);
|
|
1435
|
+
let source = args.source;
|
|
1436
|
+
let target = args.target;
|
|
1437
|
+
if (!target && await fileExists(localCandidate)) {
|
|
1438
|
+
const pragma = getStatelyPragma(await fs.readFile(localCandidate, "utf8"), localCandidate);
|
|
1439
|
+
if (!pragma?.id) this.error(`No @statelyai id found in ${localCandidate}. Pass an explicit source machine ID or URL and target path.`);
|
|
1440
|
+
source = pragma.id;
|
|
1441
|
+
target = localCandidate;
|
|
1442
|
+
}
|
|
1443
|
+
if (!target) this.error("Missing target path. Pass `statelyai pull <machine-id|url> <file>` or `statelyai pull <linked-file>`.");
|
|
1232
1444
|
const result = await pullSync({
|
|
1233
|
-
source
|
|
1234
|
-
target
|
|
1445
|
+
source,
|
|
1446
|
+
target,
|
|
1235
1447
|
apiKey,
|
|
1236
1448
|
baseUrl: flags["base-url"] ?? getDefaultBaseUrl()
|
|
1237
1449
|
});
|
|
1238
1450
|
this.log(`Pulled: ${result.source.locator} -> ${result.outputPath}\nTarget: ${result.target.kind} (${result.target.format})`);
|
|
1239
1451
|
}
|
|
1240
1452
|
};
|
|
1453
|
+
var PushCommand = class PushCommand extends Command {
|
|
1454
|
+
static enableJsonFlag = false;
|
|
1455
|
+
static summary = "Create or update remote machines for local source files.";
|
|
1456
|
+
static description = "Uses statelyai.json source discovery by default, creates remote machines for unlabeled local machine sources, updates already-linked machines, and writes returned @statelyai ids back into source files.";
|
|
1457
|
+
static args = { file: Args.string({
|
|
1458
|
+
required: false,
|
|
1459
|
+
description: "Optional local source file to push instead of scanning statelyai.json."
|
|
1460
|
+
}) };
|
|
1461
|
+
static flags = {
|
|
1462
|
+
help: Flags.help({ char: "h" }),
|
|
1463
|
+
"api-key": Flags.string({ description: "Stately API key used to create or update remote machines" }),
|
|
1464
|
+
"base-url": Flags.string({ description: "Base URL for Stately Studio or a self-hosted deployment" }),
|
|
1465
|
+
config: Flags.string({ description: "Path to statelyai.json" })
|
|
1466
|
+
};
|
|
1467
|
+
async run() {
|
|
1468
|
+
const { args, flags } = await this.parse(PushCommand);
|
|
1469
|
+
const resolvedApiKey = await resolveApiKey(flags["api-key"]);
|
|
1470
|
+
if (!resolvedApiKey.apiKey) this.error("No API key configured. Use `statelyai login`, set `STATELY_API_KEY`, or pass `--api-key`.");
|
|
1471
|
+
const { client, config, files } = await resolveConfiguredProject({
|
|
1472
|
+
apiKey: resolvedApiKey.apiKey,
|
|
1473
|
+
baseUrl: flags["base-url"],
|
|
1474
|
+
configPath: flags.config
|
|
1475
|
+
});
|
|
1476
|
+
const candidateFiles = args.file ? [{
|
|
1477
|
+
filePath: path.resolve(args.file),
|
|
1478
|
+
relativePath: path.relative(process.cwd(), path.resolve(args.file)),
|
|
1479
|
+
source: {
|
|
1480
|
+
include: [args.file],
|
|
1481
|
+
format: "xstate",
|
|
1482
|
+
xstateVersion: config.defaultXStateVersion
|
|
1483
|
+
}
|
|
1484
|
+
}] : files.filter(supportsMachineDiscovery);
|
|
1485
|
+
if (candidateFiles.length === 0) {
|
|
1486
|
+
this.log("No matching local machine source files were discovered.");
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
const linked = [];
|
|
1490
|
+
const refreshed = [];
|
|
1491
|
+
const skipped = [];
|
|
1492
|
+
for (const file of candidateFiles) {
|
|
1493
|
+
if (!supportsMachineDiscovery(file)) {
|
|
1494
|
+
skipped.push(`${file.relativePath}: unsupported format ${file.source.format}`);
|
|
1495
|
+
continue;
|
|
1496
|
+
}
|
|
1497
|
+
const result = await pushLocalMachineLinks({
|
|
1498
|
+
source: file.filePath,
|
|
1499
|
+
apiKey: resolvedApiKey.apiKey,
|
|
1500
|
+
baseUrl: flags["base-url"] ?? config.studioUrl,
|
|
1501
|
+
client,
|
|
1502
|
+
project: { projectId: config.projectId },
|
|
1503
|
+
xstateVersion: Math.max(5, file.source.xstateVersion ?? config.defaultXStateVersion)
|
|
1504
|
+
});
|
|
1505
|
+
if (result.created.length > 0) linked.push(`${file.relativePath}: ${result.created.map(({ machineIndex, machine }) => `${machine.id} [${machineIndex}]`).join(", ")}`);
|
|
1506
|
+
if (result.updated.length > 0) refreshed.push(`${file.relativePath}: ${result.updated.map(({ machineIndex, machine }) => `${machine.id} [${machineIndex}]`).join(", ")}`);
|
|
1507
|
+
for (const entry of result.skipped) skipped.push(`${file.relativePath} [${entry.machineIndex}]: ${entry.reason}`);
|
|
1508
|
+
}
|
|
1509
|
+
if (linked.length > 0) this.log(`Linked:\n${linked.join("\n")}`);
|
|
1510
|
+
if (refreshed.length > 0) this.log(`Updated:\n${refreshed.join("\n")}`);
|
|
1511
|
+
if (skipped.length > 0) this.log(`Skipped:\n${skipped.join("\n")}`);
|
|
1512
|
+
}
|
|
1513
|
+
};
|
|
1241
1514
|
var OpenCommand = class OpenCommand extends Command {
|
|
1242
1515
|
static enableJsonFlag = false;
|
|
1243
1516
|
static summary = "Open a local file in the Stately visual editor.";
|
|
@@ -1304,6 +1577,10 @@ var InitCommand = class InitCommand extends Command {
|
|
|
1304
1577
|
force: Flags.boolean({
|
|
1305
1578
|
description: "Overwrite an existing statelyai.json file",
|
|
1306
1579
|
default: false
|
|
1580
|
+
}),
|
|
1581
|
+
scan: Flags.boolean({
|
|
1582
|
+
description: "Scan the repo for machine-bearing files and suggest source globs to save into statelyai.json",
|
|
1583
|
+
default: false
|
|
1307
1584
|
})
|
|
1308
1585
|
};
|
|
1309
1586
|
async run() {
|
|
@@ -1319,7 +1596,33 @@ var InitCommand = class InitCommand extends Command {
|
|
|
1319
1596
|
visibility: flags.visibility
|
|
1320
1597
|
}
|
|
1321
1598
|
});
|
|
1322
|
-
|
|
1599
|
+
if (flags.scan) {
|
|
1600
|
+
const scanClient = createStatelyClient({
|
|
1601
|
+
apiKey: resolvedApiKey.apiKey,
|
|
1602
|
+
baseUrl: flags["base-url"] ?? result.config.studioUrl
|
|
1603
|
+
});
|
|
1604
|
+
const suggestions = await scanProjectSources({
|
|
1605
|
+
cwd: path.dirname(result.configPath),
|
|
1606
|
+
client: scanClient,
|
|
1607
|
+
defaultXStateVersion: result.config.defaultXStateVersion
|
|
1608
|
+
});
|
|
1609
|
+
if (suggestions.length === 0) {
|
|
1610
|
+
this.log(`Initialized project ${result.project.projectId} and wrote ${result.configPath}.\nNo machine source globs were suggested. Edit statelyai.json before running statelyai push.`);
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
this.log(`Initialized project ${result.project.projectId} and wrote ${result.configPath}.`);
|
|
1614
|
+
this.log(`Suggested source globs:\n${suggestions.map((source) => `- ${source.include.join(", ")}`).join("\n")}`);
|
|
1615
|
+
if (await promptYesNo("Save these source globs to statelyai.json?", true)) {
|
|
1616
|
+
const nextConfig = {
|
|
1617
|
+
...result.config,
|
|
1618
|
+
sources: suggestions
|
|
1619
|
+
};
|
|
1620
|
+
await fs.writeFile(result.configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf8");
|
|
1621
|
+
this.log("Saved scanned source globs to statelyai.json.");
|
|
1622
|
+
} else this.log("Left statelyai.json with an empty sources array. Edit it before running statelyai push.");
|
|
1623
|
+
return;
|
|
1624
|
+
}
|
|
1625
|
+
this.log(`Initialized project ${result.project.projectId} and wrote ${result.configPath}.\nNo source globs configured yet. Edit statelyai.json before running statelyai push, or rerun with --scan.`);
|
|
1323
1626
|
}
|
|
1324
1627
|
};
|
|
1325
1628
|
var LoginCommand = class LoginCommand extends Command {
|
|
@@ -1381,6 +1684,7 @@ const COMMANDS = {
|
|
|
1381
1684
|
plan: PlanCommand,
|
|
1382
1685
|
diff: DiffCommand,
|
|
1383
1686
|
pull: PullCommand,
|
|
1687
|
+
push: PushCommand,
|
|
1384
1688
|
open: OpenCommand,
|
|
1385
1689
|
init: InitCommand,
|
|
1386
1690
|
login: LoginCommand,
|
|
@@ -1409,4 +1713,4 @@ function isDirectExecution() {
|
|
|
1409
1713
|
if (isDirectExecution()) run();
|
|
1410
1714
|
|
|
1411
1715
|
//#endregion
|
|
1412
|
-
export { COMMANDS, createStatelyProjectConfig, formatPlanSummary, getEnvApiKey, inferInitProjectName, initProject, resolveApiKey, run };
|
|
1716
|
+
export { COMMANDS, createStatelyProjectConfig, formatPlanSummary, getEnvApiKey, inferInitProjectName, initProject, resolveApiKey, run, scanProjectSources };
|
package/dist/embed.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as EmbedMode, c as ExportFormatMap, d as MachineSourceLocations, f as ProjectEmbedMachine, i as EmbedEventName, l as InitOptions, m as UploadResult, n as EmbedEventHandler, o as ExportCallOptions, r as EmbedEventMap, s as ExportFormat, t as CommentsConfig, u as MachineInitOptions } from "./protocol-
|
|
1
|
+
import { a as EmbedMode, c as ExportFormatMap, d as MachineSourceLocations, f as ProjectEmbedMachine, i as EmbedEventName, l as InitOptions, m as UploadResult, n as EmbedEventHandler, o as ExportCallOptions, r as EmbedEventMap, s as ExportFormat, t as CommentsConfig, u as MachineInitOptions } from "./protocol-DN4mH4jR.mjs";
|
|
2
2
|
import { AssetUploadAdapter } from "./assetStorage.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/embed.d.ts
|
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-
|
|
1
|
+
import { a as toInitMessage, i as createPendingExportManager, r as createEventRegistry, t as createPostMessageTransport } from "./transport-C8UTS3Fa.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/embed.ts
|
|
4
4
|
function buildEmbedUrl(options) {
|
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { StatelyApiClientOptions, StatelyApiError, StatelyApiUrlOptions, createStatelyApiClient, createStatelyApiUrl } from "./api.mjs";
|
|
2
|
-
import { a as EmbedMode, c as ExportFormatMap, f as ProjectEmbedMachine, i as EmbedEventName, l as InitOptions, m as UploadResult, n as EmbedEventHandler, o as ExportCallOptions, r as EmbedEventMap, s as ExportFormat, t as CommentsConfig } from "./protocol-
|
|
2
|
+
import { a as EmbedMode, c as ExportFormatMap, f as ProjectEmbedMachine, i as EmbedEventName, l as InitOptions, m as UploadResult, n as EmbedEventHandler, o as ExportCallOptions, r as EmbedEventMap, s as ExportFormat, t as CommentsConfig } from "./protocol-DN4mH4jR.mjs";
|
|
3
3
|
import { AssetUploadAdapter, AssetUploadContext, AssetUploadRequest, CreateS3AssetUploadAdapterOptions, CreateSupabaseAssetUploadAdapterOptions, S3UploadTarget, SupabaseStorageClient, createS3AssetUploadAdapter, createSupabaseAssetUploadAdapter } from "./assetStorage.mjs";
|
|
4
|
-
import { ConnectedRepo, CreateMachineFromDefinitionInput, CreateMachineFromTemplateInput, CreateMachineInput, CreateMachineTemplate, CreateProjectInput, EnsureProjectInput, ExtractMachinesResponse, ExtractedMachine, GetMachineOptions, ProjectData, ProjectMachine, ProjectVisibility, RepoType, StudioApiError, StudioClient, StudioClientOptions, StudioMachineRecord, VerifyApiKeyResponse, XStateVersion, createStatelyClient } from "./studio.mjs";
|
|
4
|
+
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";
|
|
5
5
|
import { C as EventTypeData, S as DigraphNodeConfig, _ 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-DpBGHZwl.mjs";
|
|
6
|
-
import { PlanSyncOptions, PullSyncResult, PushSyncOptions, PushSyncProjectOptions, PushSyncResult, ResolvedSyncInput, SyncInputFormat, SyncPlan, SyncPlanSummary } from "./sync.mjs";
|
|
6
|
+
import { PlanSyncOptions, PullSyncResult, PushLocalMachineLinksResult, PushSyncOptions, PushSyncProjectOptions, PushSyncResult, ResolvedSyncInput, SyncInputFormat, SyncPlan, SyncPlanSummary } from "./sync.mjs";
|
|
7
7
|
import { AssetConfig, StatelyEmbed, StatelyEmbedOptions, createStatelyEmbed } from "./embed.mjs";
|
|
8
|
-
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-
|
|
8
|
+
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-Bg9FTvb3.mjs";
|
|
9
9
|
import { ActionLocation, GraphPatch } from "./patchTypes.mjs";
|
|
10
10
|
import { JSONSchema7 } from "json-schema";
|
|
11
11
|
import { UnknownMachineConfig } from "xstate";
|
|
@@ -185,4 +185,4 @@ declare function contextSchemaToTSType(context: Record<string, JSONSchema7> | nu
|
|
|
185
185
|
*/
|
|
186
186
|
declare function eventsSchemaToTSType(events: Record<string, JSONSchema7> | null | undefined): string | null;
|
|
187
187
|
//#endregion
|
|
188
|
-
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 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 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 };
|
|
188
|
+
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 };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as createWebSocketTransport, t as createPostMessageTransport } from "./transport-
|
|
1
|
+
import { n as createWebSocketTransport, t as createPostMessageTransport } from "./transport-C8UTS3Fa.mjs";
|
|
2
2
|
import { createStatelyEmbed } from "./embed.mjs";
|
|
3
3
|
import { createS3AssetUploadAdapter, createSupabaseAssetUploadAdapter } from "./assetStorage.mjs";
|
|
4
4
|
import { createStatelyInspector } from "./inspect.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as ExportFormatMap, o as ExportCallOptions, p as ProtocolMessage, r as EmbedEventMap, s as ExportFormat } from "./protocol-
|
|
1
|
+
import { c as ExportFormatMap, o as ExportCallOptions, p as ProtocolMessage, r as EmbedEventMap, s as ExportFormat } from "./protocol-DN4mH4jR.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/transport.d.ts
|
|
4
4
|
interface Transport {
|
package/dist/inspect.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as EmbedMode, c as ExportFormatMap, i as EmbedEventName, n as EmbedEventHandler, o as ExportCallOptions, r as EmbedEventMap, s as ExportFormat } from "./protocol-
|
|
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-
|
|
1
|
+
import { a as EmbedMode, c as ExportFormatMap, i as EmbedEventName, n as EmbedEventHandler, o as ExportCallOptions, r as EmbedEventMap, s as ExportFormat } from "./protocol-DN4mH4jR.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-Bg9FTvb3.mjs";
|
|
3
3
|
export { AdoptedActor, CreateInspectorOptions, 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-
|
|
1
|
+
import { i as createPendingExportManager, n as createWebSocketTransport, r as createEventRegistry } from "./transport-C8UTS3Fa.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/inspect.ts
|
|
4
4
|
const defaultSerializeSnapshot = (snapshot) => ({
|
package/dist/studio.d.mts
CHANGED
|
@@ -75,6 +75,11 @@ interface CreateMachineFromTemplateInput {
|
|
|
75
75
|
xstateVersion?: XStateVersion;
|
|
76
76
|
}
|
|
77
77
|
type CreateMachineInput<TDefinition = Record<string, unknown>> = CreateMachineFromDefinitionInput<TDefinition> | CreateMachineFromTemplateInput;
|
|
78
|
+
interface UpdateMachineInput<TDefinition = Record<string, unknown>> {
|
|
79
|
+
id: string;
|
|
80
|
+
name?: string;
|
|
81
|
+
definition?: TDefinition;
|
|
82
|
+
}
|
|
78
83
|
interface StudioMachineRecord<TDefinition = Record<string, unknown>> {
|
|
79
84
|
id: string;
|
|
80
85
|
name: string;
|
|
@@ -99,6 +104,7 @@ interface StudioClient {
|
|
|
99
104
|
machines: {
|
|
100
105
|
create<TMachine = Record<string, unknown>>(input: CreateMachineInput<TMachine>): Promise<StudioMachineRecord<TMachine>>;
|
|
101
106
|
createMany<TMachine = Record<string, unknown>>(input: CreateMachineInput<TMachine>): Promise<Array<StudioMachineRecord<TMachine>>>;
|
|
107
|
+
update<TMachine = Record<string, unknown>>(input: UpdateMachineInput<TMachine>): Promise<StudioMachineRecord<TMachine>>;
|
|
102
108
|
get<TMachine = Record<string, unknown>>(machineId: string, options?: GetMachineOptions): Promise<TMachine>;
|
|
103
109
|
};
|
|
104
110
|
code: {
|
|
@@ -109,4 +115,4 @@ interface StudioClient {
|
|
|
109
115
|
}
|
|
110
116
|
declare function createStatelyClient(options?: StudioClientOptions): StudioClient;
|
|
111
117
|
//#endregion
|
|
112
|
-
export { ConnectedRepo, CreateMachineFromDefinitionInput, CreateMachineFromTemplateInput, CreateMachineInput, CreateMachineTemplate, CreateProjectInput, EnsureProjectInput, ExtractMachinesResponse, ExtractedMachine, GetMachineOptions, ProjectData, ProjectMachine, ProjectVisibility, RepoType, StudioApiError, StudioClient, StudioClientOptions, StudioMachineRecord, VerifyApiKeyResponse, XStateVersion, createStatelyClient };
|
|
118
|
+
export { ConnectedRepo, CreateMachineFromDefinitionInput, CreateMachineFromTemplateInput, CreateMachineInput, CreateMachineTemplate, CreateProjectInput, EnsureProjectInput, ExtractMachinesResponse, ExtractedMachine, GetMachineOptions, ProjectData, ProjectMachine, ProjectVisibility, RepoType, StudioApiError, StudioClient, StudioClientOptions, StudioMachineRecord, UpdateMachineInput, VerifyApiKeyResponse, XStateVersion, createStatelyClient };
|
package/dist/studio.mjs
CHANGED
|
@@ -102,6 +102,13 @@ function createStatelyClient(options = {}) {
|
|
|
102
102
|
async createMany(input) {
|
|
103
103
|
return [await this.create(input)];
|
|
104
104
|
},
|
|
105
|
+
update(input) {
|
|
106
|
+
return request(`/machines/${encodeURIComponent(input.id)}`, {
|
|
107
|
+
method: "PATCH",
|
|
108
|
+
headers: { "Content-Type": "application/json" },
|
|
109
|
+
body: JSON.stringify(input)
|
|
110
|
+
});
|
|
111
|
+
},
|
|
105
112
|
get(machineId, getOptions = {}) {
|
|
106
113
|
const search = new URLSearchParams();
|
|
107
114
|
if (getOptions.version) search.set("version", getOptions.version);
|
package/dist/sync.d.mts
CHANGED
|
@@ -52,8 +52,26 @@ interface PushSyncResult {
|
|
|
52
52
|
machine: StudioMachineRecord<DigraphConfig>;
|
|
53
53
|
outputPath?: string;
|
|
54
54
|
}
|
|
55
|
+
interface PushLocalMachineLinksResult {
|
|
56
|
+
sourcePath: string;
|
|
57
|
+
project: ProjectData;
|
|
58
|
+
created: Array<{
|
|
59
|
+
machineIndex: number;
|
|
60
|
+
machine: StudioMachineRecord<DigraphConfig>;
|
|
61
|
+
}>;
|
|
62
|
+
updated: Array<{
|
|
63
|
+
machineIndex: number;
|
|
64
|
+
machine: StudioMachineRecord<DigraphConfig>;
|
|
65
|
+
}>;
|
|
66
|
+
skipped: Array<{
|
|
67
|
+
machineIndex: number;
|
|
68
|
+
reason: string;
|
|
69
|
+
}>;
|
|
70
|
+
outputPath?: string;
|
|
71
|
+
}
|
|
72
|
+
declare function pushLocalMachineLinks(options: PushSyncOptions): Promise<PushLocalMachineLinksResult>;
|
|
55
73
|
declare function planSync(options: PlanSyncOptions): Promise<SyncPlan>;
|
|
56
74
|
declare function pullSync(options: PlanSyncOptions): Promise<PullSyncResult>;
|
|
57
75
|
declare function pushSync(options: PushSyncOptions): Promise<PushSyncResult>;
|
|
58
76
|
//#endregion
|
|
59
|
-
export { PlanSyncOptions, PullSyncResult, PushSyncOptions, PushSyncProjectOptions, PushSyncResult, ResolvedSyncInput, SyncInputFormat, SyncPlan, SyncPlanSummary, planSync, pullSync, pushSync };
|
|
77
|
+
export { PlanSyncOptions, PullSyncResult, PushLocalMachineLinksResult, PushSyncOptions, PushSyncProjectOptions, PushSyncResult, ResolvedSyncInput, SyncInputFormat, SyncPlan, SyncPlanSummary, planSync, pullSync, pushLocalMachineLinks, pushSync };
|
package/dist/sync.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createStatelyClient } from "./studio.mjs";
|
|
2
|
-
import { d as upsertStatelyPragma, t as graphToXStateTS } from "./graphToXStateTS-Gzh0ZqbN.mjs";
|
|
2
|
+
import { d as upsertStatelyPragma, l as findStatelyPragmaAttachments, t as graphToXStateTS, u as getStatelyPragma } from "./graphToXStateTS-Gzh0ZqbN.mjs";
|
|
3
3
|
import { fromStudioMachine, toStudioMachine } from "./graph.mjs";
|
|
4
4
|
import { getDiff, isEmptyDiff } from "@statelyai/graph";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
@@ -186,6 +186,90 @@ function fromXStateConfig(config) {
|
|
|
186
186
|
data: {}
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
|
+
async function pushLocalMachineLinks(options) {
|
|
190
|
+
const client = options.client ?? createStatelyClient({
|
|
191
|
+
apiKey: options.apiKey,
|
|
192
|
+
baseUrl: options.baseUrl,
|
|
193
|
+
fetch: options.fetch
|
|
194
|
+
});
|
|
195
|
+
const sourcePath = path.resolve(options.cwd ?? process.cwd(), options.source);
|
|
196
|
+
const project = await resolvePushProject(client, sourcePath, options);
|
|
197
|
+
if (!project.projectVersionId) throw new Error("Resolved project is missing projectVersionId.");
|
|
198
|
+
const contents = await fs.readFile(sourcePath, "utf8");
|
|
199
|
+
const attachments = findStatelyPragmaAttachments(contents, sourcePath);
|
|
200
|
+
const extracted = await client.code.extractMachines(contents);
|
|
201
|
+
if (attachments.length === 0 || extracted.machines.length === 0) return {
|
|
202
|
+
sourcePath,
|
|
203
|
+
project,
|
|
204
|
+
created: [],
|
|
205
|
+
updated: [],
|
|
206
|
+
skipped: [{
|
|
207
|
+
machineIndex: 0,
|
|
208
|
+
reason: "No local machines were discovered in this file."
|
|
209
|
+
}]
|
|
210
|
+
};
|
|
211
|
+
if (attachments.length !== extracted.machines.length) return {
|
|
212
|
+
sourcePath,
|
|
213
|
+
project,
|
|
214
|
+
created: [],
|
|
215
|
+
updated: [],
|
|
216
|
+
skipped: [{
|
|
217
|
+
machineIndex: 0,
|
|
218
|
+
reason: "The local machine extractor did not align with the source attachments for this file."
|
|
219
|
+
}]
|
|
220
|
+
};
|
|
221
|
+
let nextContents = contents;
|
|
222
|
+
let outputPath;
|
|
223
|
+
const created = [];
|
|
224
|
+
const updated = [];
|
|
225
|
+
const skipped = [];
|
|
226
|
+
for (const [machineIndex, attachment] of attachments.entries()) {
|
|
227
|
+
const extractedMachine = extracted.machines[machineIndex];
|
|
228
|
+
if (!extractedMachine?.config) {
|
|
229
|
+
skipped.push({
|
|
230
|
+
machineIndex,
|
|
231
|
+
reason: "No extracted machine config was available for this source."
|
|
232
|
+
});
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
if (attachment.pragma?.id) {
|
|
236
|
+
const updatedMachine = await client.machines.update({
|
|
237
|
+
id: attachment.pragma.id,
|
|
238
|
+
definition: toStudioMachine(fromXStateConfig(extractedMachine.config))
|
|
239
|
+
});
|
|
240
|
+
updated.push({
|
|
241
|
+
machineIndex,
|
|
242
|
+
machine: updatedMachine
|
|
243
|
+
});
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
const machine = await client.machines.create({
|
|
247
|
+
projectVersionId: project.projectVersionId,
|
|
248
|
+
definition: toStudioMachine(fromXStateConfig(extractedMachine.config)),
|
|
249
|
+
xstateVersion: Math.max(5, options.xstateVersion ?? 5)
|
|
250
|
+
});
|
|
251
|
+
nextContents = upsertStatelyPragma(nextContents, machine.id, {
|
|
252
|
+
fileName: sourcePath,
|
|
253
|
+
machineIndex
|
|
254
|
+
});
|
|
255
|
+
created.push({
|
|
256
|
+
machineIndex,
|
|
257
|
+
machine
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
if (nextContents !== contents) {
|
|
261
|
+
await fs.writeFile(sourcePath, nextContents, "utf8");
|
|
262
|
+
outputPath = sourcePath;
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
sourcePath,
|
|
266
|
+
project,
|
|
267
|
+
created,
|
|
268
|
+
updated,
|
|
269
|
+
skipped,
|
|
270
|
+
...outputPath ? { outputPath } : {}
|
|
271
|
+
};
|
|
272
|
+
}
|
|
189
273
|
async function resolveLocalFile(locator, options) {
|
|
190
274
|
const filePath = path.resolve(options.cwd ?? process.cwd(), locator);
|
|
191
275
|
const contents = await fs.readFile(filePath, "utf8");
|
|
@@ -350,12 +434,20 @@ async function pushSync(options) {
|
|
|
350
434
|
if (source.kind !== "local-file") throw new Error("pushSync currently requires a local source file.");
|
|
351
435
|
const sourcePath = source.locator;
|
|
352
436
|
const project = await resolvePushProject(client, sourcePath, options);
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
437
|
+
const existingMachineId = source.format === "xstate" ? getStatelyPragma(await fs.readFile(sourcePath, "utf8"), sourcePath)?.id : void 0;
|
|
438
|
+
let machine;
|
|
439
|
+
if (existingMachineId) machine = await client.machines.update({
|
|
440
|
+
id: existingMachineId,
|
|
441
|
+
definition: toStudioMachine(source.graph)
|
|
358
442
|
});
|
|
443
|
+
else {
|
|
444
|
+
if (!project.projectVersionId) throw new Error("Resolved project is missing projectVersionId.");
|
|
445
|
+
machine = await client.machines.create({
|
|
446
|
+
projectVersionId: project.projectVersionId,
|
|
447
|
+
definition: toStudioMachine(source.graph),
|
|
448
|
+
xstateVersion: options.xstateVersion ?? 5
|
|
449
|
+
});
|
|
450
|
+
}
|
|
359
451
|
let outputPath;
|
|
360
452
|
if (source.format === "xstate") {
|
|
361
453
|
const contents = await fs.readFile(sourcePath, "utf8");
|
|
@@ -374,4 +466,4 @@ async function pushSync(options) {
|
|
|
374
466
|
}
|
|
375
467
|
|
|
376
468
|
//#endregion
|
|
377
|
-
export { planSync, pullSync, pushSync };
|
|
469
|
+
export { planSync, pullSync, pushLocalMachineLinks, pushSync };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statelyai/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"statelyai": "./dist/cli.mjs"
|
|
@@ -54,7 +54,9 @@
|
|
|
54
54
|
"import": "./dist/assetStorage.mjs"
|
|
55
55
|
},
|
|
56
56
|
"./statelyai.schema.json": "./schemas/statelyai.schema.json",
|
|
57
|
-
"./schemas/statelyai.schema.json": "./schemas/statelyai.schema.json"
|
|
57
|
+
"./schemas/statelyai.schema.json": "./schemas/statelyai.schema.json",
|
|
58
|
+
"./xstate-json.schema.json": "./schemas/xstate-json.schema.json",
|
|
59
|
+
"./schemas/xstate-json.schema.json": "./schemas/xstate-json.schema.json"
|
|
58
60
|
},
|
|
59
61
|
"dependencies": {
|
|
60
62
|
"@oclif/core": "^4.10.3",
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://stately.ai/schemas/xstate-json.json",
|
|
4
|
+
"title": "XState JSON machine config",
|
|
5
|
+
"description": "Strict JSON subset of an XState machine config that can be passed to createMachine(config). Shorthand string forms are normalized to object and array forms.",
|
|
6
|
+
"$ref": "#/$defs/machineConfig",
|
|
7
|
+
"$defs": {
|
|
8
|
+
"jsonValue": {
|
|
9
|
+
"description": "Any JSON value.",
|
|
10
|
+
"oneOf": [
|
|
11
|
+
{ "type": "null" },
|
|
12
|
+
{ "type": "boolean" },
|
|
13
|
+
{ "type": "number" },
|
|
14
|
+
{ "type": "string" },
|
|
15
|
+
{
|
|
16
|
+
"type": "array",
|
|
17
|
+
"items": { "$ref": "#/$defs/jsonValue" }
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"type": "object",
|
|
21
|
+
"additionalProperties": { "$ref": "#/$defs/jsonValue" }
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"jsonObject": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"additionalProperties": { "$ref": "#/$defs/jsonValue" }
|
|
28
|
+
},
|
|
29
|
+
"parameterizedObject": {
|
|
30
|
+
"type": "object",
|
|
31
|
+
"additionalProperties": false,
|
|
32
|
+
"required": ["type"],
|
|
33
|
+
"properties": {
|
|
34
|
+
"type": { "type": "string", "minLength": 1 },
|
|
35
|
+
"params": { "$ref": "#/$defs/jsonValue" }
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"actionObject": {
|
|
39
|
+
"$ref": "#/$defs/parameterizedObject"
|
|
40
|
+
},
|
|
41
|
+
"guardObject": {
|
|
42
|
+
"$ref": "#/$defs/parameterizedObject"
|
|
43
|
+
},
|
|
44
|
+
"transitionObject": {
|
|
45
|
+
"type": "object",
|
|
46
|
+
"additionalProperties": false,
|
|
47
|
+
"properties": {
|
|
48
|
+
"target": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"items": { "type": "string", "minLength": 1 }
|
|
51
|
+
},
|
|
52
|
+
"guard": { "$ref": "#/$defs/guardObject" },
|
|
53
|
+
"actions": {
|
|
54
|
+
"type": "array",
|
|
55
|
+
"items": { "$ref": "#/$defs/actionObject" }
|
|
56
|
+
},
|
|
57
|
+
"reenter": { "type": "boolean" },
|
|
58
|
+
"meta": { "$ref": "#/$defs/jsonObject" },
|
|
59
|
+
"description": { "type": "string" }
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"transitionArray": {
|
|
63
|
+
"type": "array",
|
|
64
|
+
"items": { "$ref": "#/$defs/transitionObject" }
|
|
65
|
+
},
|
|
66
|
+
"transitionsByEvent": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"additionalProperties": { "$ref": "#/$defs/transitionArray" }
|
|
69
|
+
},
|
|
70
|
+
"invokeObject": {
|
|
71
|
+
"type": "object",
|
|
72
|
+
"additionalProperties": false,
|
|
73
|
+
"required": ["src"],
|
|
74
|
+
"properties": {
|
|
75
|
+
"id": { "type": "string" },
|
|
76
|
+
"systemId": { "type": "string" },
|
|
77
|
+
"src": { "type": "string", "minLength": 1 },
|
|
78
|
+
"input": { "$ref": "#/$defs/jsonValue" },
|
|
79
|
+
"onDone": { "$ref": "#/$defs/transitionArray" },
|
|
80
|
+
"onError": { "$ref": "#/$defs/transitionArray" },
|
|
81
|
+
"onSnapshot": { "$ref": "#/$defs/transitionArray" }
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"stateNodeConfig": {
|
|
85
|
+
"type": "object",
|
|
86
|
+
"additionalProperties": false,
|
|
87
|
+
"properties": {
|
|
88
|
+
"id": { "type": "string" },
|
|
89
|
+
"type": {
|
|
90
|
+
"enum": ["atomic", "compound", "parallel", "final", "history"]
|
|
91
|
+
},
|
|
92
|
+
"history": {
|
|
93
|
+
"anyOf": [
|
|
94
|
+
{ "enum": ["shallow", "deep"] },
|
|
95
|
+
{ "type": "boolean" }
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
"states": {
|
|
99
|
+
"type": "object",
|
|
100
|
+
"additionalProperties": { "$ref": "#/$defs/stateNodeConfig" }
|
|
101
|
+
},
|
|
102
|
+
"invoke": {
|
|
103
|
+
"type": "array",
|
|
104
|
+
"items": { "$ref": "#/$defs/invokeObject" }
|
|
105
|
+
},
|
|
106
|
+
"on": { "$ref": "#/$defs/transitionsByEvent" },
|
|
107
|
+
"entry": {
|
|
108
|
+
"type": "array",
|
|
109
|
+
"items": { "$ref": "#/$defs/actionObject" }
|
|
110
|
+
},
|
|
111
|
+
"exit": {
|
|
112
|
+
"type": "array",
|
|
113
|
+
"items": { "$ref": "#/$defs/actionObject" }
|
|
114
|
+
},
|
|
115
|
+
"onDone": { "$ref": "#/$defs/transitionArray" },
|
|
116
|
+
"after": { "$ref": "#/$defs/transitionsByEvent" },
|
|
117
|
+
"always": { "$ref": "#/$defs/transitionArray" },
|
|
118
|
+
"meta": { "$ref": "#/$defs/jsonObject" },
|
|
119
|
+
"output": { "$ref": "#/$defs/jsonValue" },
|
|
120
|
+
"order": { "type": "number" },
|
|
121
|
+
"tags": {
|
|
122
|
+
"type": "array",
|
|
123
|
+
"items": { "type": "string" }
|
|
124
|
+
},
|
|
125
|
+
"description": { "type": "string" },
|
|
126
|
+
"target": { "type": "string" },
|
|
127
|
+
"initial": { "type": "string" }
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"machineConfig": {
|
|
131
|
+
"type": "object",
|
|
132
|
+
"additionalProperties": false,
|
|
133
|
+
"properties": {
|
|
134
|
+
"id": { "type": "string" },
|
|
135
|
+
"type": {
|
|
136
|
+
"enum": ["atomic", "compound", "parallel", "final", "history"]
|
|
137
|
+
},
|
|
138
|
+
"history": {
|
|
139
|
+
"anyOf": [
|
|
140
|
+
{ "enum": ["shallow", "deep"] },
|
|
141
|
+
{ "type": "boolean" }
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
"states": {
|
|
145
|
+
"type": "object",
|
|
146
|
+
"additionalProperties": { "$ref": "#/$defs/stateNodeConfig" }
|
|
147
|
+
},
|
|
148
|
+
"invoke": {
|
|
149
|
+
"type": "array",
|
|
150
|
+
"items": { "$ref": "#/$defs/invokeObject" }
|
|
151
|
+
},
|
|
152
|
+
"on": { "$ref": "#/$defs/transitionsByEvent" },
|
|
153
|
+
"entry": {
|
|
154
|
+
"type": "array",
|
|
155
|
+
"items": { "$ref": "#/$defs/actionObject" }
|
|
156
|
+
},
|
|
157
|
+
"exit": {
|
|
158
|
+
"type": "array",
|
|
159
|
+
"items": { "$ref": "#/$defs/actionObject" }
|
|
160
|
+
},
|
|
161
|
+
"onDone": { "$ref": "#/$defs/transitionArray" },
|
|
162
|
+
"after": { "$ref": "#/$defs/transitionsByEvent" },
|
|
163
|
+
"always": { "$ref": "#/$defs/transitionArray" },
|
|
164
|
+
"meta": { "$ref": "#/$defs/jsonObject" },
|
|
165
|
+
"output": { "$ref": "#/$defs/jsonValue" },
|
|
166
|
+
"order": { "type": "number" },
|
|
167
|
+
"tags": {
|
|
168
|
+
"type": "array",
|
|
169
|
+
"items": { "type": "string" }
|
|
170
|
+
},
|
|
171
|
+
"description": { "type": "string" },
|
|
172
|
+
"target": { "type": "string" },
|
|
173
|
+
"initial": { "type": "string" },
|
|
174
|
+
"schemas": { "$ref": "#/$defs/jsonValue" },
|
|
175
|
+
"version": { "type": "string" },
|
|
176
|
+
"context": { "$ref": "#/$defs/jsonObject" },
|
|
177
|
+
"options": {
|
|
178
|
+
"type": "object",
|
|
179
|
+
"additionalProperties": false,
|
|
180
|
+
"properties": {
|
|
181
|
+
"maxIterations": { "type": "number" }
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
"examples": [
|
|
188
|
+
{
|
|
189
|
+
"id": "trafficLight",
|
|
190
|
+
"initial": "green",
|
|
191
|
+
"states": {
|
|
192
|
+
"green": {
|
|
193
|
+
"tags": ["go"],
|
|
194
|
+
"on": {
|
|
195
|
+
"TIMER": [
|
|
196
|
+
{
|
|
197
|
+
"target": ["yellow"],
|
|
198
|
+
"actions": [{ "type": "trackChange" }]
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
"yellow": {
|
|
204
|
+
"on": {
|
|
205
|
+
"TIMER": [{ "target": ["red"] }]
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"red": {
|
|
209
|
+
"type": "final"
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
}
|