@walkeros/cli 1.2.0 → 1.4.0-next-1771252576264
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/CHANGELOG.md +28 -0
- package/README.md +2 -1
- package/dist/dev.d.ts +328 -0
- package/dist/dev.js +115 -0
- package/dist/dev.js.map +1 -0
- package/dist/examples/flow-complete.json +2 -0
- package/dist/examples/flow-complete.md +16 -14
- package/dist/index.d.ts +2478 -10
- package/dist/index.js +1216 -290
- package/dist/index.js.map +1 -1
- package/dist/runtime/main.js +134 -12
- package/dist/runtime/main.js.map +1 -1
- package/examples/flow-complete.json +2 -0
- package/examples/flow-complete.md +16 -14
- package/package.json +18 -5
package/dist/index.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import chalk3 from "chalk";
|
|
6
5
|
|
|
7
6
|
// src/version.ts
|
|
8
7
|
import { readFileSync } from "fs";
|
|
@@ -27,29 +26,33 @@ function findPackageJson() {
|
|
|
27
26
|
}
|
|
28
27
|
var VERSION = JSON.parse(findPackageJson()).version;
|
|
29
28
|
|
|
30
|
-
// src/
|
|
31
|
-
import
|
|
32
|
-
import fs8 from "fs-extra";
|
|
33
|
-
import { getPlatform as getPlatform2 } from "@walkeros/core";
|
|
29
|
+
// src/core/banner.ts
|
|
30
|
+
import chalk2 from "chalk";
|
|
34
31
|
|
|
35
32
|
// src/core/logger.ts
|
|
36
33
|
import chalk from "chalk";
|
|
37
34
|
var BRAND_COLOR = "#01b5e2";
|
|
38
35
|
function createLogger(options = {}) {
|
|
39
|
-
const {
|
|
36
|
+
const {
|
|
37
|
+
verbose = false,
|
|
38
|
+
silent = false,
|
|
39
|
+
json = false,
|
|
40
|
+
stderr = false
|
|
41
|
+
} = options;
|
|
40
42
|
const shouldLog = !silent && !json;
|
|
41
43
|
const shouldDebug = verbose && !silent && !json;
|
|
44
|
+
const out = stderr ? console.error : console.log;
|
|
42
45
|
return {
|
|
43
46
|
log: (...args) => {
|
|
44
47
|
if (shouldLog) {
|
|
45
48
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
46
|
-
|
|
49
|
+
out(message);
|
|
47
50
|
}
|
|
48
51
|
},
|
|
49
52
|
brand: (...args) => {
|
|
50
53
|
if (shouldLog) {
|
|
51
54
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
52
|
-
|
|
55
|
+
out(chalk.hex(BRAND_COLOR)(message));
|
|
53
56
|
}
|
|
54
57
|
},
|
|
55
58
|
error: (...args) => {
|
|
@@ -61,43 +64,43 @@ function createLogger(options = {}) {
|
|
|
61
64
|
debug: (...args) => {
|
|
62
65
|
if (shouldDebug) {
|
|
63
66
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
64
|
-
|
|
67
|
+
out(` ${message}`);
|
|
65
68
|
}
|
|
66
69
|
},
|
|
67
70
|
json: (data) => {
|
|
68
71
|
if (!silent) {
|
|
69
|
-
|
|
72
|
+
out(JSON.stringify(data, null, 2));
|
|
70
73
|
}
|
|
71
74
|
},
|
|
72
75
|
// Backward-compatible methods (all use default terminal color per design)
|
|
73
76
|
info: (...args) => {
|
|
74
77
|
if (shouldLog) {
|
|
75
78
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
76
|
-
|
|
79
|
+
out(message);
|
|
77
80
|
}
|
|
78
81
|
},
|
|
79
82
|
success: (...args) => {
|
|
80
83
|
if (shouldLog) {
|
|
81
84
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
82
|
-
|
|
85
|
+
out(message);
|
|
83
86
|
}
|
|
84
87
|
},
|
|
85
88
|
warning: (...args) => {
|
|
86
89
|
if (shouldLog) {
|
|
87
90
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
88
|
-
|
|
91
|
+
out(message);
|
|
89
92
|
}
|
|
90
93
|
},
|
|
91
94
|
warn: (...args) => {
|
|
92
95
|
if (shouldLog) {
|
|
93
96
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
94
|
-
|
|
97
|
+
out(message);
|
|
95
98
|
}
|
|
96
99
|
},
|
|
97
100
|
gray: (...args) => {
|
|
98
101
|
if (shouldLog) {
|
|
99
102
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
100
|
-
|
|
103
|
+
out(message);
|
|
101
104
|
}
|
|
102
105
|
}
|
|
103
106
|
};
|
|
@@ -106,10 +109,25 @@ function createCommandLogger(options) {
|
|
|
106
109
|
return createLogger({
|
|
107
110
|
verbose: options.verbose,
|
|
108
111
|
silent: options.silent ?? false,
|
|
109
|
-
json: options.json
|
|
112
|
+
json: options.json,
|
|
113
|
+
stderr: options.stderr
|
|
110
114
|
});
|
|
111
115
|
}
|
|
112
116
|
|
|
117
|
+
// src/core/banner.ts
|
|
118
|
+
function printBanner(version) {
|
|
119
|
+
const b = chalk2.hex(BRAND_COLOR);
|
|
120
|
+
console.error(`${b(" \u2571\u2571")}`);
|
|
121
|
+
console.error(`${b(" \u2571\u2571 \u2571\u2571")} ${b("walkerOS")}`);
|
|
122
|
+
console.error(`${b("\u2571\u2571 \u2571\u2571 \u2571\u2571")} v${version}`);
|
|
123
|
+
console.error("");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/commands/bundle/index.ts
|
|
127
|
+
import path10 from "path";
|
|
128
|
+
import fs9 from "fs-extra";
|
|
129
|
+
import { getPlatform as getPlatform2 } from "@walkeros/core";
|
|
130
|
+
|
|
113
131
|
// src/core/collector-logger.ts
|
|
114
132
|
function createCollectorLoggerConfig(cliLogger, verbose) {
|
|
115
133
|
return {
|
|
@@ -152,6 +170,18 @@ function createTimer() {
|
|
|
152
170
|
}
|
|
153
171
|
|
|
154
172
|
// src/core/output.ts
|
|
173
|
+
import fs from "fs-extra";
|
|
174
|
+
import path from "path";
|
|
175
|
+
async function writeResult(content, options) {
|
|
176
|
+
if (options.output) {
|
|
177
|
+
const outputPath = path.resolve(options.output);
|
|
178
|
+
await fs.ensureDir(path.dirname(outputPath));
|
|
179
|
+
await fs.writeFile(outputPath, content);
|
|
180
|
+
} else {
|
|
181
|
+
process.stdout.write(content);
|
|
182
|
+
process.stdout.write("\n");
|
|
183
|
+
}
|
|
184
|
+
}
|
|
155
185
|
function createJsonOutput(success, data, error, duration) {
|
|
156
186
|
return {
|
|
157
187
|
success,
|
|
@@ -171,25 +201,107 @@ function formatBytes(bytes) {
|
|
|
171
201
|
}
|
|
172
202
|
|
|
173
203
|
// src/core/tmp.ts
|
|
174
|
-
import
|
|
204
|
+
import path2 from "path";
|
|
175
205
|
var DEFAULT_TMP_ROOT = ".tmp";
|
|
176
206
|
function getTmpPath(tmpDir, ...segments) {
|
|
177
207
|
const root = tmpDir || DEFAULT_TMP_ROOT;
|
|
178
|
-
const absoluteRoot =
|
|
179
|
-
return
|
|
180
|
-
}
|
|
181
|
-
function getDefaultTmpRoot() {
|
|
182
|
-
return DEFAULT_TMP_ROOT;
|
|
208
|
+
const absoluteRoot = path2.isAbsolute(root) ? root : path2.resolve(root);
|
|
209
|
+
return path2.join(absoluteRoot, ...segments);
|
|
183
210
|
}
|
|
184
211
|
|
|
185
212
|
// src/core/asset-resolver.ts
|
|
186
213
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
187
|
-
import { existsSync } from "fs";
|
|
214
|
+
import { existsSync as existsSync2 } from "fs";
|
|
215
|
+
import path4 from "path";
|
|
216
|
+
|
|
217
|
+
// src/config/utils.ts
|
|
218
|
+
import fs2 from "fs-extra";
|
|
188
219
|
import path3 from "path";
|
|
189
220
|
|
|
221
|
+
// src/lib/config-file.ts
|
|
222
|
+
import {
|
|
223
|
+
readFileSync as readFileSync2,
|
|
224
|
+
writeFileSync,
|
|
225
|
+
mkdirSync,
|
|
226
|
+
unlinkSync,
|
|
227
|
+
existsSync
|
|
228
|
+
} from "fs";
|
|
229
|
+
import { join as join2 } from "path";
|
|
230
|
+
import { homedir } from "os";
|
|
231
|
+
function getConfigDir() {
|
|
232
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
233
|
+
const base = xdgConfig || join2(homedir(), ".config");
|
|
234
|
+
return join2(base, "walkeros");
|
|
235
|
+
}
|
|
236
|
+
function getConfigPath() {
|
|
237
|
+
return join2(getConfigDir(), "config.json");
|
|
238
|
+
}
|
|
239
|
+
function readConfig() {
|
|
240
|
+
const configPath = getConfigPath();
|
|
241
|
+
try {
|
|
242
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
243
|
+
return JSON.parse(content);
|
|
244
|
+
} catch {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function writeConfig(config) {
|
|
249
|
+
const dir = getConfigDir();
|
|
250
|
+
mkdirSync(dir, { recursive: true });
|
|
251
|
+
const configPath = getConfigPath();
|
|
252
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
|
|
253
|
+
}
|
|
254
|
+
function deleteConfig() {
|
|
255
|
+
const configPath = getConfigPath();
|
|
256
|
+
if (existsSync(configPath)) {
|
|
257
|
+
unlinkSync(configPath);
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
function resolveToken() {
|
|
263
|
+
const envToken = process.env.WALKEROS_TOKEN;
|
|
264
|
+
if (envToken) return { token: envToken, source: "env" };
|
|
265
|
+
const config = readConfig();
|
|
266
|
+
if (config?.token) return { token: config.token, source: "config" };
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
function resolveAppUrl() {
|
|
270
|
+
const envUrl = process.env.WALKEROS_APP_URL;
|
|
271
|
+
if (envUrl) return envUrl;
|
|
272
|
+
const config = readConfig();
|
|
273
|
+
if (config?.appUrl) return config.appUrl;
|
|
274
|
+
return "https://app.walkeros.io";
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// src/core/auth.ts
|
|
278
|
+
function getToken() {
|
|
279
|
+
const result = resolveToken();
|
|
280
|
+
return result?.token;
|
|
281
|
+
}
|
|
282
|
+
function getAuthHeaders() {
|
|
283
|
+
const token = getToken();
|
|
284
|
+
if (!token) return {};
|
|
285
|
+
return { Authorization: `Bearer ${token}` };
|
|
286
|
+
}
|
|
287
|
+
async function authenticatedFetch(url, init) {
|
|
288
|
+
const authHeaders = getAuthHeaders();
|
|
289
|
+
const existingHeaders = init?.headers instanceof Headers ? Object.fromEntries(init.headers.entries()) : Array.isArray(init?.headers) ? Object.fromEntries(init.headers) : init?.headers ?? {};
|
|
290
|
+
return fetch(url, {
|
|
291
|
+
...init,
|
|
292
|
+
headers: { ...existingHeaders, ...authHeaders }
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
function resolveBaseUrl() {
|
|
296
|
+
return resolveAppUrl();
|
|
297
|
+
}
|
|
298
|
+
function requireProjectId() {
|
|
299
|
+
const projectId = process.env.WALKEROS_PROJECT_ID;
|
|
300
|
+
if (!projectId) throw new Error("WALKEROS_PROJECT_ID not set.");
|
|
301
|
+
return projectId;
|
|
302
|
+
}
|
|
303
|
+
|
|
190
304
|
// src/config/utils.ts
|
|
191
|
-
import fs from "fs-extra";
|
|
192
|
-
import path2 from "path";
|
|
193
305
|
function isUrl(str) {
|
|
194
306
|
try {
|
|
195
307
|
const url = new URL(str);
|
|
@@ -203,7 +315,7 @@ async function downloadFromUrl(url) {
|
|
|
203
315
|
throw new Error(`Invalid URL: ${url}`);
|
|
204
316
|
}
|
|
205
317
|
try {
|
|
206
|
-
const response = await
|
|
318
|
+
const response = await authenticatedFetch(url);
|
|
207
319
|
if (!response.ok) {
|
|
208
320
|
throw new Error(
|
|
209
321
|
`Failed to download ${url}: ${response.status} ${response.statusText}`
|
|
@@ -211,9 +323,9 @@ async function downloadFromUrl(url) {
|
|
|
211
323
|
}
|
|
212
324
|
const content = await response.text();
|
|
213
325
|
const downloadsDir = getTmpPath(void 0, "downloads");
|
|
214
|
-
await
|
|
215
|
-
const tempPath =
|
|
216
|
-
await
|
|
326
|
+
await fs2.ensureDir(downloadsDir);
|
|
327
|
+
const tempPath = path3.join(downloadsDir, "flow.json");
|
|
328
|
+
await fs2.writeFile(tempPath, content, "utf-8");
|
|
217
329
|
return tempPath;
|
|
218
330
|
} catch (error) {
|
|
219
331
|
if (error instanceof Error) {
|
|
@@ -229,13 +341,13 @@ async function loadJsonConfig(configPath) {
|
|
|
229
341
|
absolutePath = await downloadFromUrl(configPath);
|
|
230
342
|
isTemporary = true;
|
|
231
343
|
} else {
|
|
232
|
-
absolutePath =
|
|
233
|
-
if (!await
|
|
344
|
+
absolutePath = path3.resolve(configPath);
|
|
345
|
+
if (!await fs2.pathExists(absolutePath)) {
|
|
234
346
|
throw new Error(`Configuration file not found: ${absolutePath}`);
|
|
235
347
|
}
|
|
236
348
|
}
|
|
237
349
|
try {
|
|
238
|
-
const rawConfig = await
|
|
350
|
+
const rawConfig = await fs2.readJson(absolutePath);
|
|
239
351
|
return rawConfig;
|
|
240
352
|
} catch (error) {
|
|
241
353
|
throw new Error(
|
|
@@ -244,7 +356,7 @@ async function loadJsonConfig(configPath) {
|
|
|
244
356
|
} finally {
|
|
245
357
|
if (isTemporary) {
|
|
246
358
|
try {
|
|
247
|
-
await
|
|
359
|
+
await fs2.remove(absolutePath);
|
|
248
360
|
} catch {
|
|
249
361
|
}
|
|
250
362
|
}
|
|
@@ -266,11 +378,11 @@ async function loadJsonFromSource(source, options) {
|
|
|
266
378
|
try {
|
|
267
379
|
const tempPath = await downloadFromUrl(trimmedSource);
|
|
268
380
|
try {
|
|
269
|
-
const data = await
|
|
381
|
+
const data = await fs2.readJson(tempPath);
|
|
270
382
|
return data;
|
|
271
383
|
} finally {
|
|
272
384
|
try {
|
|
273
|
-
await
|
|
385
|
+
await fs2.remove(tempPath);
|
|
274
386
|
} catch {
|
|
275
387
|
}
|
|
276
388
|
}
|
|
@@ -280,10 +392,10 @@ async function loadJsonFromSource(source, options) {
|
|
|
280
392
|
);
|
|
281
393
|
}
|
|
282
394
|
}
|
|
283
|
-
const resolvedPath =
|
|
284
|
-
if (await
|
|
395
|
+
const resolvedPath = path3.resolve(trimmedSource);
|
|
396
|
+
if (await fs2.pathExists(resolvedPath)) {
|
|
285
397
|
try {
|
|
286
|
-
const data = await
|
|
398
|
+
const data = await fs2.readJson(resolvedPath);
|
|
287
399
|
return data;
|
|
288
400
|
} catch (error) {
|
|
289
401
|
throw new Error(
|
|
@@ -309,15 +421,15 @@ var cachedAssetDir;
|
|
|
309
421
|
function getAssetDir() {
|
|
310
422
|
if (cachedAssetDir) return cachedAssetDir;
|
|
311
423
|
const currentFile = fileURLToPath2(import.meta.url);
|
|
312
|
-
let dir =
|
|
313
|
-
while (dir !==
|
|
314
|
-
if (
|
|
424
|
+
let dir = path4.dirname(currentFile);
|
|
425
|
+
while (dir !== path4.dirname(dir)) {
|
|
426
|
+
if (existsSync2(path4.join(dir, "examples"))) {
|
|
315
427
|
cachedAssetDir = dir;
|
|
316
428
|
return dir;
|
|
317
429
|
}
|
|
318
|
-
dir =
|
|
430
|
+
dir = path4.dirname(dir);
|
|
319
431
|
}
|
|
320
|
-
cachedAssetDir =
|
|
432
|
+
cachedAssetDir = path4.dirname(currentFile);
|
|
321
433
|
return cachedAssetDir;
|
|
322
434
|
}
|
|
323
435
|
function resolveAsset(assetPath, assetType, baseDir) {
|
|
@@ -326,12 +438,12 @@ function resolveAsset(assetPath, assetType, baseDir) {
|
|
|
326
438
|
}
|
|
327
439
|
if (!assetPath.includes("/") && !assetPath.includes("\\")) {
|
|
328
440
|
const assetDir = getAssetDir();
|
|
329
|
-
return
|
|
441
|
+
return path4.join(assetDir, "examples", assetPath);
|
|
330
442
|
}
|
|
331
|
-
if (
|
|
443
|
+
if (path4.isAbsolute(assetPath)) {
|
|
332
444
|
return assetPath;
|
|
333
445
|
}
|
|
334
|
-
return
|
|
446
|
+
return path4.resolve(baseDir || process.cwd(), assetPath);
|
|
335
447
|
}
|
|
336
448
|
|
|
337
449
|
// src/core/utils.ts
|
|
@@ -340,23 +452,23 @@ function getErrorMessage(error) {
|
|
|
340
452
|
}
|
|
341
453
|
|
|
342
454
|
// src/core/local-packages.ts
|
|
343
|
-
import
|
|
344
|
-
import
|
|
455
|
+
import path5 from "path";
|
|
456
|
+
import fs3 from "fs-extra";
|
|
345
457
|
async function resolveLocalPackage(packageName, localPath, configDir, logger2) {
|
|
346
|
-
const absolutePath =
|
|
347
|
-
if (!await
|
|
458
|
+
const absolutePath = path5.isAbsolute(localPath) ? localPath : path5.resolve(configDir, localPath);
|
|
459
|
+
if (!await fs3.pathExists(absolutePath)) {
|
|
348
460
|
throw new Error(
|
|
349
461
|
`Local package path not found: ${localPath} (resolved to ${absolutePath})`
|
|
350
462
|
);
|
|
351
463
|
}
|
|
352
|
-
const pkgJsonPath =
|
|
353
|
-
if (!await
|
|
464
|
+
const pkgJsonPath = path5.join(absolutePath, "package.json");
|
|
465
|
+
if (!await fs3.pathExists(pkgJsonPath)) {
|
|
354
466
|
throw new Error(
|
|
355
467
|
`No package.json found at ${absolutePath}. Is this a valid package directory?`
|
|
356
468
|
);
|
|
357
469
|
}
|
|
358
|
-
const distPath =
|
|
359
|
-
const hasDistFolder = await
|
|
470
|
+
const distPath = path5.join(absolutePath, "dist");
|
|
471
|
+
const hasDistFolder = await fs3.pathExists(distPath);
|
|
360
472
|
if (!hasDistFolder) {
|
|
361
473
|
logger2.warn(
|
|
362
474
|
`\u26A0\uFE0F ${packageName}: No dist/ folder found. Using package root.`
|
|
@@ -370,21 +482,21 @@ async function resolveLocalPackage(packageName, localPath, configDir, logger2) {
|
|
|
370
482
|
};
|
|
371
483
|
}
|
|
372
484
|
async function copyLocalPackage(localPkg, targetDir, logger2) {
|
|
373
|
-
const packageDir =
|
|
374
|
-
await
|
|
375
|
-
await
|
|
376
|
-
|
|
377
|
-
|
|
485
|
+
const packageDir = path5.join(targetDir, "node_modules", localPkg.name);
|
|
486
|
+
await fs3.ensureDir(path5.dirname(packageDir));
|
|
487
|
+
await fs3.copy(
|
|
488
|
+
path5.join(localPkg.absolutePath, "package.json"),
|
|
489
|
+
path5.join(packageDir, "package.json")
|
|
378
490
|
);
|
|
379
491
|
if (localPkg.hasDistFolder) {
|
|
380
|
-
await
|
|
492
|
+
await fs3.copy(localPkg.distPath, path5.join(packageDir, "dist"));
|
|
381
493
|
} else {
|
|
382
|
-
const entries = await
|
|
494
|
+
const entries = await fs3.readdir(localPkg.absolutePath);
|
|
383
495
|
for (const entry of entries) {
|
|
384
496
|
if (!["node_modules", ".turbo", ".git"].includes(entry)) {
|
|
385
|
-
await
|
|
386
|
-
|
|
387
|
-
|
|
497
|
+
await fs3.copy(
|
|
498
|
+
path5.join(localPkg.absolutePath, entry),
|
|
499
|
+
path5.join(packageDir, entry)
|
|
388
500
|
);
|
|
389
501
|
}
|
|
390
502
|
}
|
|
@@ -394,7 +506,7 @@ async function copyLocalPackage(localPkg, targetDir, logger2) {
|
|
|
394
506
|
}
|
|
395
507
|
|
|
396
508
|
// src/core/input-detector.ts
|
|
397
|
-
import
|
|
509
|
+
import fs4 from "fs-extra";
|
|
398
510
|
async function detectInput(inputPath, platformOverride) {
|
|
399
511
|
const content = await loadContent(inputPath);
|
|
400
512
|
try {
|
|
@@ -411,13 +523,29 @@ function detectPlatformFromPath(inputPath) {
|
|
|
411
523
|
}
|
|
412
524
|
async function loadContent(inputPath) {
|
|
413
525
|
if (isUrl(inputPath)) {
|
|
414
|
-
const response = await
|
|
526
|
+
const response = await authenticatedFetch(inputPath);
|
|
415
527
|
if (!response.ok) {
|
|
416
528
|
throw new Error(`Failed to fetch ${inputPath}: ${response.status}`);
|
|
417
529
|
}
|
|
418
530
|
return response.text();
|
|
419
531
|
}
|
|
420
|
-
return
|
|
532
|
+
return fs4.readFile(inputPath, "utf8");
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// src/core/stdin.ts
|
|
536
|
+
function isStdinPiped() {
|
|
537
|
+
return !process.stdin.isTTY;
|
|
538
|
+
}
|
|
539
|
+
async function readStdin() {
|
|
540
|
+
const chunks = [];
|
|
541
|
+
for await (const chunk of process.stdin) {
|
|
542
|
+
chunks.push(chunk);
|
|
543
|
+
}
|
|
544
|
+
const content = Buffer.concat(chunks).toString("utf-8");
|
|
545
|
+
if (!content.trim()) {
|
|
546
|
+
throw new Error("No input received on stdin");
|
|
547
|
+
}
|
|
548
|
+
return content;
|
|
421
549
|
}
|
|
422
550
|
|
|
423
551
|
// src/config/validators.ts
|
|
@@ -430,8 +558,8 @@ function validateFlowSetup(data) {
|
|
|
430
558
|
const result = safeParseSetup(data);
|
|
431
559
|
if (!result.success) {
|
|
432
560
|
const errors = result.error.issues.map((issue) => {
|
|
433
|
-
const
|
|
434
|
-
return ` - ${
|
|
561
|
+
const path15 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
|
|
562
|
+
return ` - ${path15}: ${issue.message}`;
|
|
435
563
|
}).join("\n");
|
|
436
564
|
throw new Error(`Invalid configuration:
|
|
437
565
|
${errors}`);
|
|
@@ -473,8 +601,8 @@ function getDefaultOutput(platform) {
|
|
|
473
601
|
}
|
|
474
602
|
|
|
475
603
|
// src/config/loader.ts
|
|
476
|
-
import
|
|
477
|
-
import
|
|
604
|
+
import path6 from "path";
|
|
605
|
+
import fs5 from "fs-extra";
|
|
478
606
|
import { getFlowConfig, getPlatform } from "@walkeros/core";
|
|
479
607
|
var DEFAULT_INCLUDE_FOLDER = "./shared";
|
|
480
608
|
function loadBundleConfig(rawConfig, options) {
|
|
@@ -491,11 +619,11 @@ function loadBundleConfig(rawConfig, options) {
|
|
|
491
619
|
const buildDefaults = getBuildDefaults(platform);
|
|
492
620
|
const packages = flowConfig.packages || {};
|
|
493
621
|
const output = options.buildOverrides?.output || getDefaultOutput(platform);
|
|
494
|
-
const configDir = isUrl(options.configPath) ? process.cwd() :
|
|
622
|
+
const configDir = isUrl(options.configPath) ? process.cwd() : path6.dirname(options.configPath);
|
|
495
623
|
let includes = setup.include;
|
|
496
624
|
if (!includes) {
|
|
497
|
-
const defaultIncludePath =
|
|
498
|
-
if (
|
|
625
|
+
const defaultIncludePath = path6.resolve(configDir, DEFAULT_INCLUDE_FOLDER);
|
|
626
|
+
if (fs5.pathExistsSync(defaultIncludePath)) {
|
|
499
627
|
includes = [DEFAULT_INCLUDE_FOLDER];
|
|
500
628
|
}
|
|
501
629
|
}
|
|
@@ -561,14 +689,14 @@ async function loadFlowConfig(configPath, options) {
|
|
|
561
689
|
|
|
562
690
|
// src/commands/bundle/bundler.ts
|
|
563
691
|
import esbuild from "esbuild";
|
|
564
|
-
import
|
|
565
|
-
import
|
|
692
|
+
import path9 from "path";
|
|
693
|
+
import fs8 from "fs-extra";
|
|
566
694
|
import { packageNameToVariable } from "@walkeros/core";
|
|
567
695
|
|
|
568
696
|
// src/commands/bundle/package-manager.ts
|
|
569
697
|
import pacote from "pacote";
|
|
570
|
-
import
|
|
571
|
-
import
|
|
698
|
+
import path7 from "path";
|
|
699
|
+
import fs6 from "fs-extra";
|
|
572
700
|
|
|
573
701
|
// src/core/cache-utils.ts
|
|
574
702
|
import { getHashServer } from "@walkeros/server-core";
|
|
@@ -609,16 +737,16 @@ async function withTimeout(promise, ms, errorMessage) {
|
|
|
609
737
|
return Promise.race([promise, timeout]);
|
|
610
738
|
}
|
|
611
739
|
function getPackageDirectory(baseDir, packageName, version) {
|
|
612
|
-
return
|
|
740
|
+
return path7.join(baseDir, "node_modules", packageName);
|
|
613
741
|
}
|
|
614
742
|
async function getCachedPackagePath(pkg, tmpDir) {
|
|
615
743
|
const cacheDir = getTmpPath(tmpDir, "cache", "packages");
|
|
616
744
|
const cacheKey = await getPackageCacheKey(pkg.name, pkg.version);
|
|
617
|
-
return
|
|
745
|
+
return path7.join(cacheDir, cacheKey);
|
|
618
746
|
}
|
|
619
747
|
async function isPackageCached(pkg, tmpDir) {
|
|
620
748
|
const cachedPath = await getCachedPackagePath(pkg, tmpDir);
|
|
621
|
-
return
|
|
749
|
+
return fs6.pathExists(cachedPath);
|
|
622
750
|
}
|
|
623
751
|
function validateNoDuplicatePackages(packages) {
|
|
624
752
|
const packageMap = /* @__PURE__ */ new Map();
|
|
@@ -652,9 +780,9 @@ async function resolveDependencies(pkg, packageDir, logger2, visited = /* @__PUR
|
|
|
652
780
|
}
|
|
653
781
|
visited.add(pkgKey);
|
|
654
782
|
try {
|
|
655
|
-
const packageJsonPath =
|
|
656
|
-
if (await
|
|
657
|
-
const packageJson = await
|
|
783
|
+
const packageJsonPath = path7.join(packageDir, "package.json");
|
|
784
|
+
if (await fs6.pathExists(packageJsonPath)) {
|
|
785
|
+
const packageJson = await fs6.readJson(packageJsonPath);
|
|
658
786
|
const deps = {
|
|
659
787
|
...packageJson.dependencies,
|
|
660
788
|
...packageJson.peerDependencies
|
|
@@ -682,7 +810,7 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
682
810
|
}
|
|
683
811
|
}
|
|
684
812
|
validateNoDuplicatePackages(packages);
|
|
685
|
-
await
|
|
813
|
+
await fs6.ensureDir(targetDir);
|
|
686
814
|
while (downloadQueue.length > 0) {
|
|
687
815
|
const pkg = downloadQueue.shift();
|
|
688
816
|
const pkgKey = `${pkg.name}@${pkg.version}`;
|
|
@@ -719,8 +847,8 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
719
847
|
logger2.debug(`Downloading ${packageSpec} (cached)`);
|
|
720
848
|
}
|
|
721
849
|
try {
|
|
722
|
-
await
|
|
723
|
-
await
|
|
850
|
+
await fs6.ensureDir(path7.dirname(packageDir));
|
|
851
|
+
await fs6.copy(cachedPath, packageDir);
|
|
724
852
|
packagePaths.set(pkg.name, packageDir);
|
|
725
853
|
const deps = await resolveDependencies(pkg, packageDir, logger2);
|
|
726
854
|
for (const dep of deps) {
|
|
@@ -737,7 +865,7 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
737
865
|
}
|
|
738
866
|
}
|
|
739
867
|
try {
|
|
740
|
-
await
|
|
868
|
+
await fs6.ensureDir(path7.dirname(packageDir));
|
|
741
869
|
const cacheDir = process.env.NPM_CACHE_DIR || getTmpPath(void 0, "cache", "npm");
|
|
742
870
|
await withTimeout(
|
|
743
871
|
pacote.extract(packageSpec, packageDir, {
|
|
@@ -754,15 +882,15 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
754
882
|
`Package download timed out after ${PACKAGE_DOWNLOAD_TIMEOUT_MS / 1e3}s: ${packageSpec}`
|
|
755
883
|
);
|
|
756
884
|
if (userSpecifiedPackages.has(pkg.name)) {
|
|
757
|
-
const pkgStats = await
|
|
885
|
+
const pkgStats = await fs6.stat(path7.join(packageDir, "package.json"));
|
|
758
886
|
const pkgJsonSize = pkgStats.size;
|
|
759
887
|
const sizeKB = (pkgJsonSize / 1024).toFixed(1);
|
|
760
888
|
logger2.debug(`Downloading ${packageSpec} (${sizeKB} KB)`);
|
|
761
889
|
}
|
|
762
890
|
if (useCache) {
|
|
763
891
|
try {
|
|
764
|
-
await
|
|
765
|
-
await
|
|
892
|
+
await fs6.ensureDir(path7.dirname(cachedPath));
|
|
893
|
+
await fs6.copy(packageDir, cachedPath);
|
|
766
894
|
} catch (cacheError) {
|
|
767
895
|
}
|
|
768
896
|
}
|
|
@@ -782,26 +910,26 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
782
910
|
}
|
|
783
911
|
|
|
784
912
|
// src/core/build-cache.ts
|
|
785
|
-
import
|
|
786
|
-
import
|
|
913
|
+
import fs7 from "fs-extra";
|
|
914
|
+
import path8 from "path";
|
|
787
915
|
async function getBuildCachePath(configContent, tmpDir) {
|
|
788
916
|
const cacheDir = getTmpPath(tmpDir, "cache", "builds");
|
|
789
917
|
const cacheKey = await getFlowConfigCacheKey(configContent);
|
|
790
|
-
return
|
|
918
|
+
return path8.join(cacheDir, `${cacheKey}.js`);
|
|
791
919
|
}
|
|
792
920
|
async function isBuildCached(configContent, tmpDir) {
|
|
793
921
|
const cachePath = await getBuildCachePath(configContent, tmpDir);
|
|
794
|
-
return
|
|
922
|
+
return fs7.pathExists(cachePath);
|
|
795
923
|
}
|
|
796
924
|
async function cacheBuild(configContent, buildOutput, tmpDir) {
|
|
797
925
|
const cachePath = await getBuildCachePath(configContent, tmpDir);
|
|
798
|
-
await
|
|
799
|
-
await
|
|
926
|
+
await fs7.ensureDir(path8.dirname(cachePath));
|
|
927
|
+
await fs7.writeFile(cachePath, buildOutput, "utf-8");
|
|
800
928
|
}
|
|
801
929
|
async function getCachedBuild(configContent, tmpDir) {
|
|
802
930
|
const cachePath = await getBuildCachePath(configContent, tmpDir);
|
|
803
|
-
if (await
|
|
804
|
-
return await
|
|
931
|
+
if (await fs7.pathExists(cachePath)) {
|
|
932
|
+
return await fs7.readFile(cachePath, "utf-8");
|
|
805
933
|
}
|
|
806
934
|
return null;
|
|
807
935
|
}
|
|
@@ -854,11 +982,11 @@ function generateInlineCode(inline, config, env, chain, chainPropertyName, isDes
|
|
|
854
982
|
}
|
|
855
983
|
async function copyIncludes(includes, sourceDir, outputDir, logger2) {
|
|
856
984
|
for (const include of includes) {
|
|
857
|
-
const sourcePath =
|
|
858
|
-
const folderName =
|
|
859
|
-
const destPath =
|
|
860
|
-
if (await
|
|
861
|
-
await
|
|
985
|
+
const sourcePath = path9.resolve(sourceDir, include);
|
|
986
|
+
const folderName = path9.basename(include);
|
|
987
|
+
const destPath = path9.join(outputDir, folderName);
|
|
988
|
+
if (await fs8.pathExists(sourcePath)) {
|
|
989
|
+
await fs8.copy(sourcePath, destPath);
|
|
862
990
|
logger2.debug(`Copied ${include} to output`);
|
|
863
991
|
} else {
|
|
864
992
|
logger2.debug(`Include folder not found: ${include}`);
|
|
@@ -927,14 +1055,14 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
927
1055
|
const cachedBuild = await getCachedBuild(configContent);
|
|
928
1056
|
if (cachedBuild) {
|
|
929
1057
|
logger2.debug("Using cached build");
|
|
930
|
-
const outputPath =
|
|
931
|
-
await
|
|
932
|
-
await
|
|
933
|
-
const stats = await
|
|
1058
|
+
const outputPath = path9.resolve(buildOptions.output);
|
|
1059
|
+
await fs8.ensureDir(path9.dirname(outputPath));
|
|
1060
|
+
await fs8.writeFile(outputPath, cachedBuild);
|
|
1061
|
+
const stats = await fs8.stat(outputPath);
|
|
934
1062
|
const sizeKB = (stats.size / 1024).toFixed(1);
|
|
935
1063
|
logger2.log(`Output: ${outputPath} (${sizeKB} KB, cached)`);
|
|
936
1064
|
if (showStats) {
|
|
937
|
-
const stats2 = await
|
|
1065
|
+
const stats2 = await fs8.stat(outputPath);
|
|
938
1066
|
const packageStats = Object.entries(buildOptions.packages).map(
|
|
939
1067
|
([name, pkg]) => ({
|
|
940
1068
|
name: `${name}@${pkg.version || "latest"}`,
|
|
@@ -954,7 +1082,7 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
954
1082
|
}
|
|
955
1083
|
}
|
|
956
1084
|
try {
|
|
957
|
-
await
|
|
1085
|
+
await fs8.ensureDir(TEMP_DIR);
|
|
958
1086
|
const hasSourcesOrDests = Object.keys(
|
|
959
1087
|
flowConfig.sources || {}
|
|
960
1088
|
).length > 0 || Object.keys(
|
|
@@ -982,8 +1110,8 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
982
1110
|
);
|
|
983
1111
|
for (const [pkgName, pkgPath] of packagePaths.entries()) {
|
|
984
1112
|
if (pkgName.startsWith("@walkeros/")) {
|
|
985
|
-
const pkgJsonPath =
|
|
986
|
-
const pkgJson = await
|
|
1113
|
+
const pkgJsonPath = path9.join(pkgPath, "package.json");
|
|
1114
|
+
const pkgJson = await fs8.readJSON(pkgJsonPath);
|
|
987
1115
|
if (!pkgJson.exports && pkgJson.module) {
|
|
988
1116
|
pkgJson.exports = {
|
|
989
1117
|
".": {
|
|
@@ -991,12 +1119,12 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
991
1119
|
require: pkgJson.main
|
|
992
1120
|
}
|
|
993
1121
|
};
|
|
994
|
-
await
|
|
1122
|
+
await fs8.writeJSON(pkgJsonPath, pkgJson, { spaces: 2 });
|
|
995
1123
|
}
|
|
996
1124
|
}
|
|
997
1125
|
}
|
|
998
|
-
const packageJsonPath =
|
|
999
|
-
await
|
|
1126
|
+
const packageJsonPath = path9.join(TEMP_DIR, "package.json");
|
|
1127
|
+
await fs8.writeFile(
|
|
1000
1128
|
packageJsonPath,
|
|
1001
1129
|
JSON.stringify({ type: "module" }, null, 2)
|
|
1002
1130
|
);
|
|
@@ -1006,13 +1134,13 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1006
1134
|
buildOptions,
|
|
1007
1135
|
packagePaths
|
|
1008
1136
|
);
|
|
1009
|
-
const entryPath =
|
|
1010
|
-
await
|
|
1137
|
+
const entryPath = path9.join(TEMP_DIR, "entry.js");
|
|
1138
|
+
await fs8.writeFile(entryPath, entryContent);
|
|
1011
1139
|
logger2.debug(
|
|
1012
1140
|
`Running esbuild (target: ${buildOptions.target || "es2018"}, format: ${buildOptions.format})`
|
|
1013
1141
|
);
|
|
1014
|
-
const outputPath =
|
|
1015
|
-
await
|
|
1142
|
+
const outputPath = path9.resolve(buildOptions.output);
|
|
1143
|
+
await fs8.ensureDir(path9.dirname(outputPath));
|
|
1016
1144
|
const esbuildOptions = createEsbuildOptions(
|
|
1017
1145
|
buildOptions,
|
|
1018
1146
|
entryPath,
|
|
@@ -1031,13 +1159,13 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1031
1159
|
} finally {
|
|
1032
1160
|
await esbuild.stop();
|
|
1033
1161
|
}
|
|
1034
|
-
const outputStats = await
|
|
1162
|
+
const outputStats = await fs8.stat(outputPath);
|
|
1035
1163
|
const sizeKB = (outputStats.size / 1024).toFixed(1);
|
|
1036
1164
|
const buildTime = ((Date.now() - bundleStartTime) / 1e3).toFixed(1);
|
|
1037
1165
|
logger2.log(`Output: ${outputPath} (${sizeKB} KB, ${buildTime}s)`);
|
|
1038
1166
|
if (buildOptions.cache !== false) {
|
|
1039
1167
|
const configContent = generateCacheKeyContent(flowConfig, buildOptions);
|
|
1040
|
-
const buildOutput = await
|
|
1168
|
+
const buildOutput = await fs8.readFile(outputPath, "utf-8");
|
|
1041
1169
|
await cacheBuild(configContent, buildOutput);
|
|
1042
1170
|
logger2.debug("Build cached for future use");
|
|
1043
1171
|
}
|
|
@@ -1051,7 +1179,7 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1051
1179
|
);
|
|
1052
1180
|
}
|
|
1053
1181
|
if (buildOptions.include && buildOptions.include.length > 0) {
|
|
1054
|
-
const outputDir =
|
|
1182
|
+
const outputDir = path9.dirname(outputPath);
|
|
1055
1183
|
await copyIncludes(
|
|
1056
1184
|
buildOptions.include,
|
|
1057
1185
|
buildOptions.configDir || process.cwd(),
|
|
@@ -1065,7 +1193,7 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1065
1193
|
}
|
|
1066
1194
|
}
|
|
1067
1195
|
async function collectBundleStats(outputPath, packages, startTime, entryContent) {
|
|
1068
|
-
const stats = await
|
|
1196
|
+
const stats = await fs8.stat(outputPath);
|
|
1069
1197
|
const totalSize = stats.size;
|
|
1070
1198
|
const buildTime = Date.now() - startTime;
|
|
1071
1199
|
const packageStats = Object.entries(packages).map(([name, pkg]) => {
|
|
@@ -1576,17 +1704,62 @@ Package Breakdown:`);
|
|
|
1576
1704
|
logger2.info("\u2500".repeat(50));
|
|
1577
1705
|
}
|
|
1578
1706
|
|
|
1707
|
+
// src/core/api-client.ts
|
|
1708
|
+
import createClient from "openapi-fetch";
|
|
1709
|
+
function createApiClient() {
|
|
1710
|
+
const token = getToken();
|
|
1711
|
+
if (!token) throw new Error("WALKEROS_TOKEN not set.");
|
|
1712
|
+
return createClient({
|
|
1713
|
+
baseUrl: resolveBaseUrl(),
|
|
1714
|
+
headers: {
|
|
1715
|
+
Authorization: `Bearer ${token}`,
|
|
1716
|
+
"Content-Type": "application/json"
|
|
1717
|
+
}
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1579
1721
|
// src/commands/bundle/index.ts
|
|
1722
|
+
function resolveOutputPath(output, buildOptions) {
|
|
1723
|
+
const resolved = path10.resolve(output);
|
|
1724
|
+
const ext = path10.extname(resolved);
|
|
1725
|
+
if (output.endsWith("/") || output.endsWith(path10.sep) || !ext) {
|
|
1726
|
+
const filename = buildOptions.platform === "browser" ? "walker.js" : "bundle.mjs";
|
|
1727
|
+
return path10.join(resolved, filename);
|
|
1728
|
+
}
|
|
1729
|
+
return resolved;
|
|
1730
|
+
}
|
|
1580
1731
|
async function bundleCommand(options) {
|
|
1581
1732
|
const timer = createTimer();
|
|
1582
1733
|
timer.start();
|
|
1583
|
-
const
|
|
1734
|
+
const writingToStdout = !options.output;
|
|
1735
|
+
const logger2 = createCommandLogger({
|
|
1736
|
+
...options,
|
|
1737
|
+
stderr: writingToStdout
|
|
1738
|
+
});
|
|
1584
1739
|
try {
|
|
1585
1740
|
if (options.flow && options.all) {
|
|
1586
1741
|
throw new Error("Cannot use both --flow and --all flags together");
|
|
1587
1742
|
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1743
|
+
if (options.all && writingToStdout) {
|
|
1744
|
+
throw new Error(
|
|
1745
|
+
"Cannot use --all without --output (multiple bundles need file output)"
|
|
1746
|
+
);
|
|
1747
|
+
}
|
|
1748
|
+
let rawConfig;
|
|
1749
|
+
let configPath;
|
|
1750
|
+
if (isStdinPiped() && !options.config) {
|
|
1751
|
+
const stdinContent = await readStdin();
|
|
1752
|
+
try {
|
|
1753
|
+
rawConfig = JSON.parse(stdinContent);
|
|
1754
|
+
} catch {
|
|
1755
|
+
throw new Error("Invalid JSON received on stdin");
|
|
1756
|
+
}
|
|
1757
|
+
configPath = path10.resolve(process.cwd(), "stdin.config.json");
|
|
1758
|
+
} else {
|
|
1759
|
+
const file = options.config || "bundle.config.json";
|
|
1760
|
+
configPath = resolveAsset(file, "config");
|
|
1761
|
+
rawConfig = await loadJsonConfig(configPath);
|
|
1762
|
+
}
|
|
1590
1763
|
const configsToBundle = options.all ? loadAllFlows(rawConfig, { configPath, logger: logger2 }) : [
|
|
1591
1764
|
loadBundleConfig(rawConfig, {
|
|
1592
1765
|
configPath,
|
|
@@ -1605,11 +1778,16 @@ async function bundleCommand(options) {
|
|
|
1605
1778
|
if (options.cache !== void 0) {
|
|
1606
1779
|
buildOptions.cache = options.cache;
|
|
1607
1780
|
}
|
|
1608
|
-
|
|
1781
|
+
if (options.output) {
|
|
1782
|
+
buildOptions.output = resolveOutputPath(options.output, buildOptions);
|
|
1783
|
+
} else {
|
|
1784
|
+
const ext = buildOptions.platform === "browser" ? ".js" : ".mjs";
|
|
1785
|
+
buildOptions.output = getTmpPath(void 0, "stdout-bundle" + ext);
|
|
1786
|
+
}
|
|
1609
1787
|
if (isMultiFlow || options.all) {
|
|
1610
|
-
logger2.log(`Bundling
|
|
1788
|
+
logger2.log(`Bundling flow: ${flowName}...`);
|
|
1611
1789
|
} else {
|
|
1612
|
-
logger2.log(
|
|
1790
|
+
logger2.log("Bundling...");
|
|
1613
1791
|
}
|
|
1614
1792
|
const shouldCollectStats = options.stats || options.json;
|
|
1615
1793
|
const stats = await bundleCore(
|
|
@@ -1618,29 +1796,25 @@ async function bundleCommand(options) {
|
|
|
1618
1796
|
logger2,
|
|
1619
1797
|
shouldCollectStats
|
|
1620
1798
|
);
|
|
1621
|
-
results.push({
|
|
1622
|
-
flowName,
|
|
1623
|
-
success: true,
|
|
1624
|
-
stats
|
|
1625
|
-
});
|
|
1799
|
+
results.push({ flowName, success: true, stats });
|
|
1626
1800
|
if (!options.json && !options.all && options.stats && stats) {
|
|
1627
1801
|
displayStats(stats, logger2);
|
|
1628
1802
|
}
|
|
1629
|
-
if (
|
|
1803
|
+
if (writingToStdout && !options.json) {
|
|
1804
|
+
const bundleContent = await fs9.readFile(buildOptions.output);
|
|
1805
|
+
await writeResult(bundleContent, {});
|
|
1806
|
+
}
|
|
1807
|
+
if (options.dockerfile && options.output) {
|
|
1630
1808
|
const platform = getPlatform2(flowConfig);
|
|
1631
1809
|
if (platform) {
|
|
1632
|
-
const outputDir =
|
|
1810
|
+
const outputDir = path10.dirname(buildOptions.output);
|
|
1633
1811
|
const customFile = typeof options.dockerfile === "string" ? options.dockerfile : void 0;
|
|
1634
1812
|
await generateDockerfile(outputDir, platform, logger2, customFile);
|
|
1635
1813
|
}
|
|
1636
1814
|
}
|
|
1637
1815
|
} catch (error) {
|
|
1638
1816
|
const errorMessage = getErrorMessage(error);
|
|
1639
|
-
results.push({
|
|
1640
|
-
flowName,
|
|
1641
|
-
success: false,
|
|
1642
|
-
error: errorMessage
|
|
1643
|
-
});
|
|
1817
|
+
results.push({ flowName, success: false, error: errorMessage });
|
|
1644
1818
|
if (!options.all) {
|
|
1645
1819
|
throw error;
|
|
1646
1820
|
}
|
|
@@ -1650,7 +1824,7 @@ async function bundleCommand(options) {
|
|
|
1650
1824
|
const successCount = results.filter((r) => r.success).length;
|
|
1651
1825
|
const failureCount = results.filter((r) => !r.success).length;
|
|
1652
1826
|
if (options.json) {
|
|
1653
|
-
const
|
|
1827
|
+
const jsonResult = failureCount === 0 ? createSuccessOutput(
|
|
1654
1828
|
{
|
|
1655
1829
|
flows: results,
|
|
1656
1830
|
summary: {
|
|
@@ -1664,7 +1838,9 @@ async function bundleCommand(options) {
|
|
|
1664
1838
|
`${failureCount} flow(s) failed to build`,
|
|
1665
1839
|
duration
|
|
1666
1840
|
);
|
|
1667
|
-
|
|
1841
|
+
await writeResult(JSON.stringify(jsonResult, null, 2) + "\n", {
|
|
1842
|
+
output: options.output
|
|
1843
|
+
});
|
|
1668
1844
|
} else {
|
|
1669
1845
|
if (options.all) {
|
|
1670
1846
|
logger2.log(
|
|
@@ -1684,8 +1860,10 @@ Build Summary: ${successCount}/${results.length} succeeded`
|
|
|
1684
1860
|
const duration = timer.getElapsed() / 1e3;
|
|
1685
1861
|
const errorMessage = getErrorMessage(error);
|
|
1686
1862
|
if (options.json) {
|
|
1687
|
-
const
|
|
1688
|
-
|
|
1863
|
+
const jsonError = createErrorOutput(errorMessage, duration);
|
|
1864
|
+
await writeResult(JSON.stringify(jsonError, null, 2) + "\n", {
|
|
1865
|
+
output: options.output
|
|
1866
|
+
});
|
|
1689
1867
|
} else {
|
|
1690
1868
|
logger2.error(`Error: ${errorMessage}`);
|
|
1691
1869
|
}
|
|
@@ -1694,7 +1872,7 @@ Build Summary: ${successCount}/${results.length} succeeded`
|
|
|
1694
1872
|
}
|
|
1695
1873
|
async function bundle(configOrPath, options = {}) {
|
|
1696
1874
|
let rawConfig;
|
|
1697
|
-
let configPath =
|
|
1875
|
+
let configPath = path10.resolve(process.cwd(), "walkeros.config.json");
|
|
1698
1876
|
if (typeof configOrPath === "string") {
|
|
1699
1877
|
configPath = resolveAsset(configOrPath, "config");
|
|
1700
1878
|
rawConfig = await loadJsonConfig(configPath);
|
|
@@ -1718,9 +1896,9 @@ async function bundle(configOrPath, options = {}) {
|
|
|
1718
1896
|
);
|
|
1719
1897
|
}
|
|
1720
1898
|
async function generateDockerfile(outputDir, platform, logger2, customFile) {
|
|
1721
|
-
const destPath =
|
|
1722
|
-
if (customFile && await
|
|
1723
|
-
await
|
|
1899
|
+
const destPath = path10.join(outputDir, "Dockerfile");
|
|
1900
|
+
if (customFile && await fs9.pathExists(customFile)) {
|
|
1901
|
+
await fs9.copy(customFile, destPath);
|
|
1724
1902
|
logger2.log(`Dockerfile: ${destPath} (copied from ${customFile})`);
|
|
1725
1903
|
return;
|
|
1726
1904
|
}
|
|
@@ -1737,13 +1915,29 @@ ENV BUNDLE=/app/flow/${bundleFile}
|
|
|
1737
1915
|
|
|
1738
1916
|
EXPOSE 8080
|
|
1739
1917
|
`;
|
|
1740
|
-
await
|
|
1918
|
+
await fs9.writeFile(destPath, dockerfile);
|
|
1741
1919
|
logger2.log(`Dockerfile: ${destPath}`);
|
|
1742
1920
|
}
|
|
1921
|
+
async function bundleRemote(options) {
|
|
1922
|
+
const client = createApiClient();
|
|
1923
|
+
const { data, error, response } = await client.POST("/api/bundle", {
|
|
1924
|
+
body: { flow: options.content },
|
|
1925
|
+
parseAs: "text"
|
|
1926
|
+
});
|
|
1927
|
+
if (error)
|
|
1928
|
+
throw new Error(typeof error === "string" ? error : "Bundle failed");
|
|
1929
|
+
const js = data;
|
|
1930
|
+
const statsHeader = response.headers.get("X-Bundle-Stats");
|
|
1931
|
+
return {
|
|
1932
|
+
bundle: js,
|
|
1933
|
+
size: js.length,
|
|
1934
|
+
stats: statsHeader ? JSON.parse(statsHeader) : void 0
|
|
1935
|
+
};
|
|
1936
|
+
}
|
|
1743
1937
|
|
|
1744
1938
|
// src/commands/simulate/simulator.ts
|
|
1745
|
-
import
|
|
1746
|
-
import
|
|
1939
|
+
import path11 from "path";
|
|
1940
|
+
import fs11 from "fs-extra";
|
|
1747
1941
|
import { getPlatform as getPlatform3 } from "@walkeros/core";
|
|
1748
1942
|
|
|
1749
1943
|
// src/commands/simulate/tracker.ts
|
|
@@ -1780,9 +1974,9 @@ var CallTracker = class {
|
|
|
1780
1974
|
}
|
|
1781
1975
|
for (const fullPath of paths) {
|
|
1782
1976
|
const [destKey, ...pathParts] = fullPath.split(":");
|
|
1783
|
-
const
|
|
1784
|
-
if (!
|
|
1785
|
-
const cleanPath =
|
|
1977
|
+
const path15 = pathParts.join(":");
|
|
1978
|
+
if (!path15) continue;
|
|
1979
|
+
const cleanPath = path15.replace(/^call:/, "");
|
|
1786
1980
|
const parts = cleanPath.split(".");
|
|
1787
1981
|
let current = wrapped;
|
|
1788
1982
|
let source = env;
|
|
@@ -1826,7 +2020,7 @@ var CallTracker = class {
|
|
|
1826
2020
|
|
|
1827
2021
|
// src/commands/simulate/jsdom-executor.ts
|
|
1828
2022
|
import { JSDOM, VirtualConsole } from "jsdom";
|
|
1829
|
-
import
|
|
2023
|
+
import fs10 from "fs-extra";
|
|
1830
2024
|
function buildSandboxFromEnvs(envs, destinations, tracker) {
|
|
1831
2025
|
const baseBrowserMocks = {
|
|
1832
2026
|
Image: class MockImage {
|
|
@@ -1895,7 +2089,7 @@ async function executeInJSDOM(bundlePath, destinations, event, tracker, envs, ti
|
|
|
1895
2089
|
const sandbox = buildSandboxFromEnvs(envs, destinations, tracker);
|
|
1896
2090
|
Object.assign(window, sandbox.window);
|
|
1897
2091
|
Object.assign(window.document, sandbox.document);
|
|
1898
|
-
const bundleCode = await
|
|
2092
|
+
const bundleCode = await fs10.readFile(bundlePath, "utf8");
|
|
1899
2093
|
try {
|
|
1900
2094
|
window.eval(bundleCode);
|
|
1901
2095
|
} catch (error) {
|
|
@@ -2089,7 +2283,7 @@ async function executeSimulation(event, inputPath, platformOverride, options = {
|
|
|
2089
2283
|
const tempDir = getTmpPath();
|
|
2090
2284
|
const collectorLoggerConfig = options.logger ? createCollectorLoggerConfig(options.logger, options.verbose) : void 0;
|
|
2091
2285
|
try {
|
|
2092
|
-
await
|
|
2286
|
+
await fs11.ensureDir(tempDir);
|
|
2093
2287
|
const detected = await detectInput(inputPath, platformOverride);
|
|
2094
2288
|
if (!isObject(event) || !("name" in event) || typeof event.name !== "string") {
|
|
2095
2289
|
throw new Error(
|
|
@@ -2126,7 +2320,7 @@ async function executeSimulation(event, inputPath, platformOverride, options = {
|
|
|
2126
2320
|
};
|
|
2127
2321
|
} finally {
|
|
2128
2322
|
if (tempDir) {
|
|
2129
|
-
await
|
|
2323
|
+
await fs11.remove(tempDir).catch(() => {
|
|
2130
2324
|
});
|
|
2131
2325
|
}
|
|
2132
2326
|
}
|
|
@@ -2137,7 +2331,7 @@ async function executeConfigSimulation(_content, configPath, typedEvent, tempDir
|
|
|
2137
2331
|
});
|
|
2138
2332
|
const platform = getPlatform3(flowConfig);
|
|
2139
2333
|
const tracker = new CallTracker();
|
|
2140
|
-
const tempOutput =
|
|
2334
|
+
const tempOutput = path11.join(
|
|
2141
2335
|
tempDir,
|
|
2142
2336
|
`simulation-bundle-${generateId()}.${platform === "web" ? "js" : "mjs"}`
|
|
2143
2337
|
);
|
|
@@ -2195,11 +2389,11 @@ async function executeConfigSimulation(_content, configPath, typedEvent, tempDir
|
|
|
2195
2389
|
};
|
|
2196
2390
|
}
|
|
2197
2391
|
async function executeBundleSimulation(bundleContent, platform, typedEvent, tempDir, startTime, loggerConfig2) {
|
|
2198
|
-
const tempOutput =
|
|
2392
|
+
const tempOutput = path11.join(
|
|
2199
2393
|
tempDir,
|
|
2200
2394
|
`bundle-${generateId()}.${platform === "server" ? "mjs" : "js"}`
|
|
2201
2395
|
);
|
|
2202
|
-
await
|
|
2396
|
+
await fs11.writeFile(tempOutput, bundleContent, "utf8");
|
|
2203
2397
|
const tracker = new CallTracker();
|
|
2204
2398
|
let result;
|
|
2205
2399
|
if (platform === "web") {
|
|
@@ -2234,13 +2428,25 @@ async function executeBundleSimulation(bundleContent, platform, typedEvent, temp
|
|
|
2234
2428
|
|
|
2235
2429
|
// src/commands/simulate/index.ts
|
|
2236
2430
|
async function simulateCommand(options) {
|
|
2237
|
-
const logger2 = createCommandLogger(options);
|
|
2431
|
+
const logger2 = createCommandLogger({ ...options, stderr: true });
|
|
2238
2432
|
const startTime = Date.now();
|
|
2239
2433
|
try {
|
|
2434
|
+
let config;
|
|
2435
|
+
if (isStdinPiped() && !options.config) {
|
|
2436
|
+
const stdinContent = await readStdin();
|
|
2437
|
+
const fs15 = await import("fs-extra");
|
|
2438
|
+
const path15 = await import("path");
|
|
2439
|
+
const tmpPath = path15.default.resolve(".tmp", "stdin-simulate.json");
|
|
2440
|
+
await fs15.default.ensureDir(path15.default.dirname(tmpPath));
|
|
2441
|
+
await fs15.default.writeFile(tmpPath, stdinContent, "utf-8");
|
|
2442
|
+
config = tmpPath;
|
|
2443
|
+
} else {
|
|
2444
|
+
config = options.config || "bundle.config.json";
|
|
2445
|
+
}
|
|
2240
2446
|
const event = await loadJsonFromSource(options.event, {
|
|
2241
2447
|
name: "event"
|
|
2242
2448
|
});
|
|
2243
|
-
const result = await simulateCore(
|
|
2449
|
+
const result = await simulateCore(config, event, {
|
|
2244
2450
|
flow: options.flow,
|
|
2245
2451
|
json: options.json,
|
|
2246
2452
|
verbose: options.verbose,
|
|
@@ -2250,23 +2456,24 @@ async function simulateCommand(options) {
|
|
|
2250
2456
|
...result,
|
|
2251
2457
|
duration: (Date.now() - startTime) / 1e3
|
|
2252
2458
|
};
|
|
2253
|
-
const
|
|
2459
|
+
const formatted = formatSimulationResult(resultWithDuration, {
|
|
2254
2460
|
json: options.json
|
|
2255
2461
|
});
|
|
2256
|
-
|
|
2257
|
-
console.log(output);
|
|
2258
|
-
} else {
|
|
2259
|
-
logger2.log(output);
|
|
2260
|
-
}
|
|
2462
|
+
await writeResult(formatted + "\n", { output: options.output });
|
|
2261
2463
|
process.exit(result.success ? 0 : 1);
|
|
2262
2464
|
} catch (error) {
|
|
2263
2465
|
const errorMessage = getErrorMessage(error);
|
|
2264
2466
|
if (options.json) {
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2467
|
+
const errorOutput = JSON.stringify(
|
|
2468
|
+
{
|
|
2469
|
+
success: false,
|
|
2470
|
+
error: errorMessage,
|
|
2471
|
+
duration: (Date.now() - startTime) / 1e3
|
|
2472
|
+
},
|
|
2473
|
+
null,
|
|
2474
|
+
2
|
|
2475
|
+
);
|
|
2476
|
+
await writeResult(errorOutput + "\n", { output: options.output });
|
|
2270
2477
|
} else {
|
|
2271
2478
|
logger2.error(`Error: ${errorMessage}`);
|
|
2272
2479
|
}
|
|
@@ -2281,28 +2488,33 @@ async function simulate(configOrPath, event, options = {}) {
|
|
|
2281
2488
|
}
|
|
2282
2489
|
return await simulateCore(configOrPath, event, {
|
|
2283
2490
|
json: options.json ?? false,
|
|
2284
|
-
verbose: options.verbose ?? false
|
|
2491
|
+
verbose: options.verbose ?? false,
|
|
2492
|
+
flow: options.flow,
|
|
2493
|
+
platform: options.platform
|
|
2285
2494
|
});
|
|
2286
2495
|
}
|
|
2287
2496
|
|
|
2288
2497
|
// src/commands/push/index.ts
|
|
2289
|
-
import
|
|
2498
|
+
import path12 from "path";
|
|
2290
2499
|
import { JSDOM as JSDOM2, VirtualConsole as VirtualConsole2 } from "jsdom";
|
|
2291
|
-
import
|
|
2500
|
+
import fs12 from "fs-extra";
|
|
2292
2501
|
import {
|
|
2293
2502
|
getPlatform as getPlatform4
|
|
2294
2503
|
} from "@walkeros/core";
|
|
2295
2504
|
import { schemas as schemas2 } from "@walkeros/core/dev";
|
|
2296
|
-
async function
|
|
2297
|
-
const logger2 = createCommandLogger(
|
|
2505
|
+
async function pushCore(inputPath, event, options = {}) {
|
|
2506
|
+
const logger2 = createCommandLogger({
|
|
2507
|
+
silent: options.silent,
|
|
2508
|
+
verbose: options.verbose
|
|
2509
|
+
});
|
|
2298
2510
|
const startTime = Date.now();
|
|
2299
2511
|
let tempDir;
|
|
2300
2512
|
try {
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
name: "event"
|
|
2304
|
-
}
|
|
2305
|
-
const eventResult = schemas2.PartialEventSchema.safeParse(
|
|
2513
|
+
let loadedEvent = event;
|
|
2514
|
+
if (typeof event === "string") {
|
|
2515
|
+
loadedEvent = await loadJsonFromSource(event, { name: "event" });
|
|
2516
|
+
}
|
|
2517
|
+
const eventResult = schemas2.PartialEventSchema.safeParse(loadedEvent);
|
|
2306
2518
|
if (!eventResult.success) {
|
|
2307
2519
|
const errors = eventResult.error.issues.map((issue) => `${String(issue.path.join("."))}: ${issue.message}`).join(", ");
|
|
2308
2520
|
throw new Error(`Invalid event: ${errors}`);
|
|
@@ -2321,11 +2533,18 @@ async function pushCommand(options) {
|
|
|
2321
2533
|
);
|
|
2322
2534
|
}
|
|
2323
2535
|
logger2.debug("Detecting input type");
|
|
2324
|
-
const detected = await detectInput(
|
|
2536
|
+
const detected = await detectInput(
|
|
2537
|
+
inputPath,
|
|
2538
|
+
options.platform
|
|
2539
|
+
);
|
|
2325
2540
|
let result;
|
|
2326
2541
|
if (detected.type === "config") {
|
|
2327
2542
|
result = await executeConfigPush(
|
|
2328
|
-
|
|
2543
|
+
{
|
|
2544
|
+
config: inputPath,
|
|
2545
|
+
flow: options.flow,
|
|
2546
|
+
verbose: options.verbose
|
|
2547
|
+
},
|
|
2329
2548
|
validatedEvent,
|
|
2330
2549
|
logger2,
|
|
2331
2550
|
(dir) => {
|
|
@@ -2348,55 +2567,104 @@ async function pushCommand(options) {
|
|
|
2348
2567
|
{ logger: collectorLoggerConfig }
|
|
2349
2568
|
);
|
|
2350
2569
|
}
|
|
2570
|
+
return result;
|
|
2571
|
+
} catch (error) {
|
|
2572
|
+
return {
|
|
2573
|
+
success: false,
|
|
2574
|
+
duration: Date.now() - startTime,
|
|
2575
|
+
error: getErrorMessage(error)
|
|
2576
|
+
};
|
|
2577
|
+
} finally {
|
|
2578
|
+
if (tempDir) {
|
|
2579
|
+
await fs12.remove(tempDir).catch(() => {
|
|
2580
|
+
});
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
async function pushCommand(options) {
|
|
2585
|
+
const logger2 = createCommandLogger({ ...options, stderr: true });
|
|
2586
|
+
const startTime = Date.now();
|
|
2587
|
+
try {
|
|
2588
|
+
let config;
|
|
2589
|
+
if (isStdinPiped() && !options.config) {
|
|
2590
|
+
const stdinContent = await readStdin();
|
|
2591
|
+
const tmpPath = path12.resolve(".tmp", "stdin-push.json");
|
|
2592
|
+
await fs12.ensureDir(path12.dirname(tmpPath));
|
|
2593
|
+
await fs12.writeFile(tmpPath, stdinContent, "utf-8");
|
|
2594
|
+
config = tmpPath;
|
|
2595
|
+
} else {
|
|
2596
|
+
config = options.config || "bundle.config.json";
|
|
2597
|
+
}
|
|
2598
|
+
const event = await loadJsonFromSource(options.event, { name: "event" });
|
|
2599
|
+
const result = await pushCore(config, event, {
|
|
2600
|
+
flow: options.flow,
|
|
2601
|
+
json: options.json,
|
|
2602
|
+
verbose: options.verbose,
|
|
2603
|
+
silent: options.silent,
|
|
2604
|
+
platform: options.platform
|
|
2605
|
+
});
|
|
2351
2606
|
const duration = Date.now() - startTime;
|
|
2607
|
+
let output;
|
|
2352
2608
|
if (options.json) {
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2609
|
+
output = JSON.stringify(
|
|
2610
|
+
{
|
|
2611
|
+
success: result.success,
|
|
2612
|
+
event: result.elbResult,
|
|
2613
|
+
duration
|
|
2614
|
+
},
|
|
2615
|
+
null,
|
|
2616
|
+
2
|
|
2617
|
+
);
|
|
2358
2618
|
} else {
|
|
2619
|
+
const lines = [];
|
|
2359
2620
|
if (result.success) {
|
|
2360
|
-
|
|
2621
|
+
lines.push("Event pushed successfully");
|
|
2361
2622
|
if (result.elbResult && typeof result.elbResult === "object") {
|
|
2362
2623
|
const pushResult = result.elbResult;
|
|
2363
|
-
if ("id" in pushResult && pushResult.id)
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
if ("action" in pushResult && pushResult.action) {
|
|
2370
|
-
logger2.log(` Action: ${pushResult.action}`);
|
|
2371
|
-
}
|
|
2624
|
+
if ("id" in pushResult && pushResult.id)
|
|
2625
|
+
lines.push(` Event ID: ${pushResult.id}`);
|
|
2626
|
+
if ("entity" in pushResult && pushResult.entity)
|
|
2627
|
+
lines.push(` Entity: ${pushResult.entity}`);
|
|
2628
|
+
if ("action" in pushResult && pushResult.action)
|
|
2629
|
+
lines.push(` Action: ${pushResult.action}`);
|
|
2372
2630
|
}
|
|
2373
|
-
|
|
2631
|
+
lines.push(` Duration: ${duration}ms`);
|
|
2374
2632
|
} else {
|
|
2375
|
-
|
|
2376
|
-
process.exit(1);
|
|
2633
|
+
lines.push(`Error: ${result.error}`);
|
|
2377
2634
|
}
|
|
2635
|
+
output = lines.join("\n");
|
|
2378
2636
|
}
|
|
2379
|
-
|
|
2637
|
+
await writeResult(output + "\n", { output: options.output });
|
|
2638
|
+
process.exit(result.success ? 0 : 1);
|
|
2380
2639
|
} catch (error) {
|
|
2381
2640
|
const duration = Date.now() - startTime;
|
|
2382
2641
|
const errorMessage = getErrorMessage(error);
|
|
2383
2642
|
if (options.json) {
|
|
2384
|
-
|
|
2385
|
-
success: false,
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2643
|
+
const errorOutput = JSON.stringify(
|
|
2644
|
+
{ success: false, error: errorMessage, duration },
|
|
2645
|
+
null,
|
|
2646
|
+
2
|
|
2647
|
+
);
|
|
2648
|
+
await writeResult(errorOutput + "\n", { output: options.output });
|
|
2389
2649
|
} else {
|
|
2390
2650
|
logger2.error(`Error: ${errorMessage}`);
|
|
2391
2651
|
}
|
|
2392
2652
|
process.exit(1);
|
|
2393
|
-
} finally {
|
|
2394
|
-
if (tempDir) {
|
|
2395
|
-
await fs11.remove(tempDir).catch(() => {
|
|
2396
|
-
});
|
|
2397
|
-
}
|
|
2398
2653
|
}
|
|
2399
2654
|
}
|
|
2655
|
+
async function push(configOrPath, event, options = {}) {
|
|
2656
|
+
if (typeof configOrPath !== "string") {
|
|
2657
|
+
throw new Error(
|
|
2658
|
+
"push() currently only supports config file paths. Config object support will be added in a future version. Please provide a path to a configuration file."
|
|
2659
|
+
);
|
|
2660
|
+
}
|
|
2661
|
+
return await pushCore(configOrPath, event, {
|
|
2662
|
+
json: options.json ?? false,
|
|
2663
|
+
verbose: options.verbose ?? false,
|
|
2664
|
+
flow: options.flow,
|
|
2665
|
+
platform: options.platform
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2400
2668
|
async function executeConfigPush(options, validatedEvent, logger2, setTempDir) {
|
|
2401
2669
|
logger2.debug("Loading flow configuration");
|
|
2402
2670
|
const { flowConfig, buildOptions } = await loadFlowConfig(options.config, {
|
|
@@ -2406,14 +2674,14 @@ async function executeConfigPush(options, validatedEvent, logger2, setTempDir) {
|
|
|
2406
2674
|
const platform = getPlatform4(flowConfig);
|
|
2407
2675
|
logger2.debug("Bundling flow configuration");
|
|
2408
2676
|
const configDir = buildOptions.configDir || process.cwd();
|
|
2409
|
-
const tempDir =
|
|
2677
|
+
const tempDir = path12.join(
|
|
2410
2678
|
configDir,
|
|
2411
2679
|
".tmp",
|
|
2412
2680
|
`push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
2413
2681
|
);
|
|
2414
2682
|
setTempDir(tempDir);
|
|
2415
|
-
await
|
|
2416
|
-
const tempPath =
|
|
2683
|
+
await fs12.ensureDir(tempDir);
|
|
2684
|
+
const tempPath = path12.join(
|
|
2417
2685
|
tempDir,
|
|
2418
2686
|
`bundle.${platform === "web" ? "js" : "mjs"}`
|
|
2419
2687
|
);
|
|
@@ -2446,18 +2714,18 @@ async function executeConfigPush(options, validatedEvent, logger2, setTempDir) {
|
|
|
2446
2714
|
}
|
|
2447
2715
|
}
|
|
2448
2716
|
async function executeBundlePush(bundleContent, platform, validatedEvent, logger2, setTempDir, context = {}) {
|
|
2449
|
-
const tempDir =
|
|
2717
|
+
const tempDir = path12.join(
|
|
2450
2718
|
process.cwd(),
|
|
2451
2719
|
".tmp",
|
|
2452
2720
|
`push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
2453
2721
|
);
|
|
2454
2722
|
setTempDir(tempDir);
|
|
2455
|
-
await
|
|
2456
|
-
const tempPath =
|
|
2723
|
+
await fs12.ensureDir(tempDir);
|
|
2724
|
+
const tempPath = path12.join(
|
|
2457
2725
|
tempDir,
|
|
2458
2726
|
`bundle.${platform === "server" ? "mjs" : "js"}`
|
|
2459
2727
|
);
|
|
2460
|
-
await
|
|
2728
|
+
await fs12.writeFile(tempPath, bundleContent, "utf8");
|
|
2461
2729
|
logger2.debug(`Bundle written to: ${tempPath}`);
|
|
2462
2730
|
if (platform === "web") {
|
|
2463
2731
|
logger2.debug("Executing in web environment (JSDOM)");
|
|
@@ -2479,7 +2747,7 @@ async function executeWebPush(bundlePath, event, logger2) {
|
|
|
2479
2747
|
});
|
|
2480
2748
|
const { window } = dom;
|
|
2481
2749
|
logger2.debug("Loading bundle...");
|
|
2482
|
-
const bundleCode = await
|
|
2750
|
+
const bundleCode = await fs12.readFile(bundlePath, "utf8");
|
|
2483
2751
|
window.eval(bundleCode);
|
|
2484
2752
|
logger2.debug("Waiting for collector...");
|
|
2485
2753
|
await waitForWindowProperty2(
|
|
@@ -2571,10 +2839,10 @@ function waitForWindowProperty2(window, prop, timeout = 5e3) {
|
|
|
2571
2839
|
}
|
|
2572
2840
|
|
|
2573
2841
|
// src/commands/run/index.ts
|
|
2574
|
-
import
|
|
2842
|
+
import path14 from "path";
|
|
2575
2843
|
|
|
2576
2844
|
// src/commands/run/validators.ts
|
|
2577
|
-
import { existsSync as
|
|
2845
|
+
import { existsSync as existsSync3 } from "fs";
|
|
2578
2846
|
|
|
2579
2847
|
// src/schemas/primitives.ts
|
|
2580
2848
|
import { z } from "@walkeros/core/dev";
|
|
@@ -2591,6 +2859,74 @@ var RunOptionsSchema = z2.object({
|
|
|
2591
2859
|
flowName: z2.string().optional().describe("Specific flow name to run")
|
|
2592
2860
|
});
|
|
2593
2861
|
|
|
2862
|
+
// src/schemas/validate.ts
|
|
2863
|
+
import { z as z3 } from "@walkeros/core/dev";
|
|
2864
|
+
var ValidationTypeSchema = z3.union([
|
|
2865
|
+
z3.enum(["event", "flow", "mapping"]),
|
|
2866
|
+
z3.string().regex(/^(destinations|sources|transformers)\.\w+$|^\w+$/)
|
|
2867
|
+
]).describe(
|
|
2868
|
+
'Validation type: "event", "flow", "mapping", or dot-notation path (e.g., "destinations.snowplow") to validate a specific entry against its package schema'
|
|
2869
|
+
);
|
|
2870
|
+
var ValidateOptionsSchema = z3.object({
|
|
2871
|
+
flow: z3.string().optional().describe("Flow name for multi-flow configs")
|
|
2872
|
+
});
|
|
2873
|
+
var ValidateInputShape = {
|
|
2874
|
+
type: ValidationTypeSchema,
|
|
2875
|
+
input: z3.string().min(1).describe("JSON string, file path, or URL to validate"),
|
|
2876
|
+
flow: z3.string().optional().describe("Flow name for multi-flow configs")
|
|
2877
|
+
};
|
|
2878
|
+
var ValidateInputSchema = z3.object(ValidateInputShape);
|
|
2879
|
+
|
|
2880
|
+
// src/schemas/bundle.ts
|
|
2881
|
+
import { z as z4 } from "@walkeros/core/dev";
|
|
2882
|
+
var BundleOptionsSchema = z4.object({
|
|
2883
|
+
silent: z4.boolean().optional().describe("Suppress all output"),
|
|
2884
|
+
verbose: z4.boolean().optional().describe("Enable verbose logging"),
|
|
2885
|
+
stats: z4.boolean().optional().default(true).describe("Return bundle statistics"),
|
|
2886
|
+
cache: z4.boolean().optional().default(true).describe("Enable package caching"),
|
|
2887
|
+
flowName: z4.string().optional().describe("Flow name for multi-flow configs")
|
|
2888
|
+
});
|
|
2889
|
+
var BundleInputShape = {
|
|
2890
|
+
configPath: FilePathSchema.describe(
|
|
2891
|
+
"Path to flow configuration file (JSON or JavaScript)"
|
|
2892
|
+
),
|
|
2893
|
+
flow: z4.string().optional().describe("Flow name for multi-flow configs"),
|
|
2894
|
+
stats: z4.boolean().optional().default(true).describe("Return bundle statistics"),
|
|
2895
|
+
output: z4.string().optional().describe("Output file path (defaults to config-defined)")
|
|
2896
|
+
};
|
|
2897
|
+
var BundleInputSchema = z4.object(BundleInputShape);
|
|
2898
|
+
|
|
2899
|
+
// src/schemas/simulate.ts
|
|
2900
|
+
import { z as z5 } from "@walkeros/core/dev";
|
|
2901
|
+
var PlatformSchema = z5.enum(["web", "server"]).describe("Platform type for event processing");
|
|
2902
|
+
var SimulateOptionsSchema = z5.object({
|
|
2903
|
+
silent: z5.boolean().optional().describe("Suppress all output"),
|
|
2904
|
+
verbose: z5.boolean().optional().describe("Enable verbose logging"),
|
|
2905
|
+
json: z5.boolean().optional().describe("Format output as JSON")
|
|
2906
|
+
});
|
|
2907
|
+
var SimulateInputShape = {
|
|
2908
|
+
configPath: FilePathSchema.describe("Path to flow configuration file"),
|
|
2909
|
+
event: z5.string().min(1).describe("Event as JSON string, file path, or URL"),
|
|
2910
|
+
flow: z5.string().optional().describe("Flow name for multi-flow configs"),
|
|
2911
|
+
platform: PlatformSchema.optional().describe("Override platform detection")
|
|
2912
|
+
};
|
|
2913
|
+
var SimulateInputSchema = z5.object(SimulateInputShape);
|
|
2914
|
+
|
|
2915
|
+
// src/schemas/push.ts
|
|
2916
|
+
import { z as z6 } from "@walkeros/core/dev";
|
|
2917
|
+
var PushOptionsSchema = z6.object({
|
|
2918
|
+
silent: z6.boolean().optional().describe("Suppress all output"),
|
|
2919
|
+
verbose: z6.boolean().optional().describe("Enable verbose logging"),
|
|
2920
|
+
json: z6.boolean().optional().describe("Format output as JSON")
|
|
2921
|
+
});
|
|
2922
|
+
var PushInputShape = {
|
|
2923
|
+
configPath: FilePathSchema.describe("Path to flow configuration file"),
|
|
2924
|
+
event: z6.string().min(1).describe("Event as JSON string, file path, or URL"),
|
|
2925
|
+
flow: z6.string().optional().describe("Flow name for multi-flow configs"),
|
|
2926
|
+
platform: PlatformSchema.optional().describe("Override platform detection")
|
|
2927
|
+
};
|
|
2928
|
+
var PushInputSchema = z6.object(PushInputShape);
|
|
2929
|
+
|
|
2594
2930
|
// src/commands/run/validators.ts
|
|
2595
2931
|
function validateMode(mode) {
|
|
2596
2932
|
const result = RunModeSchema.safeParse(mode);
|
|
@@ -2604,7 +2940,7 @@ function validateMode(mode) {
|
|
|
2604
2940
|
}
|
|
2605
2941
|
function validateFlowFile(filePath) {
|
|
2606
2942
|
const absolutePath = resolveAsset(filePath, "bundle");
|
|
2607
|
-
if (!
|
|
2943
|
+
if (!existsSync3(absolutePath)) {
|
|
2608
2944
|
throw new Error(
|
|
2609
2945
|
`Flow file not found: ${filePath}
|
|
2610
2946
|
Resolved path: ${absolutePath}
|
|
@@ -2625,17 +2961,17 @@ function validatePort(port) {
|
|
|
2625
2961
|
}
|
|
2626
2962
|
|
|
2627
2963
|
// src/commands/run/utils.ts
|
|
2628
|
-
import
|
|
2629
|
-
import
|
|
2964
|
+
import path13 from "path";
|
|
2965
|
+
import fs13 from "fs-extra";
|
|
2630
2966
|
async function prepareBundleForRun(configPath, options) {
|
|
2631
|
-
const configDir =
|
|
2632
|
-
const tempDir =
|
|
2967
|
+
const configDir = path13.dirname(path13.resolve(configPath));
|
|
2968
|
+
const tempDir = path13.join(
|
|
2633
2969
|
configDir,
|
|
2634
2970
|
".tmp",
|
|
2635
2971
|
`run-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
2636
2972
|
);
|
|
2637
|
-
await
|
|
2638
|
-
const tempPath =
|
|
2973
|
+
await fs13.ensureDir(tempDir);
|
|
2974
|
+
const tempPath = path13.join(tempDir, "bundle.mjs");
|
|
2639
2975
|
await bundle(configPath, {
|
|
2640
2976
|
cache: true,
|
|
2641
2977
|
verbose: options.verbose,
|
|
@@ -2826,8 +3162,8 @@ async function runCommand(mode, options) {
|
|
|
2826
3162
|
let flowPath = null;
|
|
2827
3163
|
if (mode === "collect") {
|
|
2828
3164
|
if (isPreBuilt) {
|
|
2829
|
-
flowPath =
|
|
2830
|
-
logger2.debug(`Using pre-built flow: ${
|
|
3165
|
+
flowPath = path14.resolve(configPath);
|
|
3166
|
+
logger2.debug(`Using pre-built flow: ${path14.basename(flowPath)}`);
|
|
2831
3167
|
} else {
|
|
2832
3168
|
logger2.debug("Building flow bundle");
|
|
2833
3169
|
flowPath = await prepareBundleForRun(configPath, {
|
|
@@ -2877,7 +3213,7 @@ async function run(mode, options) {
|
|
|
2877
3213
|
const isPreBuilt = isPreBuiltConfig(flowFile);
|
|
2878
3214
|
let flowPath;
|
|
2879
3215
|
if (isPreBuilt) {
|
|
2880
|
-
flowPath =
|
|
3216
|
+
flowPath = path14.resolve(flowFile);
|
|
2881
3217
|
} else {
|
|
2882
3218
|
flowPath = await prepareBundleForRun(flowFile, {
|
|
2883
3219
|
verbose: options.verbose,
|
|
@@ -2906,7 +3242,7 @@ async function run(mode, options) {
|
|
|
2906
3242
|
}
|
|
2907
3243
|
|
|
2908
3244
|
// src/commands/validate/index.ts
|
|
2909
|
-
import
|
|
3245
|
+
import chalk3 from "chalk";
|
|
2910
3246
|
|
|
2911
3247
|
// src/commands/validate/validators/event.ts
|
|
2912
3248
|
import { schemas as schemas3 } from "@walkeros/core/dev";
|
|
@@ -2951,10 +3287,10 @@ function validateEvent(input) {
|
|
|
2951
3287
|
const zodResult = PartialEventSchema.safeParse(input);
|
|
2952
3288
|
if (!zodResult.success) {
|
|
2953
3289
|
for (const issue of zodResult.error.issues) {
|
|
2954
|
-
const
|
|
2955
|
-
if (
|
|
3290
|
+
const path15 = issue.path.join(".");
|
|
3291
|
+
if (path15 === "name") continue;
|
|
2956
3292
|
errors.push({
|
|
2957
|
-
path:
|
|
3293
|
+
path: path15 || "root",
|
|
2958
3294
|
message: issue.message,
|
|
2959
3295
|
code: "SCHEMA_VALIDATION"
|
|
2960
3296
|
});
|
|
@@ -2990,9 +3326,9 @@ function validateFlow(input, options = {}) {
|
|
|
2990
3326
|
const zodResult = SetupSchema.safeParse(input);
|
|
2991
3327
|
if (!zodResult.success) {
|
|
2992
3328
|
for (const issue of zodResult.error.issues) {
|
|
2993
|
-
const
|
|
3329
|
+
const path15 = issue.path.join(".");
|
|
2994
3330
|
errors.push({
|
|
2995
|
-
path:
|
|
3331
|
+
path: path15 || "root",
|
|
2996
3332
|
message: issue.message,
|
|
2997
3333
|
code: "SCHEMA_VALIDATION"
|
|
2998
3334
|
});
|
|
@@ -3097,8 +3433,144 @@ function validateMapping(input) {
|
|
|
3097
3433
|
};
|
|
3098
3434
|
}
|
|
3099
3435
|
|
|
3436
|
+
// src/commands/validate/validators/entry.ts
|
|
3437
|
+
import Ajv from "ajv";
|
|
3438
|
+
import { fetchPackageSchema } from "@walkeros/core";
|
|
3439
|
+
var SECTIONS = ["destinations", "sources", "transformers"];
|
|
3440
|
+
function resolveEntry(path15, flowConfig) {
|
|
3441
|
+
const flows = flowConfig.flows;
|
|
3442
|
+
if (!flows || typeof flows !== "object") return "No flows found in config";
|
|
3443
|
+
const flowName = Object.keys(flows)[0];
|
|
3444
|
+
const flow = flows[flowName];
|
|
3445
|
+
if (!flow) return `Flow "${flowName}" is empty`;
|
|
3446
|
+
const parts = path15.split(".");
|
|
3447
|
+
if (parts.length === 2) {
|
|
3448
|
+
const [section, key] = parts;
|
|
3449
|
+
if (!SECTIONS.includes(section)) {
|
|
3450
|
+
return `Unknown section "${section}". Must be one of: ${SECTIONS.join(", ")}`;
|
|
3451
|
+
}
|
|
3452
|
+
const sectionData = flow[section];
|
|
3453
|
+
if (!sectionData || !(key in sectionData)) {
|
|
3454
|
+
return `Entry "${key}" not found in ${section}`;
|
|
3455
|
+
}
|
|
3456
|
+
return {
|
|
3457
|
+
section,
|
|
3458
|
+
key,
|
|
3459
|
+
entry: sectionData[key]
|
|
3460
|
+
};
|
|
3461
|
+
}
|
|
3462
|
+
if (parts.length === 1) {
|
|
3463
|
+
const key = parts[0];
|
|
3464
|
+
const matches = [];
|
|
3465
|
+
for (const section of SECTIONS) {
|
|
3466
|
+
const sectionData = flow[section];
|
|
3467
|
+
if (sectionData && key in sectionData) {
|
|
3468
|
+
matches.push({
|
|
3469
|
+
section,
|
|
3470
|
+
entry: sectionData[key]
|
|
3471
|
+
});
|
|
3472
|
+
}
|
|
3473
|
+
}
|
|
3474
|
+
if (matches.length === 0) {
|
|
3475
|
+
return `Entry "${key}" not found in any section`;
|
|
3476
|
+
}
|
|
3477
|
+
if (matches.length > 1) {
|
|
3478
|
+
const sections = matches.map((m) => m.section).join(", ");
|
|
3479
|
+
return `Ambiguous key "${key}" found in multiple sections: ${sections}. Use dot-notation (e.g., destinations.${key})`;
|
|
3480
|
+
}
|
|
3481
|
+
return { section: matches[0].section, key, entry: matches[0].entry };
|
|
3482
|
+
}
|
|
3483
|
+
return `Invalid path "${path15}". Use "section.key" or just "key"`;
|
|
3484
|
+
}
|
|
3485
|
+
async function validateEntry(path15, flowConfig) {
|
|
3486
|
+
const resolved = resolveEntry(path15, flowConfig);
|
|
3487
|
+
if (typeof resolved === "string") {
|
|
3488
|
+
return {
|
|
3489
|
+
valid: false,
|
|
3490
|
+
type: "entry",
|
|
3491
|
+
errors: [{ path: path15, message: resolved, code: "ENTRY_VALIDATION" }],
|
|
3492
|
+
warnings: [],
|
|
3493
|
+
details: {}
|
|
3494
|
+
};
|
|
3495
|
+
}
|
|
3496
|
+
const { section, key, entry } = resolved;
|
|
3497
|
+
const packageName = entry.package;
|
|
3498
|
+
if (!packageName) {
|
|
3499
|
+
return {
|
|
3500
|
+
valid: true,
|
|
3501
|
+
type: "entry",
|
|
3502
|
+
errors: [],
|
|
3503
|
+
warnings: [],
|
|
3504
|
+
details: {
|
|
3505
|
+
section,
|
|
3506
|
+
key,
|
|
3507
|
+
skipped: true,
|
|
3508
|
+
reason: "No package field \u2014 skipping remote schema validation"
|
|
3509
|
+
}
|
|
3510
|
+
};
|
|
3511
|
+
}
|
|
3512
|
+
let schemas5;
|
|
3513
|
+
try {
|
|
3514
|
+
const info = await fetchPackageSchema(packageName);
|
|
3515
|
+
schemas5 = info.schemas;
|
|
3516
|
+
} catch (error) {
|
|
3517
|
+
return {
|
|
3518
|
+
valid: false,
|
|
3519
|
+
type: "entry",
|
|
3520
|
+
errors: [
|
|
3521
|
+
{
|
|
3522
|
+
path: path15,
|
|
3523
|
+
message: error instanceof Error ? error.message : "Unknown error",
|
|
3524
|
+
code: "ENTRY_VALIDATION"
|
|
3525
|
+
}
|
|
3526
|
+
],
|
|
3527
|
+
warnings: [],
|
|
3528
|
+
details: { section, key, package: packageName }
|
|
3529
|
+
};
|
|
3530
|
+
}
|
|
3531
|
+
const settingsSchema = schemas5?.settings;
|
|
3532
|
+
if (!settingsSchema) {
|
|
3533
|
+
return {
|
|
3534
|
+
valid: true,
|
|
3535
|
+
type: "entry",
|
|
3536
|
+
errors: [],
|
|
3537
|
+
warnings: [],
|
|
3538
|
+
details: { section, key, note: "Package has no settings schema" }
|
|
3539
|
+
};
|
|
3540
|
+
}
|
|
3541
|
+
const config = entry.config;
|
|
3542
|
+
const settings = config?.settings;
|
|
3543
|
+
const ajv = new Ajv({ allErrors: true });
|
|
3544
|
+
const validate2 = ajv.compile(settingsSchema);
|
|
3545
|
+
const isValid = validate2(settings || {});
|
|
3546
|
+
if (!isValid) {
|
|
3547
|
+
const errors = (validate2.errors || []).map((e) => ({
|
|
3548
|
+
path: e.instancePath || "/",
|
|
3549
|
+
message: e.message || "Unknown error",
|
|
3550
|
+
code: e.keyword
|
|
3551
|
+
}));
|
|
3552
|
+
return {
|
|
3553
|
+
valid: false,
|
|
3554
|
+
type: "entry",
|
|
3555
|
+
errors,
|
|
3556
|
+
warnings: [],
|
|
3557
|
+
details: { section, key, package: packageName }
|
|
3558
|
+
};
|
|
3559
|
+
}
|
|
3560
|
+
return {
|
|
3561
|
+
valid: true,
|
|
3562
|
+
type: "entry",
|
|
3563
|
+
errors: [],
|
|
3564
|
+
warnings: [],
|
|
3565
|
+
details: { section, key, package: packageName }
|
|
3566
|
+
};
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3100
3569
|
// src/commands/validate/index.ts
|
|
3101
3570
|
async function validate(type, input, options = {}) {
|
|
3571
|
+
if (type.includes(".") || !["event", "flow", "mapping"].includes(type)) {
|
|
3572
|
+
return validateEntry(type, input);
|
|
3573
|
+
}
|
|
3102
3574
|
switch (type) {
|
|
3103
3575
|
case "event":
|
|
3104
3576
|
return validateEvent(input);
|
|
@@ -3127,16 +3599,16 @@ function formatResult(result, options) {
|
|
|
3127
3599
|
}
|
|
3128
3600
|
lines.push("Validation Results:");
|
|
3129
3601
|
for (const error of result.errors) {
|
|
3130
|
-
lines.push(
|
|
3602
|
+
lines.push(chalk3.red(` \u2717 ${error.path}: ${error.message}`));
|
|
3131
3603
|
}
|
|
3132
3604
|
for (const warning of result.warnings) {
|
|
3133
|
-
lines.push(
|
|
3605
|
+
lines.push(chalk3.yellow(` \u26A0 ${warning.path}: ${warning.message}`));
|
|
3134
3606
|
if (warning.suggestion) {
|
|
3135
|
-
lines.push(
|
|
3607
|
+
lines.push(chalk3.gray(` \u2192 ${warning.suggestion}`));
|
|
3136
3608
|
}
|
|
3137
3609
|
}
|
|
3138
3610
|
if (result.valid) {
|
|
3139
|
-
lines.push(
|
|
3611
|
+
lines.push(chalk3.green(` \u2713 All checks passed`));
|
|
3140
3612
|
}
|
|
3141
3613
|
lines.push("");
|
|
3142
3614
|
lines.push(
|
|
@@ -3145,24 +3617,30 @@ function formatResult(result, options) {
|
|
|
3145
3617
|
return lines.join("\n");
|
|
3146
3618
|
}
|
|
3147
3619
|
async function validateCommand(options) {
|
|
3148
|
-
const logger2 = createCommandLogger(options);
|
|
3620
|
+
const logger2 = createCommandLogger({ ...options, stderr: true });
|
|
3149
3621
|
try {
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3622
|
+
let input;
|
|
3623
|
+
if (isStdinPiped() && !options.input) {
|
|
3624
|
+
const stdinContent = await readStdin();
|
|
3625
|
+
try {
|
|
3626
|
+
input = JSON.parse(stdinContent);
|
|
3627
|
+
} catch {
|
|
3628
|
+
throw new Error("Invalid JSON received on stdin");
|
|
3629
|
+
}
|
|
3630
|
+
} else {
|
|
3631
|
+
input = await loadJsonFromSource(options.input, {
|
|
3632
|
+
name: options.type,
|
|
3633
|
+
required: true
|
|
3634
|
+
});
|
|
3635
|
+
}
|
|
3154
3636
|
const result = await validate(options.type, input, {
|
|
3155
3637
|
flow: options.flow
|
|
3156
3638
|
});
|
|
3157
|
-
const
|
|
3639
|
+
const formatted = formatResult(result, {
|
|
3158
3640
|
json: options.json,
|
|
3159
3641
|
verbose: options.verbose
|
|
3160
3642
|
});
|
|
3161
|
-
|
|
3162
|
-
console.log(output);
|
|
3163
|
-
} else {
|
|
3164
|
-
logger2.log(output);
|
|
3165
|
-
}
|
|
3643
|
+
await writeResult(formatted + "\n", { output: options.output });
|
|
3166
3644
|
if (!result.valid) {
|
|
3167
3645
|
process.exit(1);
|
|
3168
3646
|
}
|
|
@@ -3173,13 +3651,20 @@ async function validateCommand(options) {
|
|
|
3173
3651
|
} catch (error) {
|
|
3174
3652
|
const errorMessage = getErrorMessage(error);
|
|
3175
3653
|
if (options.json) {
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3654
|
+
const errorOutput = JSON.stringify(
|
|
3655
|
+
{
|
|
3656
|
+
valid: false,
|
|
3657
|
+
type: options.type,
|
|
3658
|
+
errors: [
|
|
3659
|
+
{ path: "input", message: errorMessage, code: "INPUT_ERROR" }
|
|
3660
|
+
],
|
|
3661
|
+
warnings: [],
|
|
3662
|
+
details: {}
|
|
3663
|
+
},
|
|
3664
|
+
null,
|
|
3665
|
+
2
|
|
3666
|
+
);
|
|
3667
|
+
await writeResult(errorOutput + "\n", { output: options.output });
|
|
3183
3668
|
} else {
|
|
3184
3669
|
logger2.error(`Error: ${errorMessage}`);
|
|
3185
3670
|
}
|
|
@@ -3188,21 +3673,22 @@ async function validateCommand(options) {
|
|
|
3188
3673
|
}
|
|
3189
3674
|
|
|
3190
3675
|
// src/commands/cache.ts
|
|
3191
|
-
import
|
|
3676
|
+
import fs14 from "fs-extra";
|
|
3192
3677
|
function registerCacheCommand(program2) {
|
|
3193
3678
|
const cache = program2.command("cache").description("Manage the CLI cache");
|
|
3194
3679
|
cache.command("clear").description("Clear all cached packages and builds").option("--packages", "Clear only package cache").option("--builds", "Clear only build cache").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
|
|
3195
3680
|
const logger2 = createLogger({ silent: options.silent });
|
|
3196
3681
|
const tmpDir = options.tmpDir;
|
|
3197
3682
|
if (options.packages) {
|
|
3198
|
-
await
|
|
3683
|
+
await fs14.remove(getTmpPath(tmpDir, "cache", "packages"));
|
|
3199
3684
|
logger2.log("Package cache cleared");
|
|
3200
3685
|
} else if (options.builds) {
|
|
3201
|
-
await
|
|
3686
|
+
await fs14.remove(getTmpPath(tmpDir, "cache", "builds"));
|
|
3202
3687
|
logger2.log("Build cache cleared");
|
|
3203
3688
|
} else {
|
|
3204
|
-
|
|
3205
|
-
|
|
3689
|
+
const cacheDir = getTmpPath(tmpDir, "cache");
|
|
3690
|
+
await fs14.remove(cacheDir);
|
|
3691
|
+
logger2.log(`Cache cleared: ${cacheDir}`);
|
|
3206
3692
|
}
|
|
3207
3693
|
});
|
|
3208
3694
|
cache.command("info").description("Show cache statistics").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
|
|
@@ -3217,35 +3703,395 @@ function registerCacheCommand(program2) {
|
|
|
3217
3703
|
logger2.log(`Cached builds: ${buildCount}`);
|
|
3218
3704
|
});
|
|
3219
3705
|
}
|
|
3220
|
-
function registerCleanCommand(program2) {
|
|
3221
|
-
program2.command("clean").description("Clear the entire temp directory (.tmp/)").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
|
|
3222
|
-
const logger2 = createLogger({ silent: options.silent });
|
|
3223
|
-
const tmpDir = options.tmpDir || getDefaultTmpRoot();
|
|
3224
|
-
await fs13.remove(tmpDir);
|
|
3225
|
-
logger2.log(`Temp directory cleared: ${tmpDir}`);
|
|
3226
|
-
});
|
|
3227
|
-
}
|
|
3228
3706
|
async function countEntries(dir) {
|
|
3229
|
-
if (!await
|
|
3230
|
-
const entries = await
|
|
3707
|
+
if (!await fs14.pathExists(dir)) return 0;
|
|
3708
|
+
const entries = await fs14.readdir(dir);
|
|
3231
3709
|
return entries.length;
|
|
3232
3710
|
}
|
|
3233
3711
|
|
|
3712
|
+
// src/commands/login/index.ts
|
|
3713
|
+
import { hostname } from "os";
|
|
3714
|
+
var POLL_TIMEOUT_BUFFER_MS = 5e3;
|
|
3715
|
+
async function openInBrowser(url) {
|
|
3716
|
+
const { default: open } = await import("open");
|
|
3717
|
+
await open(url);
|
|
3718
|
+
}
|
|
3719
|
+
async function loginCommand(options) {
|
|
3720
|
+
const logger2 = createLogger({
|
|
3721
|
+
verbose: options.verbose,
|
|
3722
|
+
silent: options.silent,
|
|
3723
|
+
json: options.json
|
|
3724
|
+
});
|
|
3725
|
+
try {
|
|
3726
|
+
const result = await login({ url: options.url });
|
|
3727
|
+
if (options.json) {
|
|
3728
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3729
|
+
} else if (result.success) {
|
|
3730
|
+
logger2.success(`Logged in as ${result.email}`);
|
|
3731
|
+
logger2.log(`Token stored in ${result.configPath}`);
|
|
3732
|
+
}
|
|
3733
|
+
process.exit(result.success ? 0 : 1);
|
|
3734
|
+
} catch (error) {
|
|
3735
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3736
|
+
if (options.json) {
|
|
3737
|
+
console.log(JSON.stringify({ success: false, error: message }, null, 2));
|
|
3738
|
+
} else {
|
|
3739
|
+
logger2.error(message);
|
|
3740
|
+
}
|
|
3741
|
+
process.exit(1);
|
|
3742
|
+
}
|
|
3743
|
+
}
|
|
3744
|
+
async function login(options = {}) {
|
|
3745
|
+
const appUrl = options.url || resolveAppUrl();
|
|
3746
|
+
const f = options.fetch ?? globalThis.fetch;
|
|
3747
|
+
const codeResponse = await f(`${appUrl}/api/auth/device/code`, {
|
|
3748
|
+
method: "POST",
|
|
3749
|
+
headers: { "Content-Type": "application/json" },
|
|
3750
|
+
body: JSON.stringify({})
|
|
3751
|
+
});
|
|
3752
|
+
if (!codeResponse.ok) {
|
|
3753
|
+
return { success: false, error: "Failed to request device code" };
|
|
3754
|
+
}
|
|
3755
|
+
const { deviceCode, userCode, verificationUri, expiresIn, interval } = await codeResponse.json();
|
|
3756
|
+
console.error(`
|
|
3757
|
+
! Your one-time code: ${userCode}`);
|
|
3758
|
+
console.error(` Authorize here: ${verificationUri}
|
|
3759
|
+
`);
|
|
3760
|
+
const opener = options.openUrl ?? openInBrowser;
|
|
3761
|
+
try {
|
|
3762
|
+
await opener(verificationUri);
|
|
3763
|
+
console.error(" Opening browser...");
|
|
3764
|
+
} catch {
|
|
3765
|
+
console.error(" Could not open browser. Visit the URL manually.");
|
|
3766
|
+
}
|
|
3767
|
+
console.error(" Waiting for authorization... (press Ctrl+C to cancel)\n");
|
|
3768
|
+
const deadline = Date.now() + expiresIn * 1e3 + POLL_TIMEOUT_BUFFER_MS;
|
|
3769
|
+
let pollInterval = (interval ?? 5) * 1e3;
|
|
3770
|
+
const maxAttempts = options.maxPollAttempts ?? Infinity;
|
|
3771
|
+
let attempts = 0;
|
|
3772
|
+
while (Date.now() < deadline && attempts < maxAttempts) {
|
|
3773
|
+
attempts++;
|
|
3774
|
+
await new Promise((r) => setTimeout(r, pollInterval));
|
|
3775
|
+
const tokenResponse = await f(`${appUrl}/api/auth/device/token`, {
|
|
3776
|
+
method: "POST",
|
|
3777
|
+
headers: { "Content-Type": "application/json" },
|
|
3778
|
+
body: JSON.stringify({ deviceCode, hostname: hostname() })
|
|
3779
|
+
});
|
|
3780
|
+
const data = await tokenResponse.json();
|
|
3781
|
+
if (tokenResponse.ok && data.token) {
|
|
3782
|
+
writeConfig({ token: data.token, email: data.email, appUrl });
|
|
3783
|
+
const configPath = getConfigPath();
|
|
3784
|
+
return { success: true, email: data.email, configPath };
|
|
3785
|
+
}
|
|
3786
|
+
if (data.error === "authorization_pending") continue;
|
|
3787
|
+
if (data.error === "slow_down") {
|
|
3788
|
+
pollInterval += 5e3;
|
|
3789
|
+
continue;
|
|
3790
|
+
}
|
|
3791
|
+
return { success: false, error: data.error || "Authorization failed" };
|
|
3792
|
+
}
|
|
3793
|
+
return {
|
|
3794
|
+
success: false,
|
|
3795
|
+
error: "Authorization timed out. Please try again."
|
|
3796
|
+
};
|
|
3797
|
+
}
|
|
3798
|
+
|
|
3799
|
+
// src/commands/logout/index.ts
|
|
3800
|
+
async function logoutCommand(options) {
|
|
3801
|
+
const logger2 = createLogger({
|
|
3802
|
+
verbose: options.verbose,
|
|
3803
|
+
silent: options.silent,
|
|
3804
|
+
json: options.json
|
|
3805
|
+
});
|
|
3806
|
+
const deleted = deleteConfig();
|
|
3807
|
+
const configPath = getConfigPath();
|
|
3808
|
+
if (options.json) {
|
|
3809
|
+
console.log(JSON.stringify({ success: true, deleted }));
|
|
3810
|
+
} else if (deleted) {
|
|
3811
|
+
logger2.success(`Logged out. Token removed from ${configPath}`);
|
|
3812
|
+
} else {
|
|
3813
|
+
logger2.log("No stored credentials found.");
|
|
3814
|
+
}
|
|
3815
|
+
process.exit(0);
|
|
3816
|
+
}
|
|
3817
|
+
|
|
3818
|
+
// src/commands/auth/index.ts
|
|
3819
|
+
async function whoami() {
|
|
3820
|
+
const client = createApiClient();
|
|
3821
|
+
const { data, error } = await client.GET("/api/auth/whoami");
|
|
3822
|
+
if (error) throw new Error(error.error?.message || "Not authenticated");
|
|
3823
|
+
return data;
|
|
3824
|
+
}
|
|
3825
|
+
async function whoamiCommand(options) {
|
|
3826
|
+
const logger2 = createCommandLogger(options);
|
|
3827
|
+
try {
|
|
3828
|
+
const result = await whoami();
|
|
3829
|
+
if (options.json) {
|
|
3830
|
+
await writeResult(JSON.stringify(result, null, 2), options);
|
|
3831
|
+
} else {
|
|
3832
|
+
const data = result;
|
|
3833
|
+
if (data.email) logger2.log(`${data.email}`);
|
|
3834
|
+
if (data.userId) logger2.log(`User: ${data.userId}`);
|
|
3835
|
+
if (data.projectId) logger2.log(`Project: ${data.projectId}`);
|
|
3836
|
+
}
|
|
3837
|
+
} catch (error) {
|
|
3838
|
+
logger2.error(error instanceof Error ? error.message : String(error));
|
|
3839
|
+
process.exit(1);
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
|
|
3843
|
+
// src/commands/projects/index.ts
|
|
3844
|
+
async function listProjects() {
|
|
3845
|
+
const client = createApiClient();
|
|
3846
|
+
const { data, error } = await client.GET("/api/projects");
|
|
3847
|
+
if (error) throw new Error(error.error?.message || "Failed to list projects");
|
|
3848
|
+
return data;
|
|
3849
|
+
}
|
|
3850
|
+
async function getProject(options = {}) {
|
|
3851
|
+
const id = options.projectId ?? requireProjectId();
|
|
3852
|
+
const client = createApiClient();
|
|
3853
|
+
const { data, error } = await client.GET("/api/projects/{projectId}", {
|
|
3854
|
+
params: { path: { projectId: id } }
|
|
3855
|
+
});
|
|
3856
|
+
if (error) throw new Error(error.error?.message || "Failed to get project");
|
|
3857
|
+
return data;
|
|
3858
|
+
}
|
|
3859
|
+
async function createProject(options) {
|
|
3860
|
+
const client = createApiClient();
|
|
3861
|
+
const { data, error } = await client.POST("/api/projects", {
|
|
3862
|
+
body: { name: options.name }
|
|
3863
|
+
});
|
|
3864
|
+
if (error)
|
|
3865
|
+
throw new Error(error.error?.message || "Failed to create project");
|
|
3866
|
+
return data;
|
|
3867
|
+
}
|
|
3868
|
+
async function updateProject(options) {
|
|
3869
|
+
const id = options.projectId ?? requireProjectId();
|
|
3870
|
+
const client = createApiClient();
|
|
3871
|
+
const { data, error } = await client.PATCH("/api/projects/{projectId}", {
|
|
3872
|
+
params: { path: { projectId: id } },
|
|
3873
|
+
body: { name: options.name }
|
|
3874
|
+
});
|
|
3875
|
+
if (error)
|
|
3876
|
+
throw new Error(error.error?.message || "Failed to update project");
|
|
3877
|
+
return data;
|
|
3878
|
+
}
|
|
3879
|
+
async function deleteProject(options = {}) {
|
|
3880
|
+
const id = options.projectId ?? requireProjectId();
|
|
3881
|
+
const client = createApiClient();
|
|
3882
|
+
const { data, error } = await client.DELETE("/api/projects/{projectId}", {
|
|
3883
|
+
params: { path: { projectId: id } }
|
|
3884
|
+
});
|
|
3885
|
+
if (error)
|
|
3886
|
+
throw new Error(error.error?.message || "Failed to delete project");
|
|
3887
|
+
return data ?? { success: true };
|
|
3888
|
+
}
|
|
3889
|
+
async function handleResult(fn, options) {
|
|
3890
|
+
const logger2 = createCommandLogger(options);
|
|
3891
|
+
try {
|
|
3892
|
+
const result = await fn();
|
|
3893
|
+
await writeResult(JSON.stringify(result, null, 2), options);
|
|
3894
|
+
} catch (error) {
|
|
3895
|
+
logger2.error(error instanceof Error ? error.message : String(error));
|
|
3896
|
+
process.exit(1);
|
|
3897
|
+
}
|
|
3898
|
+
}
|
|
3899
|
+
async function listProjectsCommand(options) {
|
|
3900
|
+
await handleResult(() => listProjects(), options);
|
|
3901
|
+
}
|
|
3902
|
+
async function getProjectCommand(projectId, options) {
|
|
3903
|
+
await handleResult(
|
|
3904
|
+
() => getProject({ projectId: projectId ?? options.project }),
|
|
3905
|
+
options
|
|
3906
|
+
);
|
|
3907
|
+
}
|
|
3908
|
+
async function createProjectCommand(name, options) {
|
|
3909
|
+
await handleResult(() => createProject({ name }), options);
|
|
3910
|
+
}
|
|
3911
|
+
async function updateProjectCommand(projectId, options) {
|
|
3912
|
+
const name = options.name;
|
|
3913
|
+
if (!name) {
|
|
3914
|
+
throw new Error("Missing required option: --name <name>");
|
|
3915
|
+
}
|
|
3916
|
+
await handleResult(
|
|
3917
|
+
() => updateProject({
|
|
3918
|
+
projectId: projectId ?? options.project,
|
|
3919
|
+
name
|
|
3920
|
+
}),
|
|
3921
|
+
options
|
|
3922
|
+
);
|
|
3923
|
+
}
|
|
3924
|
+
async function deleteProjectCommand(projectId, options) {
|
|
3925
|
+
await handleResult(
|
|
3926
|
+
() => deleteProject({ projectId: projectId ?? options.project }),
|
|
3927
|
+
options
|
|
3928
|
+
);
|
|
3929
|
+
}
|
|
3930
|
+
|
|
3931
|
+
// src/commands/flows/index.ts
|
|
3932
|
+
async function listFlows(options = {}) {
|
|
3933
|
+
const id = options.projectId ?? requireProjectId();
|
|
3934
|
+
const client = createApiClient();
|
|
3935
|
+
const { data, error } = await client.GET("/api/projects/{projectId}/flows", {
|
|
3936
|
+
params: {
|
|
3937
|
+
path: { projectId: id },
|
|
3938
|
+
query: {
|
|
3939
|
+
sort: options.sort,
|
|
3940
|
+
order: options.order,
|
|
3941
|
+
include_deleted: options.includeDeleted ? "true" : void 0
|
|
3942
|
+
}
|
|
3943
|
+
}
|
|
3944
|
+
});
|
|
3945
|
+
if (error) throw new Error(error.error?.message || "Failed to list flows");
|
|
3946
|
+
return data;
|
|
3947
|
+
}
|
|
3948
|
+
async function getFlow(options) {
|
|
3949
|
+
const id = options.projectId ?? requireProjectId();
|
|
3950
|
+
const client = createApiClient();
|
|
3951
|
+
const { data, error } = await client.GET(
|
|
3952
|
+
"/api/projects/{projectId}/flows/{flowId}",
|
|
3953
|
+
{
|
|
3954
|
+
params: { path: { projectId: id, flowId: options.flowId } }
|
|
3955
|
+
}
|
|
3956
|
+
);
|
|
3957
|
+
if (error) throw new Error(error.error?.message || "Failed to get flow");
|
|
3958
|
+
return data;
|
|
3959
|
+
}
|
|
3960
|
+
async function createFlow(options) {
|
|
3961
|
+
const id = options.projectId ?? requireProjectId();
|
|
3962
|
+
const client = createApiClient();
|
|
3963
|
+
const { data, error } = await client.POST("/api/projects/{projectId}/flows", {
|
|
3964
|
+
params: { path: { projectId: id } },
|
|
3965
|
+
// Content is user-provided JSON; server validates the full schema
|
|
3966
|
+
body: { name: options.name, content: options.content }
|
|
3967
|
+
});
|
|
3968
|
+
if (error) throw new Error(error.error?.message || "Failed to create flow");
|
|
3969
|
+
return data;
|
|
3970
|
+
}
|
|
3971
|
+
async function updateFlow(options) {
|
|
3972
|
+
const id = options.projectId ?? requireProjectId();
|
|
3973
|
+
const client = createApiClient();
|
|
3974
|
+
const body = {};
|
|
3975
|
+
if (options.name !== void 0) body.name = options.name;
|
|
3976
|
+
if (options.content !== void 0) body.content = options.content;
|
|
3977
|
+
const { data, error } = await client.PATCH(
|
|
3978
|
+
"/api/projects/{projectId}/flows/{flowId}",
|
|
3979
|
+
{
|
|
3980
|
+
params: { path: { projectId: id, flowId: options.flowId } },
|
|
3981
|
+
// Dynamically constructed body; server validates the full schema
|
|
3982
|
+
body
|
|
3983
|
+
}
|
|
3984
|
+
);
|
|
3985
|
+
if (error) throw new Error(error.error?.message || "Failed to update flow");
|
|
3986
|
+
return data;
|
|
3987
|
+
}
|
|
3988
|
+
async function deleteFlow(options) {
|
|
3989
|
+
const id = options.projectId ?? requireProjectId();
|
|
3990
|
+
const client = createApiClient();
|
|
3991
|
+
const { data, error } = await client.DELETE(
|
|
3992
|
+
"/api/projects/{projectId}/flows/{flowId}",
|
|
3993
|
+
{
|
|
3994
|
+
params: { path: { projectId: id, flowId: options.flowId } }
|
|
3995
|
+
}
|
|
3996
|
+
);
|
|
3997
|
+
if (error) throw new Error(error.error?.message || "Failed to delete flow");
|
|
3998
|
+
return data ?? { success: true };
|
|
3999
|
+
}
|
|
4000
|
+
async function duplicateFlow(options) {
|
|
4001
|
+
const id = options.projectId ?? requireProjectId();
|
|
4002
|
+
const client = createApiClient();
|
|
4003
|
+
const { data, error } = await client.POST(
|
|
4004
|
+
"/api/projects/{projectId}/flows/{flowId}/duplicate",
|
|
4005
|
+
{
|
|
4006
|
+
params: { path: { projectId: id, flowId: options.flowId } },
|
|
4007
|
+
body: { name: options.name }
|
|
4008
|
+
}
|
|
4009
|
+
);
|
|
4010
|
+
if (error)
|
|
4011
|
+
throw new Error(error.error?.message || "Failed to duplicate flow");
|
|
4012
|
+
return data;
|
|
4013
|
+
}
|
|
4014
|
+
async function handleResult2(fn, options) {
|
|
4015
|
+
const logger2 = createCommandLogger(options);
|
|
4016
|
+
try {
|
|
4017
|
+
const result = await fn();
|
|
4018
|
+
await writeResult(JSON.stringify(result, null, 2), options);
|
|
4019
|
+
} catch (error) {
|
|
4020
|
+
logger2.error(error instanceof Error ? error.message : String(error));
|
|
4021
|
+
process.exit(1);
|
|
4022
|
+
}
|
|
4023
|
+
}
|
|
4024
|
+
async function listFlowsCommand(options) {
|
|
4025
|
+
await handleResult2(
|
|
4026
|
+
() => listFlows({
|
|
4027
|
+
projectId: options.project,
|
|
4028
|
+
sort: options.sort,
|
|
4029
|
+
order: options.order,
|
|
4030
|
+
includeDeleted: options.includeDeleted
|
|
4031
|
+
}),
|
|
4032
|
+
options
|
|
4033
|
+
);
|
|
4034
|
+
}
|
|
4035
|
+
async function getFlowCommand(flowId, options) {
|
|
4036
|
+
await handleResult2(
|
|
4037
|
+
() => getFlow({ flowId, projectId: options.project }),
|
|
4038
|
+
options
|
|
4039
|
+
);
|
|
4040
|
+
}
|
|
4041
|
+
async function createFlowCommand(name, options) {
|
|
4042
|
+
const content = options.content ? JSON.parse(options.content) : JSON.parse(await readFlowStdin());
|
|
4043
|
+
await handleResult2(
|
|
4044
|
+
() => createFlow({ name, content, projectId: options.project }),
|
|
4045
|
+
options
|
|
4046
|
+
);
|
|
4047
|
+
}
|
|
4048
|
+
async function updateFlowCommand(flowId, options) {
|
|
4049
|
+
const content = options.content ? JSON.parse(options.content) : void 0;
|
|
4050
|
+
await handleResult2(
|
|
4051
|
+
() => updateFlow({
|
|
4052
|
+
flowId,
|
|
4053
|
+
name: options.name,
|
|
4054
|
+
content,
|
|
4055
|
+
projectId: options.project
|
|
4056
|
+
}),
|
|
4057
|
+
options
|
|
4058
|
+
);
|
|
4059
|
+
}
|
|
4060
|
+
async function deleteFlowCommand(flowId, options) {
|
|
4061
|
+
await handleResult2(
|
|
4062
|
+
() => deleteFlow({ flowId, projectId: options.project }),
|
|
4063
|
+
options
|
|
4064
|
+
);
|
|
4065
|
+
}
|
|
4066
|
+
async function duplicateFlowCommand(flowId, options) {
|
|
4067
|
+
await handleResult2(
|
|
4068
|
+
() => duplicateFlow({ flowId, name: options.name, projectId: options.project }),
|
|
4069
|
+
options
|
|
4070
|
+
);
|
|
4071
|
+
}
|
|
4072
|
+
async function readFlowStdin() {
|
|
4073
|
+
if (!isStdinPiped()) {
|
|
4074
|
+
throw new Error("Content required: use --content or pipe via stdin");
|
|
4075
|
+
}
|
|
4076
|
+
return readStdin();
|
|
4077
|
+
}
|
|
4078
|
+
|
|
3234
4079
|
// src/index.ts
|
|
3235
4080
|
var program = new Command();
|
|
3236
4081
|
program.name("walkeros").description("walkerOS CLI - Bundle and deploy walkerOS components").version(VERSION);
|
|
3237
4082
|
program.hook("preAction", (thisCommand, actionCommand) => {
|
|
3238
4083
|
const options = actionCommand.opts();
|
|
3239
|
-
if (!options.silent && !options.json) {
|
|
3240
|
-
|
|
4084
|
+
if (!options.silent && !options.json && process.stdout.isTTY) {
|
|
4085
|
+
printBanner(VERSION);
|
|
3241
4086
|
}
|
|
3242
4087
|
});
|
|
3243
|
-
program.command("bundle [file]").description("Bundle NPM packages with custom code").option("--flow <name>", "flow name for multi-flow configs").option("--all", "build all flows for multi-flow configs").option("--stats", "show bundle statistics").option("--json", "output as JSON (implies --stats)").option("--no-cache", "disable package caching").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").option(
|
|
4088
|
+
program.command("bundle [file]").description("Bundle NPM packages with custom code").option("-o, --output <path>", "write bundle to file or directory").option("--flow <name>", "flow name for multi-flow configs").option("--all", "build all flows for multi-flow configs").option("--stats", "show bundle statistics").option("--json", "output as JSON (implies --stats)").option("--no-cache", "disable package caching").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").option(
|
|
3244
4089
|
"--dockerfile [file]",
|
|
3245
4090
|
"generate Dockerfile (or copy custom file) to dist/"
|
|
3246
4091
|
).action(async (file, options) => {
|
|
3247
4092
|
await bundleCommand({
|
|
3248
|
-
config: file
|
|
4093
|
+
config: file,
|
|
4094
|
+
output: options.output,
|
|
3249
4095
|
flow: options.flow,
|
|
3250
4096
|
all: options.all,
|
|
3251
4097
|
stats: options.stats,
|
|
@@ -3256,12 +4102,13 @@ program.command("bundle [file]").description("Bundle NPM packages with custom co
|
|
|
3256
4102
|
dockerfile: options.dockerfile
|
|
3257
4103
|
});
|
|
3258
4104
|
});
|
|
3259
|
-
program.command("simulate [file]").description("Simulate event processing and capture API calls").option(
|
|
4105
|
+
program.command("simulate [file]").description("Simulate event processing and capture API calls").option("-o, --output <path>", "write result to file").option(
|
|
3260
4106
|
"-e, --event <source>",
|
|
3261
4107
|
"event to simulate (JSON string, file path, or URL)"
|
|
3262
4108
|
).option("--flow <name>", "flow name for multi-flow configs").option("-p, --platform <platform>", "platform override (web or server)").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (file, options) => {
|
|
3263
4109
|
await simulateCommand({
|
|
3264
|
-
config: file
|
|
4110
|
+
config: file,
|
|
4111
|
+
output: options.output,
|
|
3265
4112
|
event: options.event,
|
|
3266
4113
|
flow: options.flow,
|
|
3267
4114
|
platform: options.platform,
|
|
@@ -3273,9 +4120,10 @@ program.command("simulate [file]").description("Simulate event processing and ca
|
|
|
3273
4120
|
program.command("push [file]").description("Push an event through the flow with real API execution").requiredOption(
|
|
3274
4121
|
"-e, --event <source>",
|
|
3275
4122
|
"event to push (JSON string, file path, or URL)"
|
|
3276
|
-
).option("--flow <name>", "flow name for multi-flow configs").option("-p, --platform <platform>", "platform override (web or server)").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (file, options) => {
|
|
4123
|
+
).option("-o, --output <path>", "write result to file").option("--flow <name>", "flow name for multi-flow configs").option("-p, --platform <platform>", "platform override (web or server)").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (file, options) => {
|
|
3277
4124
|
await pushCommand({
|
|
3278
|
-
config: file
|
|
4125
|
+
config: file,
|
|
4126
|
+
output: options.output,
|
|
3279
4127
|
event: options.event,
|
|
3280
4128
|
flow: options.flow,
|
|
3281
4129
|
platform: options.platform,
|
|
@@ -3284,10 +4132,11 @@ program.command("push [file]").description("Push an event through the flow with
|
|
|
3284
4132
|
silent: options.silent
|
|
3285
4133
|
});
|
|
3286
4134
|
});
|
|
3287
|
-
program.command("validate <type> [input]").description("Validate event, flow, or mapping configuration").option("--flow <name>", "flow name for multi-flow configs").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").option("--strict", "fail on warnings").action(async (type, input, options) => {
|
|
4135
|
+
program.command("validate <type> [input]").description("Validate event, flow, or mapping configuration").option("-o, --output <path>", "write result to file").option("--flow <name>", "flow name for multi-flow configs").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").option("--strict", "fail on warnings").action(async (type, input, options) => {
|
|
3288
4136
|
await validateCommand({
|
|
3289
4137
|
type,
|
|
3290
4138
|
input,
|
|
4139
|
+
output: options.output,
|
|
3291
4140
|
flow: options.flow,
|
|
3292
4141
|
json: options.json,
|
|
3293
4142
|
verbose: options.verbose,
|
|
@@ -3295,6 +4144,65 @@ program.command("validate <type> [input]").description("Validate event, flow, or
|
|
|
3295
4144
|
strict: options.strict
|
|
3296
4145
|
});
|
|
3297
4146
|
});
|
|
4147
|
+
var authCmd = program.command("auth").description("Authentication and identity");
|
|
4148
|
+
authCmd.command("login").description("Log in to walkerOS via browser").option("--url <url>", "custom app URL").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (options) => {
|
|
4149
|
+
await loginCommand({
|
|
4150
|
+
url: options.url,
|
|
4151
|
+
json: options.json,
|
|
4152
|
+
verbose: options.verbose,
|
|
4153
|
+
silent: options.silent
|
|
4154
|
+
});
|
|
4155
|
+
});
|
|
4156
|
+
authCmd.command("logout").description("Remove stored credentials").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (options) => {
|
|
4157
|
+
await logoutCommand({
|
|
4158
|
+
json: options.json,
|
|
4159
|
+
verbose: options.verbose,
|
|
4160
|
+
silent: options.silent
|
|
4161
|
+
});
|
|
4162
|
+
});
|
|
4163
|
+
authCmd.command("whoami").description("Show current user identity").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (options) => {
|
|
4164
|
+
await whoamiCommand({
|
|
4165
|
+
output: options.output,
|
|
4166
|
+
json: options.json,
|
|
4167
|
+
verbose: options.verbose,
|
|
4168
|
+
silent: options.silent
|
|
4169
|
+
});
|
|
4170
|
+
});
|
|
4171
|
+
var projectsCmd = program.command("projects").description("Manage walkerOS projects");
|
|
4172
|
+
projectsCmd.command("list").description("List all projects").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (options) => {
|
|
4173
|
+
await listProjectsCommand(options);
|
|
4174
|
+
});
|
|
4175
|
+
projectsCmd.command("get [projectId]").description("Get project details").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (projectId, options) => {
|
|
4176
|
+
await getProjectCommand(projectId, options);
|
|
4177
|
+
});
|
|
4178
|
+
projectsCmd.command("create <name>").description("Create a new project").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (name, options) => {
|
|
4179
|
+
await createProjectCommand(name, options);
|
|
4180
|
+
});
|
|
4181
|
+
projectsCmd.command("update [projectId]").description("Update a project").requiredOption("--name <name>", "new project name").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (projectId, options) => {
|
|
4182
|
+
await updateProjectCommand(projectId, options);
|
|
4183
|
+
});
|
|
4184
|
+
projectsCmd.command("delete [projectId]").description("Delete a project").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (projectId, options) => {
|
|
4185
|
+
await deleteProjectCommand(projectId, options);
|
|
4186
|
+
});
|
|
4187
|
+
var flowsCmd = program.command("flows").description("Manage walkerOS flows");
|
|
4188
|
+
flowsCmd.command("list").description("List all flows in a project").option("--project <id>", "project ID (defaults to WALKEROS_PROJECT_ID)").option("--sort <field>", "sort by: name, updated_at, created_at").option("--order <dir>", "sort order: asc, desc").option("--include-deleted", "include soft-deleted flows").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (options) => {
|
|
4189
|
+
await listFlowsCommand(options);
|
|
4190
|
+
});
|
|
4191
|
+
flowsCmd.command("get <flowId>").description("Get a flow with its full content").option("--project <id>", "project ID (defaults to WALKEROS_PROJECT_ID)").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (flowId, options) => {
|
|
4192
|
+
await getFlowCommand(flowId, options);
|
|
4193
|
+
});
|
|
4194
|
+
flowsCmd.command("create <name>").description("Create a new flow").option("--project <id>", "project ID (defaults to WALKEROS_PROJECT_ID)").option("-c, --content <json>", "Flow.Setup JSON string or file path").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (name, options) => {
|
|
4195
|
+
await createFlowCommand(name, options);
|
|
4196
|
+
});
|
|
4197
|
+
flowsCmd.command("update <flowId>").description("Update a flow").option("--project <id>", "project ID (defaults to WALKEROS_PROJECT_ID)").option("--name <name>", "new flow name").option("-c, --content <json>", "new Flow.Setup JSON string or file path").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (flowId, options) => {
|
|
4198
|
+
await updateFlowCommand(flowId, options);
|
|
4199
|
+
});
|
|
4200
|
+
flowsCmd.command("delete <flowId>").description("Delete a flow").option("--project <id>", "project ID (defaults to WALKEROS_PROJECT_ID)").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (flowId, options) => {
|
|
4201
|
+
await deleteFlowCommand(flowId, options);
|
|
4202
|
+
});
|
|
4203
|
+
flowsCmd.command("duplicate <flowId>").description("Duplicate a flow").option("--project <id>", "project ID (defaults to WALKEROS_PROJECT_ID)").option("--name <name>", "name for the copy").option("-o, --output <path>", "output file path").option("--json", "output as JSON").option("-v, --verbose", "verbose output").option("-s, --silent", "suppress output").action(async (flowId, options) => {
|
|
4204
|
+
await duplicateFlowCommand(flowId, options);
|
|
4205
|
+
});
|
|
3298
4206
|
var runCmd = program.command("run").description("Run walkerOS flows in collect or serve mode");
|
|
3299
4207
|
runCmd.command("collect [file]").description(
|
|
3300
4208
|
"Run collector mode (event collection endpoint). Defaults to server-collect.mjs if no file specified."
|
|
@@ -3323,16 +4231,34 @@ runCmd.command("serve [file]").description(
|
|
|
3323
4231
|
});
|
|
3324
4232
|
});
|
|
3325
4233
|
registerCacheCommand(program);
|
|
3326
|
-
registerCleanCommand(program);
|
|
3327
4234
|
program.parse();
|
|
3328
4235
|
export {
|
|
3329
4236
|
bundle,
|
|
3330
4237
|
bundleCommand,
|
|
4238
|
+
bundleRemote,
|
|
4239
|
+
createApiClient,
|
|
4240
|
+
createFlow,
|
|
4241
|
+
createProject,
|
|
4242
|
+
deleteFlow,
|
|
4243
|
+
deleteProject,
|
|
4244
|
+
duplicateFlow,
|
|
4245
|
+
getAuthHeaders,
|
|
4246
|
+
getFlow,
|
|
4247
|
+
getProject,
|
|
4248
|
+
getToken,
|
|
4249
|
+
listFlows,
|
|
4250
|
+
listProjects,
|
|
4251
|
+
push,
|
|
3331
4252
|
pushCommand,
|
|
4253
|
+
requireProjectId,
|
|
4254
|
+
resolveBaseUrl,
|
|
3332
4255
|
run,
|
|
3333
4256
|
runCommand,
|
|
3334
4257
|
simulate,
|
|
3335
4258
|
simulateCommand,
|
|
3336
|
-
|
|
4259
|
+
updateFlow,
|
|
4260
|
+
updateProject,
|
|
4261
|
+
validate,
|
|
4262
|
+
whoami
|
|
3337
4263
|
};
|
|
3338
4264
|
//# sourceMappingURL=index.js.map
|