statelyai 0.8.6 → 0.8.8
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 +5 -2
- package/dist/bin.mjs +1 -1
- package/dist/{cli-Dx1dw7Cy.mjs → cli-CTUGfkL5.mjs} +124 -347
- package/dist/index.mjs +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -263,7 +263,10 @@ statelyai open src/checkout.machine.ts
|
|
|
263
263
|
```
|
|
264
264
|
|
|
265
265
|
Saved file changes refresh the editor. Saving visual edits writes them back to
|
|
266
|
-
the source file.
|
|
266
|
+
the source file. Editor sync sends the opened file, its reachable relative
|
|
267
|
+
imports, and ancestor package manifests; unrelated sibling files are excluded.
|
|
268
|
+
The CLI verifies the visual editor protocol before sending source data and
|
|
269
|
+
versions remote Editor Sync requests automatically.
|
|
267
270
|
|
|
268
271
|
Flags:
|
|
269
272
|
|
|
@@ -272,7 +275,7 @@ Flags:
|
|
|
272
275
|
- `--host <host>` sets the local bridge host. Default: `127.0.0.1`.
|
|
273
276
|
- `--port <port>` selects a port. Default: a random available port.
|
|
274
277
|
- `--no-open` starts the bridge without launching a browser.
|
|
275
|
-
- `--debug` logs editor protocol messages.
|
|
278
|
+
- `--debug` logs editor protocol messages with credentials redacted.
|
|
276
279
|
|
|
277
280
|
### `diff`
|
|
278
281
|
|
package/dist/bin.mjs
CHANGED
|
@@ -10,11 +10,16 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
10
10
|
import { promisify } from "node:util";
|
|
11
11
|
import { Args, Command, Flags, flush, handle, run } from "@oclif/core";
|
|
12
12
|
import * as http from "node:http";
|
|
13
|
+
import * as ts from "typescript";
|
|
14
|
+
import { EditorHostSession, StudioApiError, buildAuthorizeUrl, createPkcePair, createRemoteEditorSyncBackend, createStatelyClient, discoverAuthorizationServer, discoverProtectedResource, exchangeCodeForToken, findStatelyPragmaAttachments, getStatelyPragma, refreshToken, registerOAuthClient } from "@statelyai/sdk";
|
|
13
15
|
import { WebSocket, WebSocketServer } from "ws";
|
|
14
16
|
import os from "node:os";
|
|
15
|
-
import { StudioApiError, buildAuthorizeUrl, createPkcePair, createStatelyClient, discoverAuthorizationServer, discoverProtectedResource, exchangeCodeForToken, findStatelyPragmaAttachments, getStatelyPragma, refreshToken, registerOAuthClient } from "@statelyai/sdk";
|
|
16
17
|
import { planSync, pullSync, pushLocalMachineLinks } from "@statelyai/sdk/sync";
|
|
17
18
|
|
|
19
|
+
//#region src/version.ts
|
|
20
|
+
const CLI_VERSION = "0.8.8";
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
18
23
|
//#region src/cliHost.ts
|
|
19
24
|
const DEFAULT_SYNC_MAX_FILES = 150;
|
|
20
25
|
const DEFAULT_SYNC_MAX_BYTES = 2e6;
|
|
@@ -51,289 +56,58 @@ function rawDataToBuffer(data) {
|
|
|
51
56
|
return Buffer.from(data);
|
|
52
57
|
}
|
|
53
58
|
var RemoteEditorSession = class {
|
|
54
|
-
|
|
55
|
-
lastPersistedGraph;
|
|
56
|
-
currentSourceLocations;
|
|
57
|
-
currentFormat;
|
|
58
|
-
editorSyncAccess;
|
|
59
|
-
ready = false;
|
|
60
|
-
pendingMessages = [];
|
|
61
|
-
pendingRetrievals = /* @__PURE__ */ new Map();
|
|
62
|
-
retrieveRequestCount = 0;
|
|
63
|
-
watchedSourceUris = /* @__PURE__ */ new Set();
|
|
64
|
-
selfEditCount = 0;
|
|
65
|
-
watcher;
|
|
59
|
+
session;
|
|
66
60
|
constructor(options, sendMessage) {
|
|
67
61
|
this.options = options;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this.resolveRetrievedSource(msg);
|
|
100
|
-
break;
|
|
101
|
-
case "@statelyai.clipboardRead":
|
|
102
|
-
this.postMessage({
|
|
103
|
-
type: "@statelyai.clipboardReadResponse",
|
|
104
|
-
requestId: msg.requestId,
|
|
105
|
-
text: ""
|
|
106
|
-
});
|
|
107
|
-
break;
|
|
108
|
-
case "@statelyai.error":
|
|
109
|
-
this.handleErrorMessage(msg);
|
|
110
|
-
break;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
async initializeEditor() {
|
|
114
|
-
this.ready = true;
|
|
115
|
-
try {
|
|
116
|
-
const update = await this.parseRootDocument();
|
|
117
|
-
this.currentFormat = update.format;
|
|
118
|
-
this.currentSourceLocations = update.sourceLocations;
|
|
119
|
-
this.editorSyncAccess = update.access;
|
|
120
|
-
this.updateSourceLocations(update.sourceLocations);
|
|
121
|
-
if (this.options.apiKey) this.sendMessage({
|
|
122
|
-
type: "@statelyai.setApiKey",
|
|
123
|
-
apiKey: this.options.apiKey
|
|
124
|
-
});
|
|
125
|
-
this.postMessage({
|
|
126
|
-
type: "@statelyai.init",
|
|
127
|
-
machine: update.machine,
|
|
128
|
-
format: update.format,
|
|
129
|
-
sourceLocations: update.sourceLocations,
|
|
130
|
-
mode: update.access?.readOnly ? "viewing" : "editing",
|
|
131
|
-
readOnly: update.access?.readOnly,
|
|
132
|
-
capabilities: update.access?.capabilities,
|
|
133
|
-
theme: "light",
|
|
134
|
-
unsavedIndicator: { enabled: true },
|
|
135
|
-
leftPanels: [],
|
|
136
|
-
rightPanels: [],
|
|
137
|
-
activePanels: []
|
|
138
|
-
});
|
|
139
|
-
} catch (error) {
|
|
140
|
-
const message = formatError(error, "Failed to initialize the visual editor.");
|
|
141
|
-
this.postMessage({
|
|
142
|
-
type: "@statelyai.error",
|
|
143
|
-
code: "initialization_failed",
|
|
144
|
-
message
|
|
145
|
-
});
|
|
146
|
-
this.showError(message);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
for (const pending of this.pendingMessages) this.sendMessage(pending);
|
|
150
|
-
this.pendingMessages = [];
|
|
151
|
-
}
|
|
152
|
-
async handleSavedDocument(uri) {
|
|
153
|
-
if (uri !== this.options.rootUri && !this.watchedSourceUris.has(uri)) return;
|
|
154
|
-
if (this.selfEditCount > 0) return;
|
|
155
|
-
try {
|
|
156
|
-
const update = await this.parseRootDocument();
|
|
157
|
-
this.currentFormat = update.format;
|
|
158
|
-
this.currentSourceLocations = update.sourceLocations;
|
|
159
|
-
this.editorSyncAccess = update.access ?? this.editorSyncAccess;
|
|
160
|
-
this.updateSourceLocations(update.sourceLocations);
|
|
161
|
-
this.postMessage({
|
|
162
|
-
type: "@statelyai.update",
|
|
163
|
-
machine: update.machine,
|
|
164
|
-
format: update.format,
|
|
165
|
-
sourceLocations: update.sourceLocations
|
|
166
|
-
});
|
|
167
|
-
} catch (error) {
|
|
168
|
-
this.showError(formatError(error, "Failed to read the saved document."));
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
async saveFromEditor(msg) {
|
|
172
|
-
if (this.editorSyncAccess?.readOnly) {
|
|
173
|
-
const message = "Your Stately plan allows read-only editor sync.";
|
|
174
|
-
this.postMessage({
|
|
175
|
-
type: "@statelyai.toast",
|
|
176
|
-
message,
|
|
177
|
-
toastType: "error"
|
|
178
|
-
});
|
|
179
|
-
this.showError(message);
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
const validationErrors = getValidationErrors(msg.validations);
|
|
183
|
-
if (validationErrors.length > 0) {
|
|
184
|
-
const message = formatValidationErrorMessage(validationErrors);
|
|
185
|
-
this.postMessage({
|
|
186
|
-
type: "@statelyai.toast",
|
|
187
|
-
message,
|
|
188
|
-
toastType: "error"
|
|
189
|
-
});
|
|
190
|
-
this.showError(message);
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
this.currentSourceLocations = msg.sourceLocations ?? this.currentSourceLocations;
|
|
194
|
-
this.updateSourceLocations(this.currentSourceLocations);
|
|
195
|
-
try {
|
|
196
|
-
const serialized = await this.getSerializedPayloadForCurrentFormat();
|
|
197
|
-
const documents = await collectSourceDocuments({
|
|
198
|
-
rootFileName: this.options.fileName,
|
|
199
|
-
rootDir: this.options.rootDir,
|
|
200
|
-
extraUris: sourceLocationUris(this.currentSourceLocations)
|
|
201
|
-
});
|
|
202
|
-
const response = await this.postSync("/api/editor-sync/apply", {
|
|
203
|
-
rootUri: this.options.rootUri,
|
|
204
|
-
rootFileName: this.options.fileName,
|
|
205
|
-
rootDir: this.options.rootDir,
|
|
206
|
-
documents,
|
|
207
|
-
machineConfig: msg.machineConfig,
|
|
208
|
-
patches: msg.patches,
|
|
209
|
-
prevGraph: this.lastPersistedGraph ?? this.currentGraph,
|
|
210
|
-
nextGraph: msg.graph,
|
|
211
|
-
sourceLocations: this.currentSourceLocations,
|
|
212
|
-
serialized
|
|
213
|
-
});
|
|
214
|
-
if (response.replacements.length === 0) {
|
|
215
|
-
const message = "Unable to apply Viz changes to the source file automatically.";
|
|
216
|
-
this.postMessage({
|
|
217
|
-
type: "@statelyai.toast",
|
|
218
|
-
message,
|
|
219
|
-
toastType: "error"
|
|
220
|
-
});
|
|
221
|
-
this.showError(message);
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
await this.runWithSelfEdit(async () => {
|
|
225
|
-
await applyFileReplacements(response.replacements, this.options.rootUri);
|
|
226
|
-
});
|
|
227
|
-
this.currentGraph = msg.graph;
|
|
228
|
-
this.lastPersistedGraph = msg.graph;
|
|
229
|
-
} catch (error) {
|
|
230
|
-
const message = formatError(error, "Failed to apply Viz changes.");
|
|
231
|
-
this.postMessage({
|
|
232
|
-
type: "@statelyai.toast",
|
|
233
|
-
message,
|
|
234
|
-
toastType: "error"
|
|
235
|
-
});
|
|
236
|
-
this.showError(message);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
async parseRootDocument() {
|
|
240
|
-
const documents = await collectSourceDocuments({
|
|
241
|
-
rootFileName: this.options.fileName,
|
|
242
|
-
rootDir: this.options.rootDir,
|
|
243
|
-
extraUris: sourceLocationUris(this.currentSourceLocations)
|
|
244
|
-
});
|
|
245
|
-
return this.postSync("/api/editor-sync/parse", {
|
|
246
|
-
rootUri: this.options.rootUri,
|
|
247
|
-
rootFileName: this.options.fileName,
|
|
248
|
-
rootDir: this.options.rootDir,
|
|
249
|
-
documents
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
async postSync(pathname, body) {
|
|
253
|
-
const url = new URL(pathname, normalizedBaseUrl(this.options.editorUrl));
|
|
254
|
-
const headers = { "Content-Type": "application/json" };
|
|
255
|
-
if (this.options.apiKey) headers.Authorization = `Bearer ${this.options.apiKey}`;
|
|
256
|
-
const response = await fetchEditorHost(url, {
|
|
257
|
-
method: "POST",
|
|
258
|
-
headers,
|
|
259
|
-
body: JSON.stringify(body)
|
|
260
|
-
});
|
|
261
|
-
const data = await response.json().catch(() => null);
|
|
262
|
-
if (!response.ok) {
|
|
263
|
-
const message = data && typeof data === "object" && "error" in data && typeof data.error === "string" ? data.error : `HTTP ${response.status}`;
|
|
264
|
-
throw new Error(message);
|
|
265
|
-
}
|
|
266
|
-
return data;
|
|
267
|
-
}
|
|
268
|
-
async getSerializedPayloadForCurrentFormat() {
|
|
269
|
-
const format = this.currentFormat;
|
|
270
|
-
if (!format || format === "xstate") return;
|
|
271
|
-
try {
|
|
272
|
-
const serialized = await this.requestSerialized(format);
|
|
273
|
-
return { [format]: serialized };
|
|
274
|
-
} catch {
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
requestSerialized(format) {
|
|
279
|
-
const requestId = `retrieve-${++this.retrieveRequestCount}`;
|
|
280
|
-
return new Promise((resolve, reject) => {
|
|
281
|
-
this.pendingRetrievals.set(requestId, {
|
|
282
|
-
resolve,
|
|
283
|
-
reject
|
|
284
|
-
});
|
|
285
|
-
this.postMessage({
|
|
286
|
-
type: "@statelyai.retrieve",
|
|
287
|
-
requestId,
|
|
288
|
-
format
|
|
289
|
-
});
|
|
62
|
+
const send = (message) => {
|
|
63
|
+
this.log("send", message.type, message);
|
|
64
|
+
sendMessage(message);
|
|
65
|
+
};
|
|
66
|
+
this.session = new EditorHostSession({
|
|
67
|
+
source: {
|
|
68
|
+
rootUri: options.rootUri,
|
|
69
|
+
rootFileName: options.fileName,
|
|
70
|
+
rootDir: options.rootDir,
|
|
71
|
+
collectDocuments: (extraUris) => collectSourceDocuments({
|
|
72
|
+
rootFileName: options.fileName,
|
|
73
|
+
extraUris: [...extraUris ?? []]
|
|
74
|
+
}),
|
|
75
|
+
applyReplacements: async (replacements, rootUri) => {
|
|
76
|
+
await applyFileReplacements(replacements, rootUri);
|
|
77
|
+
return [...new Set(replacements.map((replacement) => replacement.uri ?? rootUri))];
|
|
78
|
+
},
|
|
79
|
+
watchSavedDocuments: (listener) => watchWorkspace(options.rootDir, listener)
|
|
80
|
+
},
|
|
81
|
+
sync: createRemoteEditorSyncBackend({
|
|
82
|
+
editorUrl: options.editorUrl,
|
|
83
|
+
apiKey: options.apiKey,
|
|
84
|
+
fetch: (input, init) => fetchEditorHost(input instanceof URL ? input : new URL(String(input)), init)
|
|
85
|
+
}),
|
|
86
|
+
send,
|
|
87
|
+
apiKey: options.apiKey,
|
|
88
|
+
client: {
|
|
89
|
+
name: "statelyai",
|
|
90
|
+
version: CLI_VERSION
|
|
91
|
+
},
|
|
92
|
+
showError: (message) => console.error(`Stately Editor: ${message}`)
|
|
290
93
|
});
|
|
291
94
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
this.pendingRetrievals.delete(msg.requestId);
|
|
296
|
-
const serialized = typeof msg.data === "string" ? msg.data : JSON.stringify(msg.data, null, 2);
|
|
297
|
-
pending.resolve(serialized);
|
|
298
|
-
}
|
|
299
|
-
handleErrorMessage(msg) {
|
|
300
|
-
if (msg.requestId) {
|
|
301
|
-
const pending = this.pendingRetrievals.get(msg.requestId);
|
|
302
|
-
if (pending) {
|
|
303
|
-
this.pendingRetrievals.delete(msg.requestId);
|
|
304
|
-
pending.reject(new Error(msg.message));
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
this.showError(msg.message);
|
|
309
|
-
}
|
|
310
|
-
updateSourceLocations(sourceLocations) {
|
|
311
|
-
this.watchedSourceUris.clear();
|
|
312
|
-
for (const location of sourceLocations?.states ?? []) if (location.uri !== this.options.rootUri) this.watchedSourceUris.add(location.uri);
|
|
313
|
-
}
|
|
314
|
-
async runWithSelfEdit(operation) {
|
|
315
|
-
this.selfEditCount++;
|
|
316
|
-
try {
|
|
317
|
-
return await operation();
|
|
318
|
-
} finally {
|
|
319
|
-
this.selfEditCount--;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
postMessage(msg) {
|
|
323
|
-
this.log("send", msg.type, msg);
|
|
324
|
-
if (!this.ready) {
|
|
325
|
-
this.pendingMessages.push(msg);
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
this.sendMessage(msg);
|
|
95
|
+
receiveMessage(message) {
|
|
96
|
+
this.log("recv", message.type, message);
|
|
97
|
+
return this.session.receive(message);
|
|
329
98
|
}
|
|
330
|
-
|
|
331
|
-
|
|
99
|
+
dispose() {
|
|
100
|
+
this.session.dispose();
|
|
332
101
|
}
|
|
333
102
|
log(direction, type, payload) {
|
|
334
|
-
if (this.options.debug) console.error(`[${direction}] ${type}`, payload ?? "");
|
|
103
|
+
if (this.options.debug) console.error(`[${direction}] ${type}`, redactDebugPayload(payload) ?? "");
|
|
335
104
|
}
|
|
336
105
|
};
|
|
106
|
+
function redactDebugPayload(payload) {
|
|
107
|
+
if (Array.isArray(payload)) return payload.map(redactDebugPayload);
|
|
108
|
+
if (!payload || typeof payload !== "object") return payload;
|
|
109
|
+
return Object.fromEntries(Object.entries(payload).map(([key, value]) => [key, /^(?:apiKey|accessToken|refreshToken|token|authorization)$/i.test(key) ? "[REDACTED]" : redactDebugPayload(value)]));
|
|
110
|
+
}
|
|
337
111
|
async function openEditor(options) {
|
|
338
112
|
const fileName = path$1.resolve(options.fileName);
|
|
339
113
|
await fsPromises.access(fileName);
|
|
@@ -395,50 +169,88 @@ async function openEditor(options) {
|
|
|
395
169
|
});
|
|
396
170
|
}
|
|
397
171
|
async function collectSourceDocuments(options) {
|
|
398
|
-
const files = new Set([options.rootFileName]);
|
|
399
172
|
const maxFiles = Number.parseInt(process.env.STATELY_SYNC_MAX_FILES ?? "", 10) || DEFAULT_SYNC_MAX_FILES;
|
|
400
173
|
const maxBytes = Number.parseInt(process.env.STATELY_SYNC_MAX_BYTES ?? "", 10) || DEFAULT_SYNC_MAX_BYTES;
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
const documents = [];
|
|
174
|
+
const documents = /* @__PURE__ */ new Map();
|
|
175
|
+
const queue = [];
|
|
404
176
|
let totalBytes = 0;
|
|
405
|
-
for (const fileName of
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if (entry.name.startsWith(".") || shouldSkipDirectory(entry.name)) continue;
|
|
427
|
-
const fileName = path$1.join(dir, entry.name);
|
|
428
|
-
if (entry.isDirectory()) queue.push(fileName);
|
|
429
|
-
else if (entry.isFile() && isSupportedDocument(fileName)) files.add(fileName);
|
|
177
|
+
for (const fileName of [options.rootFileName, ...(options.extraUris ?? []).map(sourceUriToFileName)]) {
|
|
178
|
+
const document = await openSourceDocument(fileName);
|
|
179
|
+
if (document) addDocument(document);
|
|
180
|
+
}
|
|
181
|
+
let packageDirectory = path$1.dirname(path$1.resolve(options.rootFileName));
|
|
182
|
+
while (true) {
|
|
183
|
+
const packageDocument = await openSourceDocument(path$1.join(packageDirectory, "package.json"));
|
|
184
|
+
if (packageDocument) addDocument(packageDocument);
|
|
185
|
+
const parent = path$1.dirname(packageDirectory);
|
|
186
|
+
if (parent === packageDirectory) break;
|
|
187
|
+
packageDirectory = parent;
|
|
188
|
+
}
|
|
189
|
+
for (let index = 0; index < queue.length; index++) {
|
|
190
|
+
const document = queue[index];
|
|
191
|
+
if (path$1.basename(document.fileName) === "package.json") continue;
|
|
192
|
+
for (const specifier of collectRelativeImportSpecifiers(document.text, document.fileName)) for (const candidate of resolveRelativeImportCandidates(document.fileName, specifier)) {
|
|
193
|
+
if (documents.has(path$1.resolve(candidate))) break;
|
|
194
|
+
const importedDocument = await openSourceDocument(candidate);
|
|
195
|
+
if (!importedDocument) continue;
|
|
196
|
+
addDocument(importedDocument);
|
|
197
|
+
break;
|
|
430
198
|
}
|
|
431
199
|
}
|
|
200
|
+
return [...documents.values()];
|
|
201
|
+
function addDocument(document) {
|
|
202
|
+
const normalizedFileName = path$1.resolve(document.fileName);
|
|
203
|
+
if (documents.has(normalizedFileName)) return;
|
|
204
|
+
if (documents.size >= maxFiles) throw new Error(`Source payload exceeds ${maxFiles} reachable files.`);
|
|
205
|
+
const byteLength = Buffer.byteLength(document.text);
|
|
206
|
+
if (totalBytes + byteLength > maxBytes) throw new Error(`Source payload exceeds ${maxBytes} bytes.`);
|
|
207
|
+
documents.set(normalizedFileName, document);
|
|
208
|
+
queue.push(document);
|
|
209
|
+
totalBytes += byteLength;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async function openSourceDocument(fileName) {
|
|
213
|
+
if (!isSupportedDocument(fileName)) return null;
|
|
214
|
+
const text = await fsPromises.readFile(fileName, "utf8").catch(() => null);
|
|
215
|
+
return text === null ? null : {
|
|
216
|
+
uri: fileNameToUri(fileName),
|
|
217
|
+
fileName,
|
|
218
|
+
text
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function collectRelativeImportSpecifiers(text, fileName) {
|
|
222
|
+
const sourceFile = ts.createSourceFile(fileName, text, ts.ScriptTarget.Latest, true, getScriptKind(fileName));
|
|
223
|
+
const specifiers = [];
|
|
224
|
+
for (const statement of sourceFile.statements) {
|
|
225
|
+
const moduleSpecifier = ts.isImportDeclaration(statement) || ts.isExportDeclaration(statement) ? statement.moduleSpecifier : void 0;
|
|
226
|
+
if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text.startsWith(".")) specifiers.push(moduleSpecifier.text);
|
|
227
|
+
}
|
|
228
|
+
return specifiers;
|
|
432
229
|
}
|
|
433
|
-
|
|
230
|
+
const importExtensions = [
|
|
231
|
+
".ts",
|
|
232
|
+
".tsx",
|
|
233
|
+
".js",
|
|
234
|
+
".jsx",
|
|
235
|
+
".mjs",
|
|
236
|
+
".cjs",
|
|
237
|
+
".mts",
|
|
238
|
+
".cts"
|
|
239
|
+
];
|
|
240
|
+
function resolveRelativeImportCandidates(fromFileName, specifier) {
|
|
241
|
+
const basePath = path$1.resolve(path$1.dirname(fromFileName), specifier);
|
|
242
|
+
if (path$1.extname(basePath)) return [basePath];
|
|
434
243
|
return [
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
244
|
+
basePath,
|
|
245
|
+
...importExtensions.map((extension) => `${basePath}${extension}`),
|
|
246
|
+
...importExtensions.map((extension) => path$1.join(basePath, `index${extension}`))
|
|
247
|
+
];
|
|
248
|
+
}
|
|
249
|
+
function getScriptKind(fileName) {
|
|
250
|
+
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
251
|
+
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
252
|
+
if (/\.(?:c|m)?js$/.test(fileName)) return ts.ScriptKind.JS;
|
|
253
|
+
return ts.ScriptKind.TS;
|
|
442
254
|
}
|
|
443
255
|
function isSupportedDocument(fileName) {
|
|
444
256
|
return supportedDocumentPattern.test(fileName);
|
|
@@ -583,22 +395,6 @@ function openBrowser(url) {
|
|
|
583
395
|
stdio: "ignore"
|
|
584
396
|
}).unref();
|
|
585
397
|
}
|
|
586
|
-
function getValidationErrors(validations) {
|
|
587
|
-
return (validations ?? []).filter((validation) => validation.level === "error");
|
|
588
|
-
}
|
|
589
|
-
function formatValidationErrorMessage(errors) {
|
|
590
|
-
const [firstError] = errors;
|
|
591
|
-
if (!firstError) return "Cannot save Viz changes because the graph has validation errors.";
|
|
592
|
-
if (errors.length === 1) return `Cannot save Viz changes: ${firstError.message}`;
|
|
593
|
-
return `Cannot save Viz changes: ${errors.length} validation errors. First: ${firstError.message}`;
|
|
594
|
-
}
|
|
595
|
-
function sourceLocationUris(sourceLocations) {
|
|
596
|
-
return [
|
|
597
|
-
...sourceLocations?.root ? [sourceLocations.root.uri] : [],
|
|
598
|
-
...(sourceLocations?.states ?? []).map((state) => state.uri),
|
|
599
|
-
...(sourceLocations?.staticValues ?? []).map((value) => value.uri)
|
|
600
|
-
];
|
|
601
|
-
}
|
|
602
398
|
function fileNameToUri(fileName) {
|
|
603
399
|
return pathToFileURL(path$1.resolve(fileName)).toString();
|
|
604
400
|
}
|
|
@@ -624,25 +420,6 @@ function compareReplacementRangesDescending(left, right) {
|
|
|
624
420
|
function normalizedBaseUrl(value) {
|
|
625
421
|
return value.replace(/\/+$/, "");
|
|
626
422
|
}
|
|
627
|
-
function formatError(error, fallback) {
|
|
628
|
-
if (!(error instanceof Error)) return fallback;
|
|
629
|
-
const details = collectErrorDetails(error);
|
|
630
|
-
return details.length > 0 ? `${error.message} (${details.join(" | ")})` : error.message;
|
|
631
|
-
}
|
|
632
|
-
function collectErrorDetails(error) {
|
|
633
|
-
const details = [];
|
|
634
|
-
const seen = /* @__PURE__ */ new Set();
|
|
635
|
-
let current = error;
|
|
636
|
-
while (current && typeof current === "object" && !seen.has(current)) {
|
|
637
|
-
seen.add(current);
|
|
638
|
-
const code = "code" in current && typeof current.code === "string" ? current.code : void 0;
|
|
639
|
-
const message = "message" in current && typeof current.message === "string" ? current.message : void 0;
|
|
640
|
-
if (code && message) details.push(`${code}: ${message}`);
|
|
641
|
-
else if (code) details.push(code);
|
|
642
|
-
current = "cause" in current ? current.cause : void 0;
|
|
643
|
-
}
|
|
644
|
-
return details;
|
|
645
|
-
}
|
|
646
423
|
function escapeAttribute(value) {
|
|
647
424
|
return value.replaceAll("&", "&").replaceAll("\"", """).replaceAll("<", "<").replaceAll(">", ">");
|
|
648
425
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as scanProjectMachines, S as run, T as createStatelyProjectConfig, _ as isFileGitDirty, a as discoverMachinesInSource, b as resolveCredentialStatus, c as formatDiscoveredMachines, d as formatProjectStatus, f as formatStoredCredentialSource, g as initProject, h as inferInitProjectName, i as discoverLinkedPullTargets, l as formatMissingNewMachineDirMessage, m as getEnvCredential, n as buildOAuthLoginStart, o as discoverOAuthLogin, p as getEnvApiKey, r as classifyPushCandidates, s as discoverRemoteProjectMachineTargets, t as COMMANDS, u as formatPlanSummary, v as resolveApiKey, w as scanProjectSources, x as resolveProjectStatus, y as resolveConfiguredPullTargets } from "./cli-
|
|
1
|
+
import { C as scanProjectMachines, S as run, T as createStatelyProjectConfig, _ as isFileGitDirty, a as discoverMachinesInSource, b as resolveCredentialStatus, c as formatDiscoveredMachines, d as formatProjectStatus, f as formatStoredCredentialSource, g as initProject, h as inferInitProjectName, i as discoverLinkedPullTargets, l as formatMissingNewMachineDirMessage, m as getEnvCredential, n as buildOAuthLoginStart, o as discoverOAuthLogin, p as getEnvApiKey, r as classifyPushCandidates, s as discoverRemoteProjectMachineTargets, t as COMMANDS, u as formatPlanSummary, v as resolveApiKey, w as scanProjectSources, x as resolveProjectStatus, y as resolveConfiguredPullTargets } from "./cli-CTUGfkL5.mjs";
|
|
2
2
|
|
|
3
3
|
export { COMMANDS, buildOAuthLoginStart, classifyPushCandidates, createStatelyProjectConfig, discoverLinkedPullTargets, discoverMachinesInSource, discoverOAuthLogin, discoverRemoteProjectMachineTargets, formatDiscoveredMachines, formatMissingNewMachineDirMessage, formatPlanSummary, formatProjectStatus, formatStoredCredentialSource, getEnvApiKey, getEnvCredential, inferInitProjectName, initProject, isFileGitDirty, resolveApiKey, resolveConfiguredPullTargets, resolveCredentialStatus, resolveProjectStatus, run, scanProjectMachines, scanProjectSources };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "statelyai",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.8",
|
|
4
4
|
"description": "Command-line tools for Stately",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@oclif/core": "^4.10.3",
|
|
24
|
+
"typescript": "^5.9.3",
|
|
24
25
|
"ws": "^8.21.0",
|
|
25
|
-
"@statelyai/sdk": "0.
|
|
26
|
+
"@statelyai/sdk": "0.20.0"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
29
|
"@types/ws": "^8.18.1",
|