@walkeros/cli 0.5.1-next.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +51 -28
  3. package/dist/__tests__/bundle/bundler.test.js +0 -1
  4. package/dist/__tests__/bundle/bundler.test.js.map +1 -1
  5. package/dist/__tests__/cli-e2e.test.js +26 -11
  6. package/dist/__tests__/cli-e2e.test.js.map +1 -1
  7. package/dist/__tests__/cli.test.js +2 -3
  8. package/dist/__tests__/cli.test.js.map +1 -1
  9. package/dist/__tests__/config-loader.test.js +6 -6
  10. package/dist/__tests__/config-loader.test.js.map +1 -1
  11. package/dist/__tests__/core/config.test.js +19 -12
  12. package/dist/__tests__/core/config.test.js.map +1 -1
  13. package/dist/__tests__/integration/bundle-run.integration.test.js +5 -5
  14. package/dist/__tests__/integration/bundle-run.integration.test.js.map +1 -1
  15. package/dist/__tests__/smoke/production.smoke.test.js +6 -6
  16. package/dist/__tests__/smoke/production.smoke.test.js.map +1 -1
  17. package/dist/commands/bundle/bundler.d.ts.map +1 -1
  18. package/dist/commands/bundle/bundler.js +18 -32
  19. package/dist/commands/bundle/bundler.js.map +1 -1
  20. package/dist/commands/bundle/index.d.ts +4 -2
  21. package/dist/commands/bundle/index.d.ts.map +1 -1
  22. package/dist/commands/bundle/index.js +99 -115
  23. package/dist/commands/bundle/index.js.map +1 -1
  24. package/dist/commands/bundle/package-manager.d.ts.map +1 -1
  25. package/dist/commands/bundle/package-manager.js +36 -13
  26. package/dist/commands/bundle/package-manager.js.map +1 -1
  27. package/dist/commands/cache.d.ts +4 -0
  28. package/dist/commands/cache.d.ts.map +1 -1
  29. package/dist/commands/cache.js +38 -14
  30. package/dist/commands/cache.js.map +1 -1
  31. package/dist/commands/push/index.d.ts.map +1 -1
  32. package/dist/commands/push/index.js +121 -131
  33. package/dist/commands/push/index.js.map +1 -1
  34. package/dist/commands/push/types.d.ts +3 -2
  35. package/dist/commands/push/types.d.ts.map +1 -1
  36. package/dist/commands/run/__tests__/run.integration.test.d.ts +1 -2
  37. package/dist/commands/run/__tests__/run.integration.test.d.ts.map +1 -1
  38. package/dist/commands/run/__tests__/run.integration.test.js +8 -9
  39. package/dist/commands/run/__tests__/run.integration.test.js.map +1 -1
  40. package/dist/commands/run/execution.js +1 -1
  41. package/dist/commands/run/execution.js.map +1 -1
  42. package/dist/commands/run/index.d.ts +1 -2
  43. package/dist/commands/run/index.d.ts.map +1 -1
  44. package/dist/commands/run/index.js +22 -59
  45. package/dist/commands/run/index.js.map +1 -1
  46. package/dist/commands/run/types.d.ts +8 -3
  47. package/dist/commands/run/types.d.ts.map +1 -1
  48. package/dist/commands/run/types.js +1 -1
  49. package/dist/commands/simulate/env-loader.d.ts.map +1 -1
  50. package/dist/commands/simulate/env-loader.js +1 -3
  51. package/dist/commands/simulate/env-loader.js.map +1 -1
  52. package/dist/commands/simulate/index.d.ts.map +1 -1
  53. package/dist/commands/simulate/index.js +47 -50
  54. package/dist/commands/simulate/index.js.map +1 -1
  55. package/dist/commands/simulate/simulator.js +3 -2
  56. package/dist/commands/simulate/simulator.js.map +1 -1
  57. package/dist/commands/simulate/types.d.ts +4 -2
  58. package/dist/commands/simulate/types.d.ts.map +1 -1
  59. package/dist/config/build-defaults.d.ts.map +1 -1
  60. package/dist/config/build-defaults.js +0 -2
  61. package/dist/config/build-defaults.js.map +1 -1
  62. package/dist/config/index.d.ts +1 -1
  63. package/dist/config/index.d.ts.map +1 -1
  64. package/dist/config/index.js +1 -1
  65. package/dist/config/index.js.map +1 -1
  66. package/dist/config/loader.d.ts.map +1 -1
  67. package/dist/config/loader.js +9 -11
  68. package/dist/config/loader.js.map +1 -1
  69. package/dist/config/utils.d.ts +0 -13
  70. package/dist/config/utils.d.ts.map +1 -1
  71. package/dist/config/utils.js +6 -28
  72. package/dist/config/utils.js.map +1 -1
  73. package/dist/core/build-cache.d.ts +4 -4
  74. package/dist/core/build-cache.d.ts.map +1 -1
  75. package/dist/core/build-cache.js +10 -9
  76. package/dist/core/build-cache.js.map +1 -1
  77. package/dist/core/index.d.ts +1 -3
  78. package/dist/core/index.d.ts.map +1 -1
  79. package/dist/core/index.js +1 -3
  80. package/dist/core/index.js.map +1 -1
  81. package/dist/core/logger.d.ts +5 -3
  82. package/dist/core/logger.d.ts.map +1 -1
  83. package/dist/core/logger.js +31 -34
  84. package/dist/core/logger.js.map +1 -1
  85. package/dist/core/tmp.d.ts +27 -0
  86. package/dist/core/tmp.d.ts.map +1 -0
  87. package/dist/core/tmp.js +36 -0
  88. package/dist/core/tmp.js.map +1 -0
  89. package/dist/index.d.ts +20 -13
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +630 -761
  92. package/dist/index.js.map +1 -1
  93. package/dist/runtime/index.d.ts +10 -0
  94. package/dist/runtime/index.d.ts.map +1 -0
  95. package/dist/runtime/index.js +10 -0
  96. package/dist/runtime/index.js.map +1 -0
  97. package/dist/runtime/main.d.ts +2 -0
  98. package/dist/runtime/main.d.ts.map +1 -0
  99. package/dist/runtime/main.js +268 -0
  100. package/dist/runtime/main.js.map +1 -0
  101. package/dist/runtime/runner.d.ts +20 -0
  102. package/dist/runtime/runner.d.ts.map +1 -0
  103. package/dist/runtime/runner.js +72 -0
  104. package/dist/runtime/runner.js.map +1 -0
  105. package/dist/runtime/serve.d.ts +19 -0
  106. package/dist/runtime/serve.d.ts.map +1 -0
  107. package/dist/runtime/serve.js +97 -0
  108. package/dist/runtime/serve.js.map +1 -0
  109. package/dist/types/global.d.ts +0 -13
  110. package/dist/types/global.d.ts.map +1 -1
  111. package/dist/types/global.js +0 -6
  112. package/dist/types/global.js.map +1 -1
  113. package/dist/version.d.ts +3 -0
  114. package/dist/version.d.ts.map +1 -0
  115. package/dist/version.js +27 -0
  116. package/dist/version.js.map +1 -0
  117. package/package.json +7 -4
  118. package/dist/core/docker.d.ts +0 -99
  119. package/dist/core/docker.d.ts.map +0 -1
  120. package/dist/core/docker.js +0 -253
  121. package/dist/core/docker.js.map +0 -1
  122. package/dist/core/execution.d.ts +0 -34
  123. package/dist/core/execution.d.ts.map +0 -1
  124. package/dist/core/execution.js +0 -64
  125. package/dist/core/execution.js.map +0 -1
  126. package/dist/core/temp-manager.d.ts +0 -51
  127. package/dist/core/temp-manager.d.ts.map +0 -1
  128. package/dist/core/temp-manager.js +0 -73
  129. package/dist/core/temp-manager.js.map +0 -1
package/dist/index.js CHANGED
@@ -2,81 +2,100 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
+ import chalk2 from "chalk";
6
+
7
+ // src/version.ts
5
8
  import { readFileSync } from "fs";
6
- import { fileURLToPath as fileURLToPath2 } from "url";
9
+ import { fileURLToPath } from "url";
7
10
  import { dirname, join } from "path";
8
- import { VERSION as DOCKER_VERSION2 } from "@walkeros/docker";
11
+ var versionFilename = fileURLToPath(import.meta.url);
12
+ var versionDirname = dirname(versionFilename);
13
+ function findPackageJson() {
14
+ const paths = [
15
+ join(versionDirname, "../package.json"),
16
+ // dist/ or src/
17
+ join(versionDirname, "../../package.json")
18
+ // src/core/ (not used, but safe)
19
+ ];
20
+ for (const p of paths) {
21
+ try {
22
+ return readFileSync(p, "utf-8");
23
+ } catch {
24
+ }
25
+ }
26
+ return JSON.stringify({ version: "0.0.0" });
27
+ }
28
+ var VERSION = JSON.parse(findPackageJson()).version;
9
29
 
10
30
  // src/commands/bundle/index.ts
11
31
  import path9 from "path";
12
32
 
13
33
  // src/core/logger.ts
14
34
  import chalk from "chalk";
35
+ var BRAND_COLOR = "#01b5e2";
15
36
  function createLogger(options = {}) {
16
37
  const { verbose = false, silent = false, json = false } = options;
17
38
  const shouldLog = !silent && !json;
18
39
  const shouldDebug = verbose && !silent && !json;
19
40
  return {
20
- log: (color, ...args) => {
41
+ log: (...args) => {
21
42
  if (shouldLog) {
22
43
  const message = args.map((arg) => String(arg)).join(" ");
23
- const colorMap = {
24
- red: chalk.red,
25
- green: chalk.green,
26
- blue: chalk.blue,
27
- yellow: chalk.yellow,
28
- gray: chalk.gray,
29
- grey: chalk.gray,
30
- cyan: chalk.cyan,
31
- magenta: chalk.magenta,
32
- white: chalk.white,
33
- black: chalk.black
34
- };
35
- const colorFn = colorMap[color];
36
- const coloredMessage = colorFn ? colorFn(message) : message;
37
- console.log(coloredMessage);
44
+ console.log(message);
38
45
  }
39
46
  },
40
- info: (...args) => {
47
+ brand: (...args) => {
41
48
  if (shouldLog) {
42
49
  const message = args.map((arg) => String(arg)).join(" ");
43
- console.log(chalk.blue(message));
50
+ console.log(chalk.hex(BRAND_COLOR)(message));
44
51
  }
45
52
  },
46
- success: (...args) => {
47
- if (shouldLog) {
53
+ error: (...args) => {
54
+ if (!json) {
48
55
  const message = args.map((arg) => String(arg)).join(" ");
49
- console.log(chalk.green(message));
56
+ console.error(chalk.red(message));
50
57
  }
51
58
  },
52
- warning: (...args) => {
59
+ debug: (...args) => {
60
+ if (shouldDebug) {
61
+ const message = args.map((arg) => String(arg)).join(" ");
62
+ console.log(` ${message}`);
63
+ }
64
+ },
65
+ json: (data) => {
66
+ if (!silent) {
67
+ console.log(JSON.stringify(data, null, 2));
68
+ }
69
+ },
70
+ // Backward-compatible methods (all use default terminal color per design)
71
+ info: (...args) => {
53
72
  if (shouldLog) {
54
73
  const message = args.map((arg) => String(arg)).join(" ");
55
- console.log(chalk.yellow(message));
74
+ console.log(message);
56
75
  }
57
76
  },
58
- warn: (...args) => {
77
+ success: (...args) => {
59
78
  if (shouldLog) {
60
79
  const message = args.map((arg) => String(arg)).join(" ");
61
- console.log(chalk.yellow(message));
80
+ console.log(message);
62
81
  }
63
82
  },
64
- error: (...args) => {
65
- if (!json) {
83
+ warning: (...args) => {
84
+ if (shouldLog) {
66
85
  const message = args.map((arg) => String(arg)).join(" ");
67
- console.error(chalk.red(message));
86
+ console.log(message);
68
87
  }
69
88
  },
70
- debug: (...args) => {
71
- if (shouldDebug) {
89
+ warn: (...args) => {
90
+ if (shouldLog) {
72
91
  const message = args.map((arg) => String(arg)).join(" ");
73
- console.log(chalk.gray(message));
92
+ console.log(message);
74
93
  }
75
94
  },
76
95
  gray: (...args) => {
77
96
  if (shouldLog) {
78
97
  const message = args.map((arg) => String(arg)).join(" ");
79
- console.log(chalk.gray(message));
98
+ console.log(message);
80
99
  }
81
100
  }
82
101
  };
@@ -132,15 +151,26 @@ function formatBytes(bytes) {
132
151
  return (bytes / 1024).toFixed(2);
133
152
  }
134
153
 
135
- // src/core/docker.ts
136
- import { spawn } from "child_process";
137
- import path2 from "path";
138
- import { VERSION as DOCKER_VERSION } from "@walkeros/docker";
154
+ // src/core/tmp.ts
155
+ import path from "path";
156
+ var DEFAULT_TMP_ROOT = ".tmp";
157
+ function getTmpPath(tmpDir, ...segments) {
158
+ const root = tmpDir || DEFAULT_TMP_ROOT;
159
+ const absoluteRoot = path.isAbsolute(root) ? root : path.resolve(root);
160
+ return path.join(absoluteRoot, ...segments);
161
+ }
162
+ function getDefaultTmpRoot() {
163
+ return DEFAULT_TMP_ROOT;
164
+ }
165
+
166
+ // src/core/asset-resolver.ts
167
+ import { fileURLToPath as fileURLToPath2 } from "url";
168
+ import { existsSync } from "fs";
169
+ import path3 from "path";
139
170
 
140
171
  // src/config/utils.ts
141
172
  import fs from "fs-extra";
142
- import path from "path";
143
- import os from "os";
173
+ import path2 from "path";
144
174
  function isUrl(str) {
145
175
  try {
146
176
  const url = new URL(str);
@@ -161,12 +191,9 @@ async function downloadFromUrl(url) {
161
191
  );
162
192
  }
163
193
  const content = await response.text();
164
- const urlObj = new URL(url);
165
- const urlFilename = path.basename(urlObj.pathname);
166
- const extension = path.extname(urlFilename) || ".json";
167
- const randomId = Math.random().toString(36).substring(2, 11);
168
- const filename = `walkeros-download-${Date.now()}-${randomId}${extension}`;
169
- const tempPath = path.join(os.tmpdir(), filename);
194
+ const downloadsDir = getTmpPath(void 0, "downloads");
195
+ await fs.ensureDir(downloadsDir);
196
+ const tempPath = path2.join(downloadsDir, "flow.json");
170
197
  await fs.writeFile(tempPath, content, "utf-8");
171
198
  return tempPath;
172
199
  } catch (error) {
@@ -183,7 +210,7 @@ async function loadJsonConfig(configPath) {
183
210
  absolutePath = await downloadFromUrl(configPath);
184
211
  isTemporary = true;
185
212
  } else {
186
- absolutePath = path.resolve(configPath);
213
+ absolutePath = path2.resolve(configPath);
187
214
  if (!await fs.pathExists(absolutePath)) {
188
215
  throw new Error(`Configuration file not found: ${absolutePath}`);
189
216
  }
@@ -204,11 +231,6 @@ async function loadJsonConfig(configPath) {
204
231
  }
205
232
  }
206
233
  }
207
- function getTempDir(tempDir = ".tmp") {
208
- const randomId = Math.random().toString(36).substring(2, 11);
209
- const basePath = path.isAbsolute(tempDir) ? tempDir : path.join(process.cwd(), tempDir);
210
- return path.join(basePath, `cli-${Date.now()}-${randomId}`);
211
- }
212
234
  async function loadJsonFromSource(source, options) {
213
235
  const paramName = options?.name || "input";
214
236
  if (!source || source.trim() === "") {
@@ -239,7 +261,7 @@ async function loadJsonFromSource(source, options) {
239
261
  );
240
262
  }
241
263
  }
242
- const resolvedPath = path.resolve(trimmedSource);
264
+ const resolvedPath = path2.resolve(trimmedSource);
243
265
  if (await fs.pathExists(resolvedPath)) {
244
266
  try {
245
267
  const data = await fs.readJson(resolvedPath);
@@ -263,193 +285,11 @@ async function loadJsonFromSource(source, options) {
263
285
  }
264
286
  }
265
287
 
266
- // src/core/docker.ts
267
- var CLI_VERSION = true ? "0.5.1-next.0" : "0.0.0";
268
- var CLI_DOCKER_IMAGE = process.env.WALKEROS_CLI_DOCKER_IMAGE || `walkeros/cli:${CLI_VERSION}`;
269
- var RUNTIME_DOCKER_IMAGE = process.env.WALKEROS_RUNTIME_DOCKER_IMAGE || `walkeros/docker:${DOCKER_VERSION}`;
270
- function buildCommonDockerArgs(options) {
271
- const args = [options.config];
272
- if (options.json) args.push("--json");
273
- if (options.verbose) args.push("--verbose");
274
- if (options.silent) args.push("--silent");
275
- return args;
276
- }
277
- function buildDockerCommand(command, args, options = {}, configFile) {
278
- const cwd = process.cwd();
279
- const cmd = ["docker", "run", "--rm"];
280
- if (configFile && !isUrl(configFile)) {
281
- const configPath = path2.resolve(cwd, configFile);
282
- cmd.push("-v", `${configPath}:/config/flow.json:ro`);
283
- args = args.map((arg) => arg === configFile ? "/config/flow.json" : arg);
284
- }
285
- cmd.push("-v", `${cwd}:/workspace`);
286
- cmd.push("-w", "/workspace");
287
- if (process.platform !== "win32") {
288
- try {
289
- const uid = process.getuid?.();
290
- const gid = process.getgid?.();
291
- if (uid !== void 0 && gid !== void 0) {
292
- cmd.push("--user", `${uid}:${gid}`);
293
- }
294
- } catch {
295
- }
296
- }
297
- if (options.verbose) {
298
- cmd.push("-e", "VERBOSE=true");
299
- }
300
- if (options.silent) {
301
- cmd.push("-e", "SILENT=true");
302
- }
303
- cmd.push(CLI_DOCKER_IMAGE);
304
- cmd.push(command, ...args);
305
- return cmd;
306
- }
307
- async function executeInDocker(command, args, options = {}, configFile) {
308
- const containerArgs = [...args, "--local"];
309
- const dockerCmd = buildDockerCommand(
310
- command,
311
- containerArgs,
312
- options,
313
- configFile
314
- );
315
- return new Promise((resolve, reject) => {
316
- const proc = spawn(dockerCmd[0], dockerCmd.slice(1), {
317
- stdio: options.silent ? "ignore" : "inherit",
318
- shell: false
319
- });
320
- proc.on("error", (error) => {
321
- reject(new Error(`Docker execution failed: ${error.message}`));
322
- });
323
- proc.on("exit", (code) => {
324
- if (code === 0) {
325
- resolve();
326
- } else {
327
- process.exit(code || 1);
328
- }
329
- });
330
- });
331
- }
332
- async function isDockerAvailable() {
333
- return new Promise((resolve) => {
334
- const proc = spawn("docker", ["--version"], {
335
- stdio: "ignore"
336
- });
337
- proc.on("error", () => resolve(false));
338
- proc.on("exit", (code) => resolve(code === 0));
339
- });
340
- }
341
- function buildDockerRunCommand(mode, flowPath, options = {}) {
342
- const cwd = process.cwd();
343
- const cmd = ["docker", "run", "--rm"];
344
- cmd.push("-e", `MODE=${mode}`);
345
- if (mode === "collect" && flowPath) {
346
- const absoluteFlowPath = path2.resolve(cwd, flowPath);
347
- const flowDir = path2.dirname(absoluteFlowPath);
348
- const flowFile = path2.basename(absoluteFlowPath);
349
- cmd.push("-v", `${flowDir}:/app/dist:ro`);
350
- cmd.push("-e", `FLOW=/app/dist/${flowFile}`);
351
- }
352
- if (mode === "serve" && flowPath) {
353
- const absoluteFilePath = path2.resolve(cwd, flowPath);
354
- cmd.push("-v", `${absoluteFilePath}:/app/bundle.mjs:ro`);
355
- cmd.push("-e", "FILE_PATH=/app/bundle.mjs");
356
- }
357
- const port = options.port !== void 0 ? options.port : 8080;
358
- cmd.push("-p", `${port}:${port}`);
359
- cmd.push("-e", `PORT=${port}`);
360
- if (options.host) {
361
- cmd.push("-e", `HOST=${options.host}`);
362
- }
363
- if (options.serveName) {
364
- cmd.push("-e", `SERVE_NAME=${options.serveName}`);
365
- }
366
- if (options.servePath) {
367
- cmd.push("-e", `SERVE_PATH=${options.servePath}`);
368
- }
369
- if (process.platform !== "win32") {
370
- try {
371
- const uid = process.getuid?.();
372
- const gid = process.getgid?.();
373
- if (uid !== void 0 && gid !== void 0) {
374
- cmd.push("--user", `${uid}:${gid}`);
375
- }
376
- } catch {
377
- }
378
- }
379
- cmd.push(RUNTIME_DOCKER_IMAGE);
380
- return cmd;
381
- }
382
- async function executeRunInDocker(mode, flowPath, options = {}) {
383
- const dockerCmd = buildDockerRunCommand(mode, flowPath, options);
384
- return new Promise((resolve, reject) => {
385
- const proc = spawn(dockerCmd[0], dockerCmd.slice(1), {
386
- stdio: options.silent ? "ignore" : "inherit",
387
- shell: false
388
- });
389
- proc.on("error", (error) => {
390
- reject(new Error(`Docker execution failed: ${error.message}`));
391
- });
392
- proc.on("exit", (code) => {
393
- if (code === 0) {
394
- resolve();
395
- } else {
396
- process.exit(code || 1);
397
- }
398
- });
399
- });
400
- }
401
-
402
- // src/core/execution.ts
403
- function getExecutionMode(options) {
404
- if (options.local || process.env.WALKEROS_CONTAINER === "true") {
405
- return "local";
406
- }
407
- return "docker";
408
- }
409
- async function executeCommand(localHandler, dockerCommand, dockerArgs, options, logger2, configFile) {
410
- const mode = getExecutionMode(options);
411
- if (options.dryRun) {
412
- if (mode === "docker") {
413
- const cmd = `docker run walkeros/cli:latest ${dockerCommand} ${dockerArgs.join(" ")}`;
414
- logger2?.info(`[DRY-RUN] Would execute: ${cmd}`);
415
- } else {
416
- logger2?.info(
417
- `[DRY-RUN] Would execute locally: ${dockerCommand} ${dockerArgs.join(" ")}`
418
- );
419
- }
420
- return;
421
- }
422
- if (mode === "local") {
423
- if (logger2 && !options.silent) {
424
- logger2.info("\u{1F5A5}\uFE0F Executing locally...");
425
- }
426
- await localHandler();
427
- } else {
428
- const dockerAvailable = await isDockerAvailable();
429
- if (!dockerAvailable) {
430
- throw new Error(
431
- "Docker is not available. Please install Docker or use --local flag to execute locally."
432
- );
433
- }
434
- if (logger2 && !options.silent) {
435
- logger2.info("\u{1F433} Executing in Docker container...");
436
- }
437
- await executeInDocker(dockerCommand, dockerArgs, options, configFile);
438
- }
439
- }
440
-
441
- // src/core/temp-manager.ts
442
- import { getHashServer } from "@walkeros/server-core";
443
- import fs2 from "fs-extra";
444
-
445
288
  // src/core/asset-resolver.ts
446
- import { fileURLToPath } from "url";
447
- import { existsSync } from "fs";
448
- import path3 from "path";
449
289
  var cachedAssetDir;
450
290
  function getAssetDir() {
451
291
  if (cachedAssetDir) return cachedAssetDir;
452
- const currentFile = fileURLToPath(import.meta.url);
292
+ const currentFile = fileURLToPath2(import.meta.url);
453
293
  let dir = path3.dirname(currentFile);
454
294
  while (dir !== path3.dirname(dir)) {
455
295
  if (existsSync(path3.join(dir, "examples"))) {
@@ -482,22 +322,22 @@ function getErrorMessage(error) {
482
322
 
483
323
  // src/core/local-packages.ts
484
324
  import path4 from "path";
485
- import fs3 from "fs-extra";
325
+ import fs2 from "fs-extra";
486
326
  async function resolveLocalPackage(packageName, localPath, configDir, logger2) {
487
327
  const absolutePath = path4.isAbsolute(localPath) ? localPath : path4.resolve(configDir, localPath);
488
- if (!await fs3.pathExists(absolutePath)) {
328
+ if (!await fs2.pathExists(absolutePath)) {
489
329
  throw new Error(
490
330
  `Local package path not found: ${localPath} (resolved to ${absolutePath})`
491
331
  );
492
332
  }
493
333
  const pkgJsonPath = path4.join(absolutePath, "package.json");
494
- if (!await fs3.pathExists(pkgJsonPath)) {
334
+ if (!await fs2.pathExists(pkgJsonPath)) {
495
335
  throw new Error(
496
336
  `No package.json found at ${absolutePath}. Is this a valid package directory?`
497
337
  );
498
338
  }
499
339
  const distPath = path4.join(absolutePath, "dist");
500
- const hasDistFolder = await fs3.pathExists(distPath);
340
+ const hasDistFolder = await fs2.pathExists(distPath);
501
341
  if (!hasDistFolder) {
502
342
  logger2.warn(
503
343
  `\u26A0\uFE0F ${packageName}: No dist/ folder found. Using package root.`
@@ -512,18 +352,18 @@ async function resolveLocalPackage(packageName, localPath, configDir, logger2) {
512
352
  }
513
353
  async function copyLocalPackage(localPkg, targetDir, logger2) {
514
354
  const packageDir = path4.join(targetDir, "node_modules", localPkg.name);
515
- await fs3.ensureDir(path4.dirname(packageDir));
516
- await fs3.copy(
355
+ await fs2.ensureDir(path4.dirname(packageDir));
356
+ await fs2.copy(
517
357
  path4.join(localPkg.absolutePath, "package.json"),
518
358
  path4.join(packageDir, "package.json")
519
359
  );
520
360
  if (localPkg.hasDistFolder) {
521
- await fs3.copy(localPkg.distPath, path4.join(packageDir, "dist"));
361
+ await fs2.copy(localPkg.distPath, path4.join(packageDir, "dist"));
522
362
  } else {
523
- const entries = await fs3.readdir(localPkg.absolutePath);
363
+ const entries = await fs2.readdir(localPkg.absolutePath);
524
364
  for (const entry of entries) {
525
365
  if (!["node_modules", ".turbo", ".git"].includes(entry)) {
526
- await fs3.copy(
366
+ await fs2.copy(
527
367
  path4.join(localPkg.absolutePath, entry),
528
368
  path4.join(packageDir, entry)
529
369
  );
@@ -544,8 +384,8 @@ function validateFlowSetup(data) {
544
384
  const result = safeParseSetup(data);
545
385
  if (!result.success) {
546
386
  const errors = result.error.issues.map((issue) => {
547
- const path15 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
548
- return ` - ${path15}: ${issue.message}`;
387
+ const path14 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
388
+ return ` - ${path14}: ${issue.message}`;
549
389
  }).join("\n");
550
390
  throw new Error(`Invalid configuration:
551
391
  ${errors}`);
@@ -564,7 +404,6 @@ var WEB_BUILD_DEFAULTS = {
564
404
  minify: true,
565
405
  sourcemap: false,
566
406
  cache: true,
567
- tempDir: ".tmp",
568
407
  windowCollector: "collector",
569
408
  windowElb: "elb"
570
409
  };
@@ -574,8 +413,7 @@ var SERVER_BUILD_DEFAULTS = {
574
413
  target: "node20",
575
414
  minify: true,
576
415
  sourcemap: false,
577
- cache: true,
578
- tempDir: ".tmp"
416
+ cache: true
579
417
  };
580
418
  var DEFAULT_OUTPUT_PATHS = {
581
419
  web: "./dist/walker.js",
@@ -590,7 +428,7 @@ function getDefaultOutput(platform) {
590
428
 
591
429
  // src/config/loader.ts
592
430
  import path5 from "path";
593
- import fs4 from "fs-extra";
431
+ import fs3 from "fs-extra";
594
432
  import { getFlowConfig, getPlatform } from "@walkeros/core";
595
433
  var DEFAULT_INCLUDE_FOLDER = "./shared";
596
434
  function loadBundleConfig(rawConfig, options) {
@@ -606,18 +444,12 @@ function loadBundleConfig(rawConfig, options) {
606
444
  }
607
445
  const buildDefaults = getBuildDefaults(platform);
608
446
  const packages = flowConfig.packages || {};
609
- let output = getDefaultOutput(platform);
610
- if (options.buildOverrides?.output) {
611
- output = options.buildOverrides.output;
612
- }
613
- const configDir = path5.dirname(options.configPath);
614
- if (!path5.isAbsolute(output)) {
615
- output = path5.resolve(configDir, output);
616
- }
447
+ const output = options.buildOverrides?.output || getDefaultOutput(platform);
448
+ const configDir = isUrl(options.configPath) ? process.cwd() : path5.dirname(options.configPath);
617
449
  let includes = setup.include;
618
450
  if (!includes) {
619
451
  const defaultIncludePath = path5.resolve(configDir, DEFAULT_INCLUDE_FOLDER);
620
- if (fs4.pathExistsSync(defaultIncludePath)) {
452
+ if (fs3.pathExistsSync(defaultIncludePath)) {
621
453
  includes = [DEFAULT_INCLUDE_FOLDER];
622
454
  }
623
455
  }
@@ -680,16 +512,16 @@ function loadAllFlows(rawConfig, options) {
680
512
  // src/commands/bundle/bundler.ts
681
513
  import esbuild from "esbuild";
682
514
  import path8 from "path";
683
- import fs7 from "fs-extra";
515
+ import fs6 from "fs-extra";
684
516
  import { packageNameToVariable } from "@walkeros/core";
685
517
 
686
518
  // src/commands/bundle/package-manager.ts
687
519
  import pacote from "pacote";
688
520
  import path6 from "path";
689
- import fs5 from "fs-extra";
521
+ import fs4 from "fs-extra";
690
522
 
691
523
  // src/core/cache-utils.ts
692
- import { getHashServer as getHashServer2 } from "@walkeros/server-core";
524
+ import { getHashServer } from "@walkeros/server-core";
693
525
  var HASH_LENGTH = 12;
694
526
  function isMutableVersion(version) {
695
527
  return version === "latest" || version.includes("^") || version.includes("~") || version.includes("*") || version.includes("x");
@@ -702,10 +534,10 @@ async function getPackageCacheKey(packageName, version, date) {
702
534
  if (isMutableVersion(version)) {
703
535
  const dateStr = date ?? getTodayDate();
704
536
  const input2 = `${safeName}@${version}:${dateStr}`;
705
- return getHashServer2(input2, HASH_LENGTH);
537
+ return getHashServer(input2, HASH_LENGTH);
706
538
  }
707
539
  const input = `${safeName}@${version}`;
708
- return getHashServer2(input, HASH_LENGTH);
540
+ return getHashServer(input, HASH_LENGTH);
709
541
  }
710
542
  function normalizeJson(content) {
711
543
  const parsed = JSON.parse(content);
@@ -715,21 +547,28 @@ async function getFlowConfigCacheKey(content, date) {
715
547
  const dateStr = date ?? getTodayDate();
716
548
  const normalized = normalizeJson(content);
717
549
  const input = `${normalized}:${dateStr}`;
718
- return getHashServer2(input, HASH_LENGTH);
550
+ return getHashServer(input, HASH_LENGTH);
719
551
  }
720
552
 
721
553
  // src/commands/bundle/package-manager.ts
554
+ var PACKAGE_DOWNLOAD_TIMEOUT_MS = 6e4;
555
+ async function withTimeout(promise, ms, errorMessage) {
556
+ const timeout = new Promise(
557
+ (_, reject) => setTimeout(() => reject(new Error(errorMessage)), ms)
558
+ );
559
+ return Promise.race([promise, timeout]);
560
+ }
722
561
  function getPackageDirectory(baseDir, packageName, version) {
723
562
  return path6.join(baseDir, "node_modules", packageName);
724
563
  }
725
- async function getCachedPackagePath(pkg, tempDir) {
726
- const cacheDir = path6.join(".tmp", "cache", "packages");
564
+ async function getCachedPackagePath(pkg, tmpDir) {
565
+ const cacheDir = getTmpPath(tmpDir, "cache", "packages");
727
566
  const cacheKey = await getPackageCacheKey(pkg.name, pkg.version);
728
567
  return path6.join(cacheDir, cacheKey);
729
568
  }
730
- async function isPackageCached(pkg, tempDir) {
731
- const cachedPath = await getCachedPackagePath(pkg, tempDir);
732
- return fs5.pathExists(cachedPath);
569
+ async function isPackageCached(pkg, tmpDir) {
570
+ const cachedPath = await getCachedPackagePath(pkg, tmpDir);
571
+ return fs4.pathExists(cachedPath);
733
572
  }
734
573
  function validateNoDuplicatePackages(packages) {
735
574
  const packageMap = /* @__PURE__ */ new Map();
@@ -764,11 +603,11 @@ async function resolveDependencies(pkg, packageDir, logger2, visited = /* @__PUR
764
603
  visited.add(pkgKey);
765
604
  try {
766
605
  const packageJsonPath = path6.join(packageDir, "package.json");
767
- if (await fs5.pathExists(packageJsonPath)) {
768
- const packageJson2 = await fs5.readJson(packageJsonPath);
606
+ if (await fs4.pathExists(packageJsonPath)) {
607
+ const packageJson = await fs4.readJson(packageJsonPath);
769
608
  const deps = {
770
- ...packageJson2.dependencies,
771
- ...packageJson2.peerDependencies
609
+ ...packageJson.dependencies,
610
+ ...packageJson.peerDependencies
772
611
  };
773
612
  for (const [name, versionSpec] of Object.entries(deps)) {
774
613
  if (typeof versionSpec === "string") {
@@ -785,6 +624,7 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
785
624
  const packagePaths = /* @__PURE__ */ new Map();
786
625
  const downloadQueue = [...packages];
787
626
  const processed = /* @__PURE__ */ new Set();
627
+ const userSpecifiedPackages = new Set(packages.map((p) => p.name));
788
628
  const localPackageMap = /* @__PURE__ */ new Map();
789
629
  for (const pkg of packages) {
790
630
  if (pkg.path) {
@@ -792,7 +632,7 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
792
632
  }
793
633
  }
794
634
  validateNoDuplicatePackages(packages);
795
- await fs5.ensureDir(targetDir);
635
+ await fs4.ensureDir(targetDir);
796
636
  while (downloadQueue.length > 0) {
797
637
  const pkg = downloadQueue.shift();
798
638
  const pkgKey = `${pkg.name}@${pkg.version}`;
@@ -823,12 +663,14 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
823
663
  }
824
664
  const packageSpec = `${pkg.name}@${pkg.version}`;
825
665
  const packageDir = getPackageDirectory(targetDir, pkg.name, pkg.version);
826
- const cachedPath = await getCachedPackagePath(pkg, targetDir);
827
- if (useCache && await isPackageCached(pkg, targetDir)) {
828
- logger2.debug(`Using cached ${packageSpec}...`);
666
+ const cachedPath = await getCachedPackagePath(pkg);
667
+ if (useCache && await isPackageCached(pkg)) {
668
+ if (userSpecifiedPackages.has(pkg.name)) {
669
+ logger2.debug(`Downloading ${packageSpec} (cached)`);
670
+ }
829
671
  try {
830
- await fs5.ensureDir(path6.dirname(packageDir));
831
- await fs5.copy(cachedPath, packageDir);
672
+ await fs4.ensureDir(path6.dirname(packageDir));
673
+ await fs4.copy(cachedPath, packageDir);
832
674
  packagePaths.set(pkg.name, packageDir);
833
675
  const deps = await resolveDependencies(pkg, packageDir, logger2);
834
676
  for (const dep of deps) {
@@ -844,27 +686,34 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
844
686
  );
845
687
  }
846
688
  }
847
- logger2.debug(`Downloading ${packageSpec}...`);
848
689
  try {
849
- await fs5.ensureDir(path6.dirname(packageDir));
850
- const cacheDir = process.env.NPM_CACHE_DIR || path6.join(process.cwd(), ".npm-cache");
851
- await pacote.extract(packageSpec, packageDir, {
852
- // Force npm registry download, prevent workspace resolution
853
- registry: "https://registry.npmjs.org",
854
- // Force online fetching from registry (don't use cached workspace packages)
855
- preferOnline: true,
856
- // Cache for performance
857
- cache: cacheDir,
858
- // Don't resolve relative to workspace context
859
- where: void 0
860
- });
690
+ await fs4.ensureDir(path6.dirname(packageDir));
691
+ const cacheDir = process.env.NPM_CACHE_DIR || getTmpPath(void 0, "cache", "npm");
692
+ await withTimeout(
693
+ pacote.extract(packageSpec, packageDir, {
694
+ // Force npm registry download, prevent workspace resolution
695
+ registry: "https://registry.npmjs.org",
696
+ // Force online fetching from registry (don't use cached workspace packages)
697
+ preferOnline: true,
698
+ // Cache for performance
699
+ cache: cacheDir,
700
+ // Don't resolve relative to workspace context
701
+ where: void 0
702
+ }),
703
+ PACKAGE_DOWNLOAD_TIMEOUT_MS,
704
+ `Package download timed out after ${PACKAGE_DOWNLOAD_TIMEOUT_MS / 1e3}s: ${packageSpec}`
705
+ );
706
+ if (userSpecifiedPackages.has(pkg.name)) {
707
+ const pkgStats = await fs4.stat(path6.join(packageDir, "package.json"));
708
+ const pkgJsonSize = pkgStats.size;
709
+ const sizeKB = (pkgJsonSize / 1024).toFixed(1);
710
+ logger2.debug(`Downloading ${packageSpec} (${sizeKB} KB)`);
711
+ }
861
712
  if (useCache) {
862
713
  try {
863
- await fs5.ensureDir(path6.dirname(cachedPath));
864
- await fs5.copy(packageDir, cachedPath);
865
- logger2.debug(`Cached ${packageSpec} for future use`);
714
+ await fs4.ensureDir(path6.dirname(cachedPath));
715
+ await fs4.copy(packageDir, cachedPath);
866
716
  } catch (cacheError) {
867
- logger2.debug(`Failed to cache ${packageSpec}: ${cacheError}`);
868
717
  }
869
718
  }
870
719
  packagePaths.set(pkg.name, packageDir);
@@ -883,26 +732,26 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
883
732
  }
884
733
 
885
734
  // src/core/build-cache.ts
886
- import fs6 from "fs-extra";
735
+ import fs5 from "fs-extra";
887
736
  import path7 from "path";
888
- var BUILD_CACHE_DIR = path7.join(".tmp", "cache", "builds");
889
- async function getBuildCachePath(configContent, cacheDir = BUILD_CACHE_DIR) {
737
+ async function getBuildCachePath(configContent, tmpDir) {
738
+ const cacheDir = getTmpPath(tmpDir, "cache", "builds");
890
739
  const cacheKey = await getFlowConfigCacheKey(configContent);
891
740
  return path7.join(cacheDir, `${cacheKey}.js`);
892
741
  }
893
- async function isBuildCached(configContent, cacheDir = BUILD_CACHE_DIR) {
894
- const cachePath = await getBuildCachePath(configContent, cacheDir);
895
- return fs6.pathExists(cachePath);
742
+ async function isBuildCached(configContent, tmpDir) {
743
+ const cachePath = await getBuildCachePath(configContent, tmpDir);
744
+ return fs5.pathExists(cachePath);
896
745
  }
897
- async function cacheBuild(configContent, buildOutput, cacheDir = BUILD_CACHE_DIR) {
898
- const cachePath = await getBuildCachePath(configContent, cacheDir);
899
- await fs6.ensureDir(path7.dirname(cachePath));
900
- await fs6.writeFile(cachePath, buildOutput, "utf-8");
746
+ async function cacheBuild(configContent, buildOutput, tmpDir) {
747
+ const cachePath = await getBuildCachePath(configContent, tmpDir);
748
+ await fs5.ensureDir(path7.dirname(cachePath));
749
+ await fs5.writeFile(cachePath, buildOutput, "utf-8");
901
750
  }
902
- async function getCachedBuild(configContent, cacheDir = BUILD_CACHE_DIR) {
903
- const cachePath = await getBuildCachePath(configContent, cacheDir);
904
- if (await fs6.pathExists(cachePath)) {
905
- return await fs6.readFile(cachePath, "utf-8");
751
+ async function getCachedBuild(configContent, tmpDir) {
752
+ const cachePath = await getBuildCachePath(configContent, tmpDir);
753
+ if (await fs5.pathExists(cachePath)) {
754
+ return await fs5.readFile(cachePath, "utf-8");
906
755
  }
907
756
  return null;
908
757
  }
@@ -913,8 +762,8 @@ async function copyIncludes(includes, sourceDir, outputDir, logger2) {
913
762
  const sourcePath = path8.resolve(sourceDir, include);
914
763
  const folderName = path8.basename(include);
915
764
  const destPath = path8.join(outputDir, folderName);
916
- if (await fs7.pathExists(sourcePath)) {
917
- await fs7.copy(sourcePath, destPath);
765
+ if (await fs6.pathExists(sourcePath)) {
766
+ await fs6.copy(sourcePath, destPath);
918
767
  logger2.debug(`Copied ${include} to output`);
919
768
  } else {
920
769
  logger2.debug(`Include folder not found: ${include}`);
@@ -935,21 +784,22 @@ function generateCacheKeyContent(flowConfig, buildOptions) {
935
784
  }
936
785
  async function bundleCore(flowConfig, buildOptions, logger2, showStats = false) {
937
786
  const bundleStartTime = Date.now();
938
- const TEMP_DIR = buildOptions.tempDir ? path8.isAbsolute(buildOptions.tempDir) ? buildOptions.tempDir : path8.resolve(buildOptions.tempDir) : getTempDir();
787
+ const TEMP_DIR = buildOptions.tempDir || getTmpPath();
939
788
  if (buildOptions.cache !== false) {
940
789
  const configContent = generateCacheKeyContent(flowConfig, buildOptions);
941
790
  const cached = await isBuildCached(configContent);
942
791
  if (cached) {
943
792
  const cachedBuild = await getCachedBuild(configContent);
944
793
  if (cachedBuild) {
945
- logger2.info("\u2728 Using cached build");
794
+ logger2.debug("Using cached build");
946
795
  const outputPath = path8.resolve(buildOptions.output);
947
- await fs7.ensureDir(path8.dirname(outputPath));
948
- await fs7.writeFile(outputPath, cachedBuild);
949
- logger2.gray(`Output: ${outputPath}`);
950
- logger2.success("\u2705 Build completed (from cache)");
796
+ await fs6.ensureDir(path8.dirname(outputPath));
797
+ await fs6.writeFile(outputPath, cachedBuild);
798
+ const stats = await fs6.stat(outputPath);
799
+ const sizeKB = (stats.size / 1024).toFixed(1);
800
+ logger2.log(`Output: ${outputPath} (${sizeKB} KB, cached)`);
951
801
  if (showStats) {
952
- const stats = await fs7.stat(outputPath);
802
+ const stats2 = await fs6.stat(outputPath);
953
803
  const packageStats = Object.entries(buildOptions.packages).map(
954
804
  ([name, pkg]) => ({
955
805
  name: `${name}@${pkg.version || "latest"}`,
@@ -958,7 +808,7 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
958
808
  })
959
809
  );
960
810
  return {
961
- totalSize: stats.size,
811
+ totalSize: stats2.size,
962
812
  packages: packageStats,
963
813
  buildTime: Date.now() - bundleStartTime,
964
814
  treeshakingEffective: true
@@ -969,11 +819,8 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
969
819
  }
970
820
  }
971
821
  try {
972
- if (!buildOptions.tempDir) {
973
- await fs7.emptyDir(TEMP_DIR);
974
- }
975
- logger2.debug("Cleaned temporary directory");
976
- logger2.info("\u{1F4E5} Downloading packages...");
822
+ await fs6.ensureDir(TEMP_DIR);
823
+ logger2.debug("Downloading packages");
977
824
  const packagesArray = Object.entries(buildOptions.packages).map(
978
825
  ([name, packageConfig]) => ({
979
826
  name,
@@ -993,7 +840,7 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
993
840
  for (const [pkgName, pkgPath] of packagePaths.entries()) {
994
841
  if (pkgName.startsWith("@walkeros/")) {
995
842
  const pkgJsonPath = path8.join(pkgPath, "package.json");
996
- const pkgJson = await fs7.readJSON(pkgJsonPath);
843
+ const pkgJson = await fs6.readJSON(pkgJsonPath);
997
844
  if (!pkgJson.exports && pkgJson.module) {
998
845
  pkgJson.exports = {
999
846
  ".": {
@@ -1001,26 +848,28 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
1001
848
  require: pkgJson.main
1002
849
  }
1003
850
  };
1004
- await fs7.writeJSON(pkgJsonPath, pkgJson, { spaces: 2 });
851
+ await fs6.writeJSON(pkgJsonPath, pkgJson, { spaces: 2 });
1005
852
  }
1006
853
  }
1007
854
  }
1008
855
  const packageJsonPath = path8.join(TEMP_DIR, "package.json");
1009
- await fs7.writeFile(
856
+ await fs6.writeFile(
1010
857
  packageJsonPath,
1011
858
  JSON.stringify({ type: "module" }, null, 2)
1012
859
  );
1013
- logger2.info("\u{1F4DD} Creating entry point...");
860
+ logger2.debug("Creating entry point");
1014
861
  const entryContent = await createEntryPoint(
1015
862
  flowConfig,
1016
863
  buildOptions,
1017
864
  packagePaths
1018
865
  );
1019
866
  const entryPath = path8.join(TEMP_DIR, "entry.js");
1020
- await fs7.writeFile(entryPath, entryContent);
1021
- logger2.info("\u26A1 Bundling with esbuild...");
867
+ await fs6.writeFile(entryPath, entryContent);
868
+ logger2.debug(
869
+ `Running esbuild (target: ${buildOptions.target || "es2018"}, format: ${buildOptions.format})`
870
+ );
1022
871
  const outputPath = path8.resolve(buildOptions.output);
1023
- await fs7.ensureDir(path8.dirname(outputPath));
872
+ await fs6.ensureDir(path8.dirname(outputPath));
1024
873
  const esbuildOptions = createEsbuildOptions(
1025
874
  buildOptions,
1026
875
  entryPath,
@@ -1037,10 +886,13 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
1037
886
  buildOptions.code || ""
1038
887
  );
1039
888
  }
1040
- logger2.gray(`Output: ${outputPath}`);
889
+ const outputStats = await fs6.stat(outputPath);
890
+ const sizeKB = (outputStats.size / 1024).toFixed(1);
891
+ const buildTime = ((Date.now() - bundleStartTime) / 1e3).toFixed(1);
892
+ logger2.log(`Output: ${outputPath} (${sizeKB} KB, ${buildTime}s)`);
1041
893
  if (buildOptions.cache !== false) {
1042
894
  const configContent = generateCacheKeyContent(flowConfig, buildOptions);
1043
- const buildOutput = await fs7.readFile(outputPath, "utf-8");
895
+ const buildOutput = await fs6.readFile(outputPath, "utf-8");
1044
896
  await cacheBuild(configContent, buildOutput);
1045
897
  logger2.debug("Build cached for future use");
1046
898
  }
@@ -1062,21 +914,13 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
1062
914
  logger2
1063
915
  );
1064
916
  }
1065
- if (!buildOptions.tempDir) {
1066
- await fs7.remove(TEMP_DIR);
1067
- logger2.debug("Cleaned up temporary files");
1068
- }
1069
917
  return stats;
1070
918
  } catch (error) {
1071
- if (!buildOptions.tempDir) {
1072
- await fs7.remove(TEMP_DIR).catch(() => {
1073
- });
1074
- }
1075
919
  throw error;
1076
920
  }
1077
921
  }
1078
922
  async function collectBundleStats(outputPath, packages, startTime, entryContent) {
1079
- const stats = await fs7.stat(outputPath);
923
+ const stats = await fs6.stat(outputPath);
1080
924
  const totalSize = stats.size;
1081
925
  const buildTime = Date.now() - startTime;
1082
926
  const packageStats = Object.entries(packages).map(([name, pkg]) => {
@@ -1437,130 +1281,111 @@ async function bundleCommand(options) {
1437
1281
  const timer = createTimer();
1438
1282
  timer.start();
1439
1283
  const logger2 = createCommandLogger(options);
1440
- const dockerArgs = buildCommonDockerArgs(options);
1441
- if (options.flow) dockerArgs.push("--flow", options.flow);
1442
- if (options.all) dockerArgs.push("--all");
1443
- if (options.stats) dockerArgs.push("--stats");
1444
- if (options.cache === false) dockerArgs.push("--no-cache");
1445
- await executeCommand(
1446
- async () => {
1284
+ if (options.dryRun) {
1285
+ logger2.log(`[DRY-RUN] Would execute bundle with config: ${options.config}`);
1286
+ return;
1287
+ }
1288
+ try {
1289
+ if (options.flow && options.all) {
1290
+ throw new Error("Cannot use both --flow and --all flags together");
1291
+ }
1292
+ const configPath = resolveAsset(options.config, "config");
1293
+ const rawConfig = await loadJsonConfig(configPath);
1294
+ const configsToBundle = options.all ? loadAllFlows(rawConfig, { configPath, logger: logger2 }) : [
1295
+ loadBundleConfig(rawConfig, {
1296
+ configPath,
1297
+ flowName: options.flow,
1298
+ logger: logger2
1299
+ })
1300
+ ];
1301
+ const results = [];
1302
+ for (const {
1303
+ flowConfig,
1304
+ buildOptions,
1305
+ flowName,
1306
+ isMultiFlow
1307
+ } of configsToBundle) {
1447
1308
  try {
1448
- if (options.flow && options.all) {
1449
- throw new Error("Cannot use both --flow and --all flags together");
1309
+ if (options.cache !== void 0) {
1310
+ buildOptions.cache = options.cache;
1311
+ }
1312
+ const configBasename = path9.basename(configPath);
1313
+ if (isMultiFlow || options.all) {
1314
+ logger2.log(`Bundling ${configBasename} (flow: ${flowName})...`);
1315
+ } else {
1316
+ logger2.log(`Bundling ${configBasename}...`);
1450
1317
  }
1451
- logger2.info("\u{1F4E6} Reading configuration...");
1452
- const configPath = resolveAsset(options.config, "config");
1453
- const rawConfig = await loadJsonConfig(configPath);
1454
- const configsToBundle = options.all ? loadAllFlows(rawConfig, { configPath, logger: logger2 }) : [
1455
- loadBundleConfig(rawConfig, {
1456
- configPath,
1457
- flowName: options.flow,
1458
- logger: logger2
1459
- })
1460
- ];
1461
- const results = [];
1462
- for (const {
1318
+ const shouldCollectStats = options.stats || options.json;
1319
+ const stats = await bundleCore(
1463
1320
  flowConfig,
1464
1321
  buildOptions,
1322
+ logger2,
1323
+ shouldCollectStats
1324
+ );
1325
+ results.push({
1465
1326
  flowName,
1466
- isMultiFlow
1467
- } of configsToBundle) {
1468
- try {
1469
- if (options.cache !== void 0) {
1470
- buildOptions.cache = options.cache;
1471
- }
1472
- if (isMultiFlow || options.all) {
1473
- logger2.info(`
1474
- \u{1F527} Building flow: ${flowName}`);
1475
- } else {
1476
- logger2.info("\u{1F527} Starting bundle process...");
1477
- }
1478
- const shouldCollectStats = options.stats || options.json;
1479
- const stats = await bundleCore(
1480
- flowConfig,
1481
- buildOptions,
1482
- logger2,
1483
- shouldCollectStats
1484
- );
1485
- results.push({
1486
- flowName,
1487
- success: true,
1488
- stats
1489
- });
1490
- if (!options.json && !options.all && options.stats && stats) {
1491
- displayStats(stats, logger2);
1492
- }
1493
- } catch (error) {
1494
- const errorMessage = getErrorMessage(error);
1495
- results.push({
1496
- flowName,
1497
- success: false,
1498
- error: errorMessage
1499
- });
1500
- if (!options.all) {
1501
- throw error;
1502
- }
1503
- }
1504
- }
1505
- const duration = timer.end() / 1e3;
1506
- const successCount = results.filter((r) => r.success).length;
1507
- const failureCount = results.filter((r) => !r.success).length;
1508
- if (options.json) {
1509
- const outputLogger = createLogger({ silent: false, json: false });
1510
- const output = failureCount === 0 ? createSuccessOutput(
1511
- {
1512
- flows: results,
1513
- summary: {
1514
- total: results.length,
1515
- success: successCount,
1516
- failed: failureCount
1517
- }
1518
- },
1519
- duration
1520
- ) : createErrorOutput(
1521
- `${failureCount} flow(s) failed to build`,
1522
- duration
1523
- );
1524
- outputLogger.log("white", JSON.stringify(output, null, 2));
1525
- } else {
1526
- if (options.all) {
1527
- logger2.info(`
1528
- \u{1F4CA} Build Summary:`);
1529
- logger2.info(` Total: ${results.length}`);
1530
- logger2.success(` \u2705 Success: ${successCount}`);
1531
- if (failureCount > 0) {
1532
- logger2.error(` \u274C Failed: ${failureCount}`);
1533
- }
1534
- }
1535
- if (failureCount === 0) {
1536
- logger2.success(
1537
- `
1538
- \u2705 Bundle created successfully in ${timer.format()}`
1539
- );
1540
- } else {
1541
- throw new Error(`${failureCount} flow(s) failed to build`);
1542
- }
1327
+ success: true,
1328
+ stats
1329
+ });
1330
+ if (!options.json && !options.all && options.stats && stats) {
1331
+ displayStats(stats, logger2);
1543
1332
  }
1544
1333
  } catch (error) {
1545
- const duration = timer.getElapsed() / 1e3;
1546
1334
  const errorMessage = getErrorMessage(error);
1547
- if (options.json) {
1548
- const outputLogger = createLogger({ silent: false, json: false });
1549
- const output = createErrorOutput(errorMessage, duration);
1550
- outputLogger.log("white", JSON.stringify(output, null, 2));
1551
- } else {
1552
- logger2.error("\u274C Bundle failed:");
1553
- logger2.error(errorMessage);
1335
+ results.push({
1336
+ flowName,
1337
+ success: false,
1338
+ error: errorMessage
1339
+ });
1340
+ if (!options.all) {
1341
+ throw error;
1554
1342
  }
1555
- process.exit(1);
1556
1343
  }
1557
- },
1558
- "bundle",
1559
- dockerArgs,
1560
- options,
1561
- logger2,
1562
- options.config
1563
- );
1344
+ }
1345
+ const duration = timer.end() / 1e3;
1346
+ const successCount = results.filter((r) => r.success).length;
1347
+ const failureCount = results.filter((r) => !r.success).length;
1348
+ if (options.json) {
1349
+ const output = failureCount === 0 ? createSuccessOutput(
1350
+ {
1351
+ flows: results,
1352
+ summary: {
1353
+ total: results.length,
1354
+ success: successCount,
1355
+ failed: failureCount
1356
+ }
1357
+ },
1358
+ duration
1359
+ ) : createErrorOutput(
1360
+ `${failureCount} flow(s) failed to build`,
1361
+ duration
1362
+ );
1363
+ logger2.json(output);
1364
+ } else {
1365
+ if (options.all) {
1366
+ logger2.log(
1367
+ `
1368
+ Build Summary: ${successCount}/${results.length} succeeded`
1369
+ );
1370
+ if (failureCount > 0) {
1371
+ logger2.error(`Failed: ${failureCount}`);
1372
+ }
1373
+ }
1374
+ if (failureCount > 0) {
1375
+ throw new Error(`${failureCount} flow(s) failed to build`);
1376
+ }
1377
+ }
1378
+ } catch (error) {
1379
+ const duration = timer.getElapsed() / 1e3;
1380
+ const errorMessage = getErrorMessage(error);
1381
+ if (options.json) {
1382
+ const output = createErrorOutput(errorMessage, duration);
1383
+ logger2.json(output);
1384
+ } else {
1385
+ logger2.error(`Error: ${errorMessage}`);
1386
+ }
1387
+ process.exit(1);
1388
+ }
1564
1389
  }
1565
1390
  async function bundle(configOrPath, options = {}) {
1566
1391
  let rawConfig;
@@ -1590,7 +1415,7 @@ async function bundle(configOrPath, options = {}) {
1590
1415
 
1591
1416
  // src/commands/simulate/simulator.ts
1592
1417
  import path10 from "path";
1593
- import fs9 from "fs-extra";
1418
+ import fs8 from "fs-extra";
1594
1419
  import { getPlatform as getPlatform2 } from "@walkeros/core";
1595
1420
 
1596
1421
  // src/commands/simulate/tracker.ts
@@ -1627,9 +1452,9 @@ var CallTracker = class {
1627
1452
  }
1628
1453
  for (const fullPath of paths) {
1629
1454
  const [destKey, ...pathParts] = fullPath.split(":");
1630
- const path15 = pathParts.join(":");
1631
- if (!path15) continue;
1632
- const cleanPath = path15.replace(/^call:/, "");
1455
+ const path14 = pathParts.join(":");
1456
+ if (!path14) continue;
1457
+ const cleanPath = path14.replace(/^call:/, "");
1633
1458
  const parts = cleanPath.split(".");
1634
1459
  let current = wrapped;
1635
1460
  let source = env;
@@ -1673,7 +1498,7 @@ var CallTracker = class {
1673
1498
 
1674
1499
  // src/commands/simulate/jsdom-executor.ts
1675
1500
  import { JSDOM, VirtualConsole } from "jsdom";
1676
- import fs8 from "fs-extra";
1501
+ import fs7 from "fs-extra";
1677
1502
  function buildSandboxFromEnvs(envs, destinations, tracker) {
1678
1503
  const baseBrowserMocks = {
1679
1504
  Image: class MockImage {
@@ -1710,11 +1535,11 @@ function buildSandboxFromEnvs(envs, destinations, tracker) {
1710
1535
  return sandbox;
1711
1536
  }
1712
1537
  function waitForWindowProperty(window, prop, timeout = 5e3) {
1713
- return new Promise((resolve, reject) => {
1538
+ return new Promise((resolve3, reject) => {
1714
1539
  const start = Date.now();
1715
1540
  const check = () => {
1716
1541
  if (window[prop] !== void 0) {
1717
- resolve();
1542
+ resolve3();
1718
1543
  } else if (Date.now() - start > timeout) {
1719
1544
  reject(
1720
1545
  new Error(
@@ -1742,7 +1567,7 @@ async function executeInJSDOM(bundlePath, destinations, event, tracker, envs, ti
1742
1567
  const sandbox = buildSandboxFromEnvs(envs, destinations, tracker);
1743
1568
  Object.assign(window, sandbox.window);
1744
1569
  Object.assign(window.document, sandbox.document);
1745
- const bundleCode = await fs8.readFile(bundlePath, "utf8");
1570
+ const bundleCode = await fs7.readFile(bundlePath, "utf8");
1746
1571
  try {
1747
1572
  window.eval(bundleCode);
1748
1573
  } catch (error) {
@@ -1881,10 +1706,7 @@ async function loadDestinationEnvs(destinations) {
1881
1706
  simulation: envModule.simulation || []
1882
1707
  };
1883
1708
  }
1884
- } catch (error) {
1885
- console.warn(
1886
- `Warning: Could not load env for destination "${destKey}": ${error instanceof Error ? error.message : String(error)}`
1887
- );
1709
+ } catch {
1888
1710
  }
1889
1711
  }
1890
1712
  return envs;
@@ -1941,7 +1763,7 @@ function formatSimulationResult(result, options = {}) {
1941
1763
  async function executeSimulation(event, configPath) {
1942
1764
  const startTime = Date.now();
1943
1765
  let bundlePath;
1944
- const tempDir = getTempDir();
1766
+ const tempDir = getTmpPath();
1945
1767
  try {
1946
1768
  if (!isObject(event) || !("name" in event) || typeof event.name !== "string") {
1947
1769
  throw new Error(
@@ -1949,7 +1771,7 @@ async function executeSimulation(event, configPath) {
1949
1771
  );
1950
1772
  }
1951
1773
  const typedEvent = event;
1952
- await fs9.ensureDir(tempDir);
1774
+ await fs8.ensureDir(tempDir);
1953
1775
  const rawConfig = await loadJsonConfig(configPath);
1954
1776
  const { flowConfig, buildOptions } = loadBundleConfig(rawConfig, {
1955
1777
  configPath
@@ -2023,7 +1845,7 @@ async function executeSimulation(event, configPath) {
2023
1845
  };
2024
1846
  } finally {
2025
1847
  if (tempDir) {
2026
- await fs9.remove(tempDir).catch(() => {
1848
+ await fs8.remove(tempDir).catch(() => {
2027
1849
  });
2028
1850
  }
2029
1851
  }
@@ -2032,59 +1854,50 @@ async function executeSimulation(event, configPath) {
2032
1854
  // src/commands/simulate/index.ts
2033
1855
  async function simulateCommand(options) {
2034
1856
  const logger2 = createCommandLogger(options);
2035
- const dockerArgs = buildCommonDockerArgs(options);
2036
- if (options.event) dockerArgs.push("--event", options.event);
2037
- await executeCommand(
2038
- async () => {
2039
- const startTime = Date.now();
2040
- try {
2041
- const event = await loadJsonFromSource(options.event, {
2042
- name: "event"
2043
- });
2044
- const result = await simulateCore(options.config, event, {
2045
- json: options.json,
2046
- verbose: options.verbose,
2047
- silent: options.silent
2048
- });
2049
- const resultWithDuration = {
2050
- ...result,
2051
- duration: (Date.now() - startTime) / 1e3
2052
- };
2053
- const outputLogger = createLogger({ silent: false, json: false });
2054
- const output = formatSimulationResult(resultWithDuration, {
2055
- json: options.json
2056
- });
2057
- outputLogger.log("white", output);
2058
- if (!result.success) {
2059
- process.exit(1);
2060
- }
2061
- } catch (error) {
2062
- const errorMessage = getErrorMessage(error);
2063
- if (options.json) {
2064
- const outputLogger = createLogger({ silent: false, json: false });
2065
- const errorOutput = JSON.stringify(
2066
- {
2067
- success: false,
2068
- error: errorMessage,
2069
- duration: (Date.now() - startTime) / 1e3
2070
- },
2071
- null,
2072
- 2
2073
- );
2074
- outputLogger.log("white", errorOutput);
2075
- } else {
2076
- const errorLogger = createLogger({ silent: false, json: false });
2077
- errorLogger.error(`\u274C Simulate command failed: ${errorMessage}`);
2078
- }
2079
- process.exit(1);
2080
- }
2081
- },
2082
- "simulate",
2083
- dockerArgs,
2084
- options,
2085
- logger2,
2086
- options.config
2087
- );
1857
+ if (options.dryRun) {
1858
+ logger2.log(
1859
+ `[DRY-RUN] Would execute simulate with config: ${options.config}`
1860
+ );
1861
+ return;
1862
+ }
1863
+ const startTime = Date.now();
1864
+ try {
1865
+ const event = await loadJsonFromSource(options.event, {
1866
+ name: "event"
1867
+ });
1868
+ const result = await simulateCore(options.config, event, {
1869
+ json: options.json,
1870
+ verbose: options.verbose,
1871
+ silent: options.silent
1872
+ });
1873
+ const resultWithDuration = {
1874
+ ...result,
1875
+ duration: (Date.now() - startTime) / 1e3
1876
+ };
1877
+ if (options.json) {
1878
+ logger2.json(resultWithDuration);
1879
+ } else {
1880
+ const output = formatSimulationResult(resultWithDuration, {
1881
+ json: false
1882
+ });
1883
+ logger2.log(output);
1884
+ }
1885
+ if (!result.success) {
1886
+ process.exit(1);
1887
+ }
1888
+ } catch (error) {
1889
+ const errorMessage = getErrorMessage(error);
1890
+ if (options.json) {
1891
+ logger2.json({
1892
+ success: false,
1893
+ error: errorMessage,
1894
+ duration: (Date.now() - startTime) / 1e3
1895
+ });
1896
+ } else {
1897
+ logger2.error(`Error: ${errorMessage}`);
1898
+ }
1899
+ process.exit(1);
1900
+ }
2088
1901
  }
2089
1902
  async function simulate(configOrPath, event, options = {}) {
2090
1903
  if (typeof configOrPath !== "string") {
@@ -2101,153 +1914,125 @@ async function simulate(configOrPath, event, options = {}) {
2101
1914
  // src/commands/push/index.ts
2102
1915
  import path11 from "path";
2103
1916
  import { JSDOM as JSDOM2, VirtualConsole as VirtualConsole2 } from "jsdom";
2104
- import fs10 from "fs-extra";
1917
+ import fs9 from "fs-extra";
2105
1918
  import { getPlatform as getPlatform3 } from "@walkeros/core";
2106
1919
  import { schemas as schemas2 } from "@walkeros/core/dev";
2107
1920
  async function pushCommand(options) {
2108
1921
  const logger2 = createCommandLogger(options);
2109
- const dockerArgs = buildCommonDockerArgs(options);
2110
- dockerArgs.push("--event", options.event);
2111
- if (options.flow) dockerArgs.push("--flow", options.flow);
2112
- await executeCommand(
2113
- async () => {
2114
- const startTime = Date.now();
2115
- try {
2116
- logger2.info("\u{1F4E5} Loading event...");
2117
- const event = await loadJsonFromSource(options.event, {
2118
- name: "event"
2119
- });
2120
- const eventResult = schemas2.PartialEventSchema.safeParse(event);
2121
- if (!eventResult.success) {
2122
- const errors = eventResult.error.issues.map((issue) => `${String(issue.path.join("."))}: ${issue.message}`).join(", ");
2123
- throw new Error(`Invalid event: ${errors}`);
2124
- }
2125
- const parsedEvent = eventResult.data;
2126
- if (!parsedEvent.name) {
2127
- throw new Error('Invalid event: Missing required "name" property');
2128
- }
2129
- const validatedEvent = {
2130
- name: parsedEvent.name,
2131
- data: parsedEvent.data || {}
2132
- };
2133
- if (!validatedEvent.name.includes(" ")) {
2134
- logger2.warn(
2135
- `Event name "${validatedEvent.name}" should follow "ENTITY ACTION" format (e.g., "page view")`
2136
- );
2137
- }
2138
- logger2.info("\u{1F4E6} Loading flow configuration...");
2139
- const configPath = path11.resolve(options.config);
2140
- const rawConfig = await loadJsonConfig(configPath);
2141
- const { flowConfig, buildOptions, flowName, isMultiFlow } = loadBundleConfig(rawConfig, {
2142
- configPath: options.config,
2143
- flowName: options.flow,
2144
- logger: logger2
2145
- });
2146
- const platform = getPlatform3(flowConfig);
2147
- logger2.info("\u{1F528} Bundling flow configuration...");
2148
- const configDir = path11.dirname(configPath);
2149
- const tempDir = path11.join(
2150
- configDir,
2151
- ".tmp",
2152
- `push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
2153
- );
2154
- await fs10.ensureDir(tempDir);
2155
- const tempPath = path11.join(
2156
- tempDir,
2157
- `bundle.${platform === "web" ? "js" : "mjs"}`
2158
- );
2159
- const pushBuildOptions = {
2160
- ...buildOptions,
2161
- output: tempPath,
2162
- // Web uses IIFE for browser-like execution, server uses ESM
2163
- format: platform === "web" ? "iife" : "esm",
2164
- platform: platform === "web" ? "browser" : "node",
2165
- ...platform === "web" && {
2166
- windowCollector: "collector",
2167
- windowElb: "elb"
1922
+ const startTime = Date.now();
1923
+ try {
1924
+ logger2.debug("Loading event");
1925
+ const event = await loadJsonFromSource(options.event, {
1926
+ name: "event"
1927
+ });
1928
+ const eventResult = schemas2.PartialEventSchema.safeParse(event);
1929
+ if (!eventResult.success) {
1930
+ const errors = eventResult.error.issues.map((issue) => `${String(issue.path.join("."))}: ${issue.message}`).join(", ");
1931
+ throw new Error(`Invalid event: ${errors}`);
1932
+ }
1933
+ const parsedEvent = eventResult.data;
1934
+ if (!parsedEvent.name) {
1935
+ throw new Error('Invalid event: Missing required "name" property');
1936
+ }
1937
+ const validatedEvent = {
1938
+ name: parsedEvent.name,
1939
+ data: parsedEvent.data || {}
1940
+ };
1941
+ if (!validatedEvent.name.includes(" ")) {
1942
+ logger2.log(
1943
+ `Warning: Event name "${validatedEvent.name}" should follow "ENTITY ACTION" format (e.g., "page view")`
1944
+ );
1945
+ }
1946
+ logger2.debug("Loading flow configuration");
1947
+ const configPath = path11.resolve(options.config);
1948
+ const rawConfig = await loadJsonConfig(configPath);
1949
+ const { flowConfig, buildOptions, flowName, isMultiFlow } = loadBundleConfig(rawConfig, {
1950
+ configPath: options.config,
1951
+ flowName: options.flow,
1952
+ logger: logger2
1953
+ });
1954
+ const platform = getPlatform3(flowConfig);
1955
+ logger2.debug("Bundling flow configuration");
1956
+ const configDir = path11.dirname(configPath);
1957
+ const tempDir = path11.join(
1958
+ configDir,
1959
+ ".tmp",
1960
+ `push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
1961
+ );
1962
+ await fs9.ensureDir(tempDir);
1963
+ const tempPath = path11.join(
1964
+ tempDir,
1965
+ `bundle.${platform === "web" ? "js" : "mjs"}`
1966
+ );
1967
+ const pushBuildOptions = {
1968
+ ...buildOptions,
1969
+ output: tempPath,
1970
+ // Web uses IIFE for browser-like execution, server uses ESM
1971
+ format: platform === "web" ? "iife" : "esm",
1972
+ platform: platform === "web" ? "browser" : "node",
1973
+ ...platform === "web" && {
1974
+ windowCollector: "collector",
1975
+ windowElb: "elb"
1976
+ }
1977
+ };
1978
+ await bundleCore(flowConfig, pushBuildOptions, logger2, false);
1979
+ logger2.debug(`Bundle created: ${tempPath}`);
1980
+ let result;
1981
+ if (platform === "web") {
1982
+ logger2.debug("Executing in web environment (JSDOM)");
1983
+ result = await executeWebPush(tempPath, validatedEvent, logger2);
1984
+ } else if (platform === "server") {
1985
+ logger2.debug("Executing in server environment (Node.js)");
1986
+ result = await executeServerPush(tempPath, validatedEvent, logger2);
1987
+ } else {
1988
+ throw new Error(`Unsupported platform: ${platform}`);
1989
+ }
1990
+ const duration = Date.now() - startTime;
1991
+ if (options.json) {
1992
+ logger2.json({
1993
+ success: result.success,
1994
+ event: result.elbResult,
1995
+ duration
1996
+ });
1997
+ } else {
1998
+ if (result.success) {
1999
+ logger2.log("Event pushed successfully");
2000
+ if (result.elbResult && typeof result.elbResult === "object") {
2001
+ const pushResult = result.elbResult;
2002
+ if ("id" in pushResult && pushResult.id) {
2003
+ logger2.log(` Event ID: ${pushResult.id}`);
2168
2004
  }
2169
- };
2170
- await bundleCore(flowConfig, pushBuildOptions, logger2, false);
2171
- logger2.debug(`Bundle created: ${tempPath}`);
2172
- let result;
2173
- if (platform === "web") {
2174
- logger2.info("\u{1F310} Executing in web environment (JSDOM)...");
2175
- result = await executeWebPush(tempPath, validatedEvent, logger2);
2176
- } else if (platform === "server") {
2177
- logger2.info("\u{1F5A5}\uFE0F Executing in server environment (Node.js)...");
2178
- result = await executeServerPush(tempPath, validatedEvent, logger2);
2179
- } else {
2180
- throw new Error(`Unsupported platform: ${platform}`);
2181
- }
2182
- const duration = Date.now() - startTime;
2183
- if (options.json) {
2184
- const outputLogger = createLogger({ silent: false, json: false });
2185
- outputLogger.log(
2186
- "white",
2187
- JSON.stringify(
2188
- {
2189
- success: result.success,
2190
- event: result.elbResult,
2191
- duration
2192
- },
2193
- null,
2194
- 2
2195
- )
2196
- );
2197
- } else {
2198
- if (result.success) {
2199
- logger2.success("\u2705 Event pushed successfully");
2200
- if (result.elbResult && typeof result.elbResult === "object") {
2201
- const pushResult = result.elbResult;
2202
- if ("id" in pushResult && pushResult.id) {
2203
- logger2.info(` Event ID: ${pushResult.id}`);
2204
- }
2205
- if ("entity" in pushResult && pushResult.entity) {
2206
- logger2.info(` Entity: ${pushResult.entity}`);
2207
- }
2208
- if ("action" in pushResult && pushResult.action) {
2209
- logger2.info(` Action: ${pushResult.action}`);
2210
- }
2211
- }
2212
- logger2.info(` Duration: ${duration}ms`);
2213
- } else {
2214
- logger2.error(`\u274C Push failed: ${result.error}`);
2215
- process.exit(1);
2005
+ if ("entity" in pushResult && pushResult.entity) {
2006
+ logger2.log(` Entity: ${pushResult.entity}`);
2007
+ }
2008
+ if ("action" in pushResult && pushResult.action) {
2009
+ logger2.log(` Action: ${pushResult.action}`);
2216
2010
  }
2217
2011
  }
2218
- try {
2219
- await fs10.remove(tempDir);
2220
- } catch {
2221
- }
2222
- } catch (error) {
2223
- const duration = Date.now() - startTime;
2224
- const errorMessage = getErrorMessage(error);
2225
- if (options.json) {
2226
- const outputLogger = createLogger({ silent: false, json: false });
2227
- outputLogger.log(
2228
- "white",
2229
- JSON.stringify(
2230
- {
2231
- success: false,
2232
- error: errorMessage,
2233
- duration
2234
- },
2235
- null,
2236
- 2
2237
- )
2238
- );
2239
- } else {
2240
- logger2.error(`\u274C Push command failed: ${errorMessage}`);
2241
- }
2012
+ logger2.log(` Duration: ${duration}ms`);
2013
+ } else {
2014
+ logger2.error(`Error: ${result.error}`);
2242
2015
  process.exit(1);
2243
2016
  }
2244
- },
2245
- "push",
2246
- dockerArgs,
2247
- options,
2248
- logger2,
2249
- options.config
2250
- );
2017
+ }
2018
+ try {
2019
+ await fs9.remove(tempDir);
2020
+ } catch {
2021
+ }
2022
+ } catch (error) {
2023
+ const duration = Date.now() - startTime;
2024
+ const errorMessage = getErrorMessage(error);
2025
+ if (options.json) {
2026
+ logger2.json({
2027
+ success: false,
2028
+ error: errorMessage,
2029
+ duration
2030
+ });
2031
+ } else {
2032
+ logger2.error(`Error: ${errorMessage}`);
2033
+ }
2034
+ process.exit(1);
2035
+ }
2251
2036
  }
2252
2037
  async function executeWebPush(bundlePath, event, logger2) {
2253
2038
  const startTime = Date.now();
@@ -2261,7 +2046,7 @@ async function executeWebPush(bundlePath, event, logger2) {
2261
2046
  });
2262
2047
  const { window } = dom;
2263
2048
  logger2.debug("Loading bundle...");
2264
- const bundleCode = await fs10.readFile(bundlePath, "utf8");
2049
+ const bundleCode = await fs9.readFile(bundlePath, "utf8");
2265
2050
  window.eval(bundleCode);
2266
2051
  logger2.debug("Waiting for elb...");
2267
2052
  await waitForWindowProperty2(
@@ -2271,7 +2056,7 @@ async function executeWebPush(bundlePath, event, logger2) {
2271
2056
  );
2272
2057
  const windowObj = window;
2273
2058
  const elb = windowObj.elb;
2274
- logger2.info(`Pushing event: ${event.name}`);
2059
+ logger2.log(`Pushing event: ${event.name}`);
2275
2060
  const elbResult = await elb(event.name, event.data);
2276
2061
  return {
2277
2062
  success: true,
@@ -2309,7 +2094,7 @@ async function executeServerPush(bundlePath, event, logger2, timeout = 6e4) {
2309
2094
  );
2310
2095
  }
2311
2096
  const { elb } = result;
2312
- logger2.info(`Pushing event: ${event.name}`);
2097
+ logger2.log(`Pushing event: ${event.name}`);
2313
2098
  const elbResult = await elb(event.name, event.data);
2314
2099
  return {
2315
2100
  success: true,
@@ -2327,11 +2112,11 @@ async function executeServerPush(bundlePath, event, logger2, timeout = 6e4) {
2327
2112
  }
2328
2113
  }
2329
2114
  function waitForWindowProperty2(window, prop, timeout = 5e3) {
2330
- return new Promise((resolve, reject) => {
2115
+ return new Promise((resolve3, reject) => {
2331
2116
  const start = Date.now();
2332
2117
  const check = () => {
2333
2118
  if (window[prop] !== void 0) {
2334
- resolve();
2119
+ resolve3();
2335
2120
  } else if (Date.now() - start > timeout) {
2336
2121
  reject(
2337
2122
  new Error(
@@ -2402,7 +2187,7 @@ function validatePort(port) {
2402
2187
 
2403
2188
  // src/commands/run/utils.ts
2404
2189
  import path12 from "path";
2405
- import fs11 from "fs-extra";
2190
+ import fs10 from "fs-extra";
2406
2191
  async function prepareBundleForRun(configPath, options) {
2407
2192
  const configDir = path12.dirname(path12.resolve(configPath));
2408
2193
  const tempDir = path12.join(
@@ -2410,7 +2195,7 @@ async function prepareBundleForRun(configPath, options) {
2410
2195
  ".tmp",
2411
2196
  `run-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
2412
2197
  );
2413
- await fs11.ensureDir(tempDir);
2198
+ await fs10.ensureDir(tempDir);
2414
2199
  const tempPath = path12.join(tempDir, "bundle.mjs");
2415
2200
  await bundle(configPath, {
2416
2201
  cache: true,
@@ -2430,7 +2215,128 @@ function isPreBuiltConfig(configPath) {
2430
2215
 
2431
2216
  // src/commands/run/execution.ts
2432
2217
  import { createLogger as createLogger2, Level } from "@walkeros/core";
2433
- import { runFlow, runServeMode } from "@walkeros/docker";
2218
+
2219
+ // src/runtime/runner.ts
2220
+ import { pathToFileURL as pathToFileURL2 } from "url";
2221
+ import { resolve, dirname as dirname2 } from "path";
2222
+ async function runFlow(file, config, logger2) {
2223
+ logger2.info(`Loading flow from ${file}`);
2224
+ try {
2225
+ const absolutePath = resolve(file);
2226
+ const flowDir = dirname2(absolutePath);
2227
+ process.chdir(flowDir);
2228
+ const fileUrl = pathToFileURL2(absolutePath).href;
2229
+ const module = await import(fileUrl);
2230
+ if (!module.default || typeof module.default !== "function") {
2231
+ logger2.throw(
2232
+ `Invalid flow bundle: ${file} must export a default function`
2233
+ );
2234
+ }
2235
+ const result = await module.default(config);
2236
+ if (!result || !result.collector) {
2237
+ logger2.throw(`Invalid flow bundle: ${file} must return { collector }`);
2238
+ }
2239
+ const { collector } = result;
2240
+ logger2.info("Flow running");
2241
+ if (config?.port) {
2242
+ logger2.info(`Port: ${config.port}`);
2243
+ }
2244
+ const shutdown = async (signal) => {
2245
+ logger2.info(`Received ${signal}, shutting down gracefully...`);
2246
+ try {
2247
+ if (collector.command) {
2248
+ await collector.command("shutdown");
2249
+ }
2250
+ logger2.info("Shutdown complete");
2251
+ process.exit(0);
2252
+ } catch (error) {
2253
+ const message = error instanceof Error ? error.message : String(error);
2254
+ logger2.error(`Error during shutdown: ${message}`);
2255
+ process.exit(1);
2256
+ }
2257
+ };
2258
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
2259
+ process.on("SIGINT", () => shutdown("SIGINT"));
2260
+ await new Promise(() => {
2261
+ });
2262
+ } catch (error) {
2263
+ const message = error instanceof Error ? error.message : String(error);
2264
+ logger2.error(`Failed to run flow: ${message}`);
2265
+ if (error instanceof Error && error.stack) {
2266
+ logger2.debug("Stack trace:", { stack: error.stack });
2267
+ }
2268
+ throw error;
2269
+ }
2270
+ }
2271
+
2272
+ // src/runtime/serve.ts
2273
+ import express from "express";
2274
+ import { resolve as resolve2 } from "path";
2275
+ async function runServeMode(config, logger2) {
2276
+ const port = process.env.PORT ? parseInt(process.env.PORT, 10) : config?.port || 8080;
2277
+ const host = process.env.HOST || config?.host || "0.0.0.0";
2278
+ const file = resolve2(process.env.FILE || config?.file || "./dist/walker.js");
2279
+ const serveName = process.env.SERVE_NAME || config?.serveName || "walker.js";
2280
+ const servePath = process.env.SERVE_PATH || config?.servePath || "";
2281
+ const urlPath = servePath ? `/${servePath}/${serveName}` : `/${serveName}`;
2282
+ logger2.info("Starting single-file server...");
2283
+ logger2.info(`File: ${file}`);
2284
+ logger2.info(`URL: http://${host}:${port}${urlPath}`);
2285
+ try {
2286
+ const app = express();
2287
+ app.get("/health", (req, res) => {
2288
+ res.json({
2289
+ status: "ok",
2290
+ version: VERSION,
2291
+ timestamp: Date.now(),
2292
+ mode: "serve",
2293
+ file,
2294
+ url: urlPath
2295
+ });
2296
+ });
2297
+ app.get(urlPath, (req, res) => {
2298
+ res.type("application/javascript");
2299
+ res.sendFile(file, { dotfiles: "allow" }, (err) => {
2300
+ if (err && !res.headersSent) {
2301
+ const errCode = err.code;
2302
+ const errStatus = err.status || err.statusCode;
2303
+ if (errCode !== "ECONNABORTED") {
2304
+ logger2.error(
2305
+ `sendFile error for ${file}: ${err.message} (code: ${errCode}, status: ${errStatus})`
2306
+ );
2307
+ }
2308
+ if (errStatus === 404 || errCode === "ENOENT" || errCode === "EISDIR" || errCode === "ENOTDIR") {
2309
+ res.status(404).send("File not found");
2310
+ } else if (errCode !== "ECONNABORTED") {
2311
+ res.status(500).send("Internal server error");
2312
+ }
2313
+ }
2314
+ });
2315
+ });
2316
+ const server = app.listen(port, host, () => {
2317
+ logger2.info(`Server listening on http://${host}:${port}`);
2318
+ logger2.info(`GET ${urlPath} - Bundle file`);
2319
+ logger2.info(`GET /health - Health check`);
2320
+ });
2321
+ const shutdownHandler = (signal) => {
2322
+ logger2.info(`Received ${signal}, shutting down...`);
2323
+ server.close(() => {
2324
+ logger2.info("Server closed");
2325
+ process.exit(0);
2326
+ });
2327
+ };
2328
+ process.on("SIGTERM", () => shutdownHandler("SIGTERM"));
2329
+ process.on("SIGINT", () => shutdownHandler("SIGINT"));
2330
+ await new Promise(() => {
2331
+ });
2332
+ } catch (error) {
2333
+ const message = error instanceof Error ? error.message : String(error);
2334
+ logger2.error(`Server failed: ${message}`);
2335
+ process.exit(1);
2336
+ }
2337
+ }
2338
+
2339
+ // src/commands/run/execution.ts
2434
2340
  var logLevel = process.env.VERBOSE === "true" ? Level.DEBUG : Level.INFO;
2435
2341
  var logger = createLogger2({ level: logLevel });
2436
2342
  async function executeRunLocal(mode, flowPath, options) {
@@ -2478,76 +2384,40 @@ async function runCommand(mode, options) {
2478
2384
  if (mode === "collect") {
2479
2385
  if (isPreBuilt) {
2480
2386
  flowPath = path13.resolve(configPath);
2481
- if (!options.json && !options.silent) {
2482
- logger2.info(`\u{1F4E6} Using pre-built flow: ${path13.basename(flowPath)}`);
2483
- }
2387
+ logger2.debug(`Using pre-built flow: ${path13.basename(flowPath)}`);
2484
2388
  } else {
2485
- if (!options.json && !options.silent) {
2486
- logger2.info("\u{1F528} Building flow bundle...");
2487
- }
2389
+ logger2.debug("Building flow bundle");
2488
2390
  flowPath = await prepareBundleForRun(configPath, {
2489
2391
  verbose: options.verbose,
2490
2392
  silent: options.json || options.silent
2491
2393
  });
2492
- if (!options.json && !options.silent) {
2493
- logger2.success("\u2705 Bundle ready");
2494
- }
2394
+ logger2.debug("Bundle ready");
2495
2395
  }
2496
2396
  }
2497
- const executionMode = getExecutionMode(options);
2498
2397
  if (options.dryRun) {
2499
- if (executionMode === "docker") {
2500
- logger2.info(
2501
- `[DRY-RUN] Would execute in Docker: run ${mode} with runtime image`
2502
- );
2503
- } else {
2504
- logger2.info(`[DRY-RUN] Would execute locally: run ${mode}`);
2505
- }
2398
+ logger2.log(`[DRY-RUN] Would execute locally: run ${mode}`);
2506
2399
  return;
2507
2400
  }
2508
- if (executionMode === "docker") {
2509
- const dockerAvailable = await isDockerAvailable();
2510
- if (!dockerAvailable) {
2511
- throw new Error(
2512
- "Docker is not available. Please install Docker or use --local flag to execute locally."
2513
- );
2514
- }
2515
- if (!options.json && !options.silent) {
2516
- logger2.info("\u{1F433} Executing in production runtime container...");
2517
- }
2518
- await executeRunInDocker(mode, flowPath, {
2519
- port: options.port,
2520
- host: options.host,
2521
- serveName: options.serveName,
2522
- servePath: options.servePath,
2523
- silent: options.silent
2524
- });
2525
- } else {
2526
- if (!options.json && !options.silent) {
2527
- const modeLabel = mode === "collect" ? "Collector" : "Server";
2528
- logger2.info(`\u{1F5A5}\uFE0F Starting ${modeLabel} locally...`);
2529
- }
2530
- await executeRunLocal(mode, flowPath, {
2531
- port: options.port,
2532
- host: options.host,
2533
- serveName: options.serveName,
2534
- servePath: options.servePath
2535
- });
2536
- }
2401
+ const modeLabel = mode === "collect" ? "Collector" : "Server";
2402
+ logger2.log(`Starting ${modeLabel}...`);
2403
+ await executeRunLocal(mode, flowPath, {
2404
+ port: options.port,
2405
+ host: options.host,
2406
+ serveName: options.serveName,
2407
+ servePath: options.servePath
2408
+ });
2537
2409
  } catch (error) {
2538
2410
  const duration = timer.getElapsed() / 1e3;
2539
2411
  const errorMessage = getErrorMessage(error);
2540
2412
  if (options.json) {
2541
- const output = {
2413
+ logger2.json({
2542
2414
  success: false,
2543
2415
  mode,
2544
2416
  error: errorMessage,
2545
2417
  duration
2546
- };
2547
- console.log(JSON.stringify(output, null, 2));
2418
+ });
2548
2419
  } else {
2549
- logger2.error("\u274C Run failed:");
2550
- logger2.error(errorMessage);
2420
+ logger2.error(`Error: ${errorMessage}`);
2551
2421
  }
2552
2422
  process.exit(1);
2553
2423
  }
@@ -2597,56 +2467,59 @@ async function run(mode, options) {
2597
2467
  }
2598
2468
 
2599
2469
  // src/commands/cache.ts
2600
- import fs12 from "fs-extra";
2601
- import path14 from "path";
2602
- var CACHE_DIR = path14.join(".tmp", "cache");
2470
+ import fs11 from "fs-extra";
2603
2471
  function registerCacheCommand(program2) {
2604
2472
  const cache = program2.command("cache").description("Manage the CLI cache");
2605
- cache.command("clear").description("Clear all cached packages and builds").option("--packages", "Clear only package cache").option("--builds", "Clear only build cache").action(async (options) => {
2473
+ 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) => {
2474
+ const logger2 = createLogger({ silent: options.silent });
2475
+ const tmpDir = options.tmpDir;
2606
2476
  if (options.packages) {
2607
- await fs12.remove(path14.join(CACHE_DIR, "packages"));
2608
- console.log("Package cache cleared");
2477
+ await fs11.remove(getTmpPath(tmpDir, "cache", "packages"));
2478
+ logger2.log("Package cache cleared");
2609
2479
  } else if (options.builds) {
2610
- await fs12.remove(path14.join(CACHE_DIR, "builds"));
2611
- console.log("Build cache cleared");
2480
+ await fs11.remove(getTmpPath(tmpDir, "cache", "builds"));
2481
+ logger2.log("Build cache cleared");
2612
2482
  } else {
2613
- await fs12.remove(CACHE_DIR);
2614
- console.log("All caches cleared");
2483
+ await fs11.remove(getTmpPath(tmpDir, "cache"));
2484
+ logger2.log("All caches cleared");
2615
2485
  }
2616
2486
  });
2617
- cache.command("info").description("Show cache statistics").action(async () => {
2618
- const packagesDir = path14.join(CACHE_DIR, "packages");
2619
- const buildsDir = path14.join(CACHE_DIR, "builds");
2487
+ cache.command("info").description("Show cache statistics").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
2488
+ const logger2 = createLogger({ silent: options.silent });
2489
+ const tmpDir = options.tmpDir;
2490
+ const packagesDir = getTmpPath(tmpDir, "cache", "packages");
2491
+ const buildsDir = getTmpPath(tmpDir, "cache", "builds");
2620
2492
  const packageCount = await countEntries(packagesDir);
2621
2493
  const buildCount = await countEntries(buildsDir);
2622
- console.log(`Cache directory: ${CACHE_DIR}`);
2623
- console.log(`Cached packages: ${packageCount}`);
2624
- console.log(`Cached builds: ${buildCount}`);
2494
+ logger2.log(`Cache directory: ${getTmpPath(tmpDir, "cache")}`);
2495
+ logger2.log(`Cached packages: ${packageCount}`);
2496
+ logger2.log(`Cached builds: ${buildCount}`);
2497
+ });
2498
+ }
2499
+ function registerCleanCommand(program2) {
2500
+ program2.command("clean").description("Clear the entire temp directory (.tmp/)").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
2501
+ const logger2 = createLogger({ silent: options.silent });
2502
+ const tmpDir = options.tmpDir || getDefaultTmpRoot();
2503
+ await fs11.remove(tmpDir);
2504
+ logger2.log(`Temp directory cleared: ${tmpDir}`);
2625
2505
  });
2626
2506
  }
2627
2507
  async function countEntries(dir) {
2628
- if (!await fs12.pathExists(dir)) return 0;
2629
- const entries = await fs12.readdir(dir);
2508
+ if (!await fs11.pathExists(dir)) return 0;
2509
+ const entries = await fs11.readdir(dir);
2630
2510
  return entries.length;
2631
2511
  }
2632
2512
 
2633
2513
  // src/index.ts
2634
- var __filename = fileURLToPath2(import.meta.url);
2635
- var __dirname = dirname(__filename);
2636
- var packageJson = JSON.parse(
2637
- readFileSync(join(__dirname, "../package.json"), "utf-8")
2638
- );
2639
- var VERSION = packageJson.version;
2640
2514
  var program = new Command();
2641
2515
  program.name("walkeros").description("walkerOS CLI - Bundle and deploy walkerOS components").version(VERSION);
2642
2516
  program.hook("preAction", (thisCommand, actionCommand) => {
2643
2517
  const options = actionCommand.opts();
2644
2518
  if (!options.silent && !options.json) {
2645
- console.log(`\u{1F680} walkerOS CLI v${VERSION}`);
2646
- console.log(`\u{1F433} Using Docker runtime: walkeros/docker:${DOCKER_VERSION2}`);
2519
+ console.log(chalk2.hex("#01b5e2")(`walkerOS v${VERSION}`));
2647
2520
  }
2648
2521
  });
2649
- program.command("bundle [file]").description("Bundle NPM packages with custom code").option("-f, --flow <name>", "flow to build (for multi-flow configs)").option("--all", "build all flows (for multi-flow configs)").option("-s, --stats", "show bundle statistics").option("--json", "output statistics in JSON format (implies --stats)").option("--no-cache", "disable package caching and download fresh packages").option("-v, --verbose", "verbose output").option("--local", "execute in local Node.js instead of Docker").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
2522
+ program.command("bundle [file]").description("Bundle NPM packages with custom code").option("-f, --flow <name>", "flow to build (for multi-flow configs)").option("--all", "build all flows (for multi-flow configs)").option("-s, --stats", "show bundle statistics").option("--json", "output statistics in JSON format (implies --stats)").option("--no-cache", "disable package caching and download fresh packages").option("-v, --verbose", "verbose output").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
2650
2523
  await bundleCommand({
2651
2524
  config: file || "bundle.config.json",
2652
2525
  flow: options.flow,
@@ -2655,7 +2528,6 @@ program.command("bundle [file]").description("Bundle NPM packages with custom co
2655
2528
  json: options.json,
2656
2529
  cache: options.cache,
2657
2530
  verbose: options.verbose,
2658
- local: options.local,
2659
2531
  dryRun: options.dryRun,
2660
2532
  silent: options.silent
2661
2533
  });
@@ -2663,13 +2535,12 @@ program.command("bundle [file]").description("Bundle NPM packages with custom co
2663
2535
  program.command("simulate [file]").description("Simulate event processing and capture API calls").option(
2664
2536
  "-e, --event <source>",
2665
2537
  "Event to simulate (JSON string, file path, or URL)"
2666
- ).option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--local", "execute in local Node.js instead of Docker").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
2538
+ ).option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
2667
2539
  await simulateCommand({
2668
2540
  config: file || "bundle.config.json",
2669
2541
  event: options.event,
2670
2542
  json: options.json,
2671
2543
  verbose: options.verbose,
2672
- local: options.local,
2673
2544
  dryRun: options.dryRun,
2674
2545
  silent: options.silent
2675
2546
  });
@@ -2677,35 +2548,33 @@ program.command("simulate [file]").description("Simulate event processing and ca
2677
2548
  program.command("push [file]").description("Push an event through the flow with real API execution").requiredOption(
2678
2549
  "-e, --event <source>",
2679
2550
  "Event to push (JSON string, file path, or URL)"
2680
- ).option("--flow <name>", "Flow name (for multi-flow configs)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("-s, --silent", "Suppress output").option("--local", "Execute in local Node.js instead of Docker").action(async (file, options) => {
2551
+ ).option("--flow <name>", "Flow name (for multi-flow configs)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("-s, --silent", "Suppress output").action(async (file, options) => {
2681
2552
  await pushCommand({
2682
2553
  config: file || "bundle.config.json",
2683
2554
  event: options.event,
2684
2555
  flow: options.flow,
2685
2556
  json: options.json,
2686
2557
  verbose: options.verbose,
2687
- silent: options.silent,
2688
- local: options.local
2558
+ silent: options.silent
2689
2559
  });
2690
2560
  });
2691
2561
  var runCmd = program.command("run").description("Run walkerOS flows in collect or serve mode");
2692
2562
  runCmd.command("collect [file]").description(
2693
2563
  "Run collector mode (event collection endpoint). Defaults to server-collect.mjs if no file specified."
2694
- ).option("-p, --port <number>", "Port to listen on (default: 8080)", parseInt).option("-h, --host <address>", "Host address (default: 0.0.0.0)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--local", "execute in local Node.js instead of Docker").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
2564
+ ).option("-p, --port <number>", "Port to listen on (default: 8080)", parseInt).option("-h, --host <address>", "Host address (default: 0.0.0.0)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
2695
2565
  await runCommand("collect", {
2696
2566
  config: file || "server-collect.mjs",
2697
2567
  port: options.port,
2698
2568
  host: options.host,
2699
2569
  json: options.json,
2700
2570
  verbose: options.verbose,
2701
- local: options.local,
2702
2571
  dryRun: options.dryRun,
2703
2572
  silent: options.silent
2704
2573
  });
2705
2574
  });
2706
2575
  runCmd.command("serve [file]").description(
2707
2576
  "Run serve mode (single-file server for browser bundles). Defaults to baked-in web-serve.js if no file specified."
2708
- ).option("-p, --port <number>", "Port to listen on (default: 8080)", parseInt).option("-h, --host <address>", "Host address (default: 0.0.0.0)").option("--name <filename>", "Filename in URL (default: walker.js)").option("--path <directory>", "URL directory path (e.g., libs/v1)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--local", "execute in local Node.js instead of Docker").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
2577
+ ).option("-p, --port <number>", "Port to listen on (default: 8080)", parseInt).option("-h, --host <address>", "Host address (default: 0.0.0.0)").option("--name <filename>", "Filename in URL (default: walker.js)").option("--path <directory>", "URL directory path (e.g., libs/v1)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
2709
2578
  await runCommand("serve", {
2710
2579
  config: file || "web-serve.js",
2711
2580
  port: options.port,
@@ -2714,12 +2583,12 @@ runCmd.command("serve [file]").description(
2714
2583
  servePath: options.path,
2715
2584
  json: options.json,
2716
2585
  verbose: options.verbose,
2717
- local: options.local,
2718
2586
  dryRun: options.dryRun,
2719
2587
  silent: options.silent
2720
2588
  });
2721
2589
  });
2722
2590
  registerCacheCommand(program);
2591
+ registerCleanCommand(program);
2723
2592
  program.parse();
2724
2593
  export {
2725
2594
  bundle,