@walkeros/cli 0.5.1-next.1 → 0.6.1-next-1766186076625

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 (255) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +104 -36
  3. package/dist/index.d.ts +22 -13
  4. package/dist/index.js +852 -813
  5. package/dist/index.js.map +1 -1
  6. package/dist/runtime/main.d.ts +2 -0
  7. package/dist/runtime/main.js +269 -0
  8. package/dist/runtime/main.js.map +1 -0
  9. package/package.json +8 -5
  10. package/dist/__tests__/bundle/bundler-helpers.test.d.ts +0 -2
  11. package/dist/__tests__/bundle/bundler-helpers.test.d.ts.map +0 -1
  12. package/dist/__tests__/bundle/bundler-helpers.test.js +0 -151
  13. package/dist/__tests__/bundle/bundler-helpers.test.js.map +0 -1
  14. package/dist/__tests__/bundle/bundler.test.d.ts +0 -2
  15. package/dist/__tests__/bundle/bundler.test.d.ts.map +0 -1
  16. package/dist/__tests__/bundle/bundler.test.js +0 -353
  17. package/dist/__tests__/bundle/bundler.test.js.map +0 -1
  18. package/dist/__tests__/bundle/programmatic.test.d.ts +0 -2
  19. package/dist/__tests__/bundle/programmatic.test.d.ts.map +0 -1
  20. package/dist/__tests__/bundle/programmatic.test.js +0 -148
  21. package/dist/__tests__/bundle/programmatic.test.js.map +0 -1
  22. package/dist/__tests__/cli-e2e.test.d.ts +0 -8
  23. package/dist/__tests__/cli-e2e.test.d.ts.map +0 -1
  24. package/dist/__tests__/cli-e2e.test.js +0 -130
  25. package/dist/__tests__/cli-e2e.test.js.map +0 -1
  26. package/dist/__tests__/cli.test.d.ts +0 -2
  27. package/dist/__tests__/cli.test.d.ts.map +0 -1
  28. package/dist/__tests__/cli.test.js +0 -180
  29. package/dist/__tests__/cli.test.js.map +0 -1
  30. package/dist/__tests__/config-loader.test.d.ts +0 -7
  31. package/dist/__tests__/config-loader.test.d.ts.map +0 -1
  32. package/dist/__tests__/config-loader.test.js +0 -414
  33. package/dist/__tests__/config-loader.test.js.map +0 -1
  34. package/dist/__tests__/core/asset-resolver.test.d.ts +0 -2
  35. package/dist/__tests__/core/asset-resolver.test.d.ts.map +0 -1
  36. package/dist/__tests__/core/asset-resolver.test.js +0 -14
  37. package/dist/__tests__/core/asset-resolver.test.js.map +0 -1
  38. package/dist/__tests__/core/build-cache.test.d.ts +0 -2
  39. package/dist/__tests__/core/build-cache.test.d.ts.map +0 -1
  40. package/dist/__tests__/core/build-cache.test.js +0 -55
  41. package/dist/__tests__/core/build-cache.test.js.map +0 -1
  42. package/dist/__tests__/core/cache-utils.test.d.ts +0 -2
  43. package/dist/__tests__/core/cache-utils.test.d.ts.map +0 -1
  44. package/dist/__tests__/core/cache-utils.test.js +0 -70
  45. package/dist/__tests__/core/cache-utils.test.js.map +0 -1
  46. package/dist/__tests__/core/config.test.d.ts +0 -2
  47. package/dist/__tests__/core/config.test.d.ts.map +0 -1
  48. package/dist/__tests__/core/config.test.js +0 -72
  49. package/dist/__tests__/core/config.test.js.map +0 -1
  50. package/dist/__tests__/core/logger.test.d.ts +0 -2
  51. package/dist/__tests__/core/logger.test.d.ts.map +0 -1
  52. package/dist/__tests__/core/logger.test.js +0 -53
  53. package/dist/__tests__/core/logger.test.js.map +0 -1
  54. package/dist/__tests__/integration/bundle-run.integration.test.d.ts +0 -8
  55. package/dist/__tests__/integration/bundle-run.integration.test.d.ts.map +0 -1
  56. package/dist/__tests__/integration/bundle-run.integration.test.js +0 -54
  57. package/dist/__tests__/integration/bundle-run.integration.test.js.map +0 -1
  58. package/dist/__tests__/push/push.test.d.ts +0 -7
  59. package/dist/__tests__/push/push.test.d.ts.map +0 -1
  60. package/dist/__tests__/push/push.test.js +0 -197
  61. package/dist/__tests__/push/push.test.js.map +0 -1
  62. package/dist/__tests__/simulate/env-loader.test.d.ts +0 -2
  63. package/dist/__tests__/simulate/env-loader.test.d.ts.map +0 -1
  64. package/dist/__tests__/simulate/env-loader.test.js +0 -47
  65. package/dist/__tests__/simulate/env-loader.test.js.map +0 -1
  66. package/dist/__tests__/simulate/node-executor.test.d.ts +0 -5
  67. package/dist/__tests__/simulate/node-executor.test.d.ts.map +0 -1
  68. package/dist/__tests__/simulate/node-executor.test.js +0 -25
  69. package/dist/__tests__/simulate/node-executor.test.js.map +0 -1
  70. package/dist/__tests__/simulate/server-simulate.integration.test.d.ts +0 -5
  71. package/dist/__tests__/simulate/server-simulate.integration.test.d.ts.map +0 -1
  72. package/dist/__tests__/simulate/server-simulate.integration.test.js +0 -58
  73. package/dist/__tests__/simulate/server-simulate.integration.test.js.map +0 -1
  74. package/dist/__tests__/smoke/production.smoke.test.d.ts +0 -8
  75. package/dist/__tests__/smoke/production.smoke.test.d.ts.map +0 -1
  76. package/dist/__tests__/smoke/production.smoke.test.js +0 -65
  77. package/dist/__tests__/smoke/production.smoke.test.js.map +0 -1
  78. package/dist/commands/bundle/bundler.d.ts +0 -32
  79. package/dist/commands/bundle/bundler.d.ts.map +0 -1
  80. package/dist/commands/bundle/bundler.js +0 -583
  81. package/dist/commands/bundle/bundler.js.map +0 -1
  82. package/dist/commands/bundle/index.d.ts +0 -57
  83. package/dist/commands/bundle/index.d.ts.map +0 -1
  84. package/dist/commands/bundle/index.js +0 -200
  85. package/dist/commands/bundle/index.js.map +0 -1
  86. package/dist/commands/bundle/package-manager.d.ts +0 -8
  87. package/dist/commands/bundle/package-manager.d.ts.map +0 -1
  88. package/dist/commands/bundle/package-manager.js +0 -197
  89. package/dist/commands/bundle/package-manager.js.map +0 -1
  90. package/dist/commands/bundle/stats.d.ts +0 -23
  91. package/dist/commands/bundle/stats.d.ts.map +0 -1
  92. package/dist/commands/bundle/stats.js +0 -52
  93. package/dist/commands/bundle/stats.js.map +0 -1
  94. package/dist/commands/cache.d.ts +0 -3
  95. package/dist/commands/cache.d.ts.map +0 -1
  96. package/dist/commands/cache.js +0 -44
  97. package/dist/commands/cache.js.map +0 -1
  98. package/dist/commands/push/index.d.ts +0 -7
  99. package/dist/commands/push/index.d.ts.map +0 -1
  100. package/dist/commands/push/index.js +0 -257
  101. package/dist/commands/push/index.js.map +0 -1
  102. package/dist/commands/push/types.d.ts +0 -21
  103. package/dist/commands/push/types.d.ts.map +0 -1
  104. package/dist/commands/push/types.js +0 -2
  105. package/dist/commands/push/types.js.map +0 -1
  106. package/dist/commands/run/__tests__/run.integration.test.d.ts +0 -8
  107. package/dist/commands/run/__tests__/run.integration.test.d.ts.map +0 -1
  108. package/dist/commands/run/__tests__/run.integration.test.js +0 -52
  109. package/dist/commands/run/__tests__/run.integration.test.js.map +0 -1
  110. package/dist/commands/run/__tests__/validators.test.d.ts +0 -2
  111. package/dist/commands/run/__tests__/validators.test.d.ts.map +0 -1
  112. package/dist/commands/run/__tests__/validators.test.js +0 -80
  113. package/dist/commands/run/__tests__/validators.test.js.map +0 -1
  114. package/dist/commands/run/execution.d.ts +0 -14
  115. package/dist/commands/run/execution.d.ts.map +0 -1
  116. package/dist/commands/run/execution.js +0 -41
  117. package/dist/commands/run/execution.js.map +0 -1
  118. package/dist/commands/run/index.d.ts +0 -39
  119. package/dist/commands/run/index.d.ts.map +0 -1
  120. package/dist/commands/run/index.js +0 -191
  121. package/dist/commands/run/index.js.map +0 -1
  122. package/dist/commands/run/types.d.ts +0 -60
  123. package/dist/commands/run/types.d.ts.map +0 -1
  124. package/dist/commands/run/types.js +0 -7
  125. package/dist/commands/run/types.js.map +0 -1
  126. package/dist/commands/run/utils.d.ts +0 -29
  127. package/dist/commands/run/utils.d.ts.map +0 -1
  128. package/dist/commands/run/utils.js +0 -52
  129. package/dist/commands/run/utils.js.map +0 -1
  130. package/dist/commands/run/validators.d.ts +0 -33
  131. package/dist/commands/run/validators.d.ts.map +0 -1
  132. package/dist/commands/run/validators.js +0 -58
  133. package/dist/commands/run/validators.js.map +0 -1
  134. package/dist/commands/simulate/env-loader.d.ts +0 -19
  135. package/dist/commands/simulate/env-loader.d.ts.map +0 -1
  136. package/dist/commands/simulate/env-loader.js +0 -46
  137. package/dist/commands/simulate/env-loader.js.map +0 -1
  138. package/dist/commands/simulate/index.d.ts +0 -48
  139. package/dist/commands/simulate/index.d.ts.map +0 -1
  140. package/dist/commands/simulate/index.js +0 -116
  141. package/dist/commands/simulate/index.js.map +0 -1
  142. package/dist/commands/simulate/jsdom-executor.d.ts +0 -37
  143. package/dist/commands/simulate/jsdom-executor.d.ts.map +0 -1
  144. package/dist/commands/simulate/jsdom-executor.js +0 -137
  145. package/dist/commands/simulate/jsdom-executor.js.map +0 -1
  146. package/dist/commands/simulate/node-executor.d.ts +0 -28
  147. package/dist/commands/simulate/node-executor.d.ts.map +0 -1
  148. package/dist/commands/simulate/node-executor.js +0 -94
  149. package/dist/commands/simulate/node-executor.js.map +0 -1
  150. package/dist/commands/simulate/simulator.d.ts +0 -14
  151. package/dist/commands/simulate/simulator.d.ts.map +0 -1
  152. package/dist/commands/simulate/simulator.js +0 -162
  153. package/dist/commands/simulate/simulator.js.map +0 -1
  154. package/dist/commands/simulate/tracker.d.ts +0 -30
  155. package/dist/commands/simulate/tracker.d.ts.map +0 -1
  156. package/dist/commands/simulate/tracker.js +0 -96
  157. package/dist/commands/simulate/tracker.js.map +0 -1
  158. package/dist/commands/simulate/types.d.ts +0 -18
  159. package/dist/commands/simulate/types.d.ts.map +0 -1
  160. package/dist/commands/simulate/types.js +0 -2
  161. package/dist/commands/simulate/types.js.map +0 -1
  162. package/dist/config/build-defaults.d.ts +0 -49
  163. package/dist/config/build-defaults.d.ts.map +0 -1
  164. package/dist/config/build-defaults.js +0 -70
  165. package/dist/config/build-defaults.js.map +0 -1
  166. package/dist/config/index.d.ts +0 -13
  167. package/dist/config/index.d.ts.map +0 -1
  168. package/dist/config/index.js +0 -15
  169. package/dist/config/index.js.map +0 -1
  170. package/dist/config/loader.d.ts +0 -81
  171. package/dist/config/loader.d.ts.map +0 -1
  172. package/dist/config/loader.js +0 -155
  173. package/dist/config/loader.js.map +0 -1
  174. package/dist/config/utils.d.ts +0 -114
  175. package/dist/config/utils.d.ts.map +0 -1
  176. package/dist/config/utils.js +0 -257
  177. package/dist/config/utils.js.map +0 -1
  178. package/dist/config/validators.d.ts +0 -52
  179. package/dist/config/validators.d.ts.map +0 -1
  180. package/dist/config/validators.js +0 -85
  181. package/dist/config/validators.js.map +0 -1
  182. package/dist/core/asset-resolver.d.ts +0 -34
  183. package/dist/core/asset-resolver.d.ts.map +0 -1
  184. package/dist/core/asset-resolver.js +0 -70
  185. package/dist/core/asset-resolver.js.map +0 -1
  186. package/dist/core/build-cache.d.ts +0 -23
  187. package/dist/core/build-cache.d.ts.map +0 -1
  188. package/dist/core/build-cache.js +0 -43
  189. package/dist/core/build-cache.js.map +0 -1
  190. package/dist/core/cache-utils.d.ts +0 -27
  191. package/dist/core/cache-utils.d.ts.map +0 -1
  192. package/dist/core/cache-utils.js +0 -60
  193. package/dist/core/cache-utils.js.map +0 -1
  194. package/dist/core/docker.d.ts +0 -99
  195. package/dist/core/docker.d.ts.map +0 -1
  196. package/dist/core/docker.js +0 -253
  197. package/dist/core/docker.js.map +0 -1
  198. package/dist/core/execution.d.ts +0 -34
  199. package/dist/core/execution.d.ts.map +0 -1
  200. package/dist/core/execution.js +0 -64
  201. package/dist/core/execution.js.map +0 -1
  202. package/dist/core/index.d.ts +0 -10
  203. package/dist/core/index.d.ts.map +0 -1
  204. package/dist/core/index.js +0 -10
  205. package/dist/core/index.js.map +0 -1
  206. package/dist/core/local-packages.d.ts +0 -19
  207. package/dist/core/local-packages.d.ts.map +0 -1
  208. package/dist/core/local-packages.js +0 -60
  209. package/dist/core/local-packages.js.map +0 -1
  210. package/dist/core/logger.d.ts +0 -28
  211. package/dist/core/logger.d.ts.map +0 -1
  212. package/dist/core/logger.js +0 -88
  213. package/dist/core/logger.js.map +0 -1
  214. package/dist/core/output.d.ts +0 -30
  215. package/dist/core/output.d.ts.map +0 -1
  216. package/dist/core/output.js +0 -46
  217. package/dist/core/output.js.map +0 -1
  218. package/dist/core/temp-manager.d.ts +0 -51
  219. package/dist/core/temp-manager.d.ts.map +0 -1
  220. package/dist/core/temp-manager.js +0 -73
  221. package/dist/core/temp-manager.js.map +0 -1
  222. package/dist/core/timer.d.ts +0 -14
  223. package/dist/core/timer.d.ts.map +0 -1
  224. package/dist/core/timer.js +0 -29
  225. package/dist/core/timer.js.map +0 -1
  226. package/dist/core/utils.d.ts +0 -10
  227. package/dist/core/utils.d.ts.map +0 -1
  228. package/dist/core/utils.js +0 -12
  229. package/dist/core/utils.js.map +0 -1
  230. package/dist/index.d.ts.map +0 -1
  231. package/dist/schemas/index.d.ts +0 -9
  232. package/dist/schemas/index.d.ts.map +0 -1
  233. package/dist/schemas/index.js +0 -9
  234. package/dist/schemas/index.js.map +0 -1
  235. package/dist/schemas/primitives.d.ts +0 -37
  236. package/dist/schemas/primitives.d.ts.map +0 -1
  237. package/dist/schemas/primitives.js +0 -43
  238. package/dist/schemas/primitives.js.map +0 -1
  239. package/dist/schemas/run.d.ts +0 -23
  240. package/dist/schemas/run.d.ts.map +0 -1
  241. package/dist/schemas/run.js +0 -20
  242. package/dist/schemas/run.js.map +0 -1
  243. package/dist/types/bundle.d.ts +0 -141
  244. package/dist/types/bundle.d.ts.map +0 -1
  245. package/dist/types/bundle.js +0 -10
  246. package/dist/types/bundle.js.map +0 -1
  247. package/dist/types/global.d.ts +0 -51
  248. package/dist/types/global.d.ts.map +0 -1
  249. package/dist/types/global.js +0 -30
  250. package/dist/types/global.js.map +0 -1
  251. package/dist/types/index.d.ts +0 -8
  252. package/dist/types/index.d.ts.map +0 -1
  253. package/dist/types/index.js +0 -8
  254. package/dist/types/index.js.map +0 -1
  255. package/dist/walker.js +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
  };
@@ -89,6 +108,23 @@ function createCommandLogger(options) {
89
108
  });
90
109
  }
91
110
 
111
+ // src/core/collector-logger.ts
112
+ function createCollectorLoggerConfig(cliLogger, verbose) {
113
+ return {
114
+ level: verbose ? "DEBUG" : "ERROR",
115
+ handler: (level, message, context, scope) => {
116
+ const scopePath = scope.length > 0 ? `[${scope.join(":")}] ` : "";
117
+ const hasContext = Object.keys(context).length > 0;
118
+ const contextStr = hasContext ? ` ${JSON.stringify(context)}` : "";
119
+ if (level === 0) {
120
+ cliLogger.error(`${scopePath}${message}${contextStr}`);
121
+ } else if (verbose) {
122
+ cliLogger.debug(`${scopePath}${message}${contextStr}`);
123
+ }
124
+ }
125
+ };
126
+ }
127
+
92
128
  // src/core/timer.ts
93
129
  function createTimer() {
94
130
  let startTime = 0;
@@ -132,15 +168,26 @@ function formatBytes(bytes) {
132
168
  return (bytes / 1024).toFixed(2);
133
169
  }
134
170
 
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";
171
+ // src/core/tmp.ts
172
+ import path from "path";
173
+ var DEFAULT_TMP_ROOT = ".tmp";
174
+ function getTmpPath(tmpDir, ...segments) {
175
+ const root = tmpDir || DEFAULT_TMP_ROOT;
176
+ const absoluteRoot = path.isAbsolute(root) ? root : path.resolve(root);
177
+ return path.join(absoluteRoot, ...segments);
178
+ }
179
+ function getDefaultTmpRoot() {
180
+ return DEFAULT_TMP_ROOT;
181
+ }
182
+
183
+ // src/core/asset-resolver.ts
184
+ import { fileURLToPath as fileURLToPath2 } from "url";
185
+ import { existsSync } from "fs";
186
+ import path3 from "path";
139
187
 
140
188
  // src/config/utils.ts
141
189
  import fs from "fs-extra";
142
- import path from "path";
143
- import os from "os";
190
+ import path2 from "path";
144
191
  function isUrl(str) {
145
192
  try {
146
193
  const url = new URL(str);
@@ -161,12 +208,9 @@ async function downloadFromUrl(url) {
161
208
  );
162
209
  }
163
210
  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);
211
+ const downloadsDir = getTmpPath(void 0, "downloads");
212
+ await fs.ensureDir(downloadsDir);
213
+ const tempPath = path2.join(downloadsDir, "flow.json");
170
214
  await fs.writeFile(tempPath, content, "utf-8");
171
215
  return tempPath;
172
216
  } catch (error) {
@@ -183,7 +227,7 @@ async function loadJsonConfig(configPath) {
183
227
  absolutePath = await downloadFromUrl(configPath);
184
228
  isTemporary = true;
185
229
  } else {
186
- absolutePath = path.resolve(configPath);
230
+ absolutePath = path2.resolve(configPath);
187
231
  if (!await fs.pathExists(absolutePath)) {
188
232
  throw new Error(`Configuration file not found: ${absolutePath}`);
189
233
  }
@@ -204,11 +248,6 @@ async function loadJsonConfig(configPath) {
204
248
  }
205
249
  }
206
250
  }
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
251
  async function loadJsonFromSource(source, options) {
213
252
  const paramName = options?.name || "input";
214
253
  if (!source || source.trim() === "") {
@@ -239,7 +278,7 @@ async function loadJsonFromSource(source, options) {
239
278
  );
240
279
  }
241
280
  }
242
- const resolvedPath = path.resolve(trimmedSource);
281
+ const resolvedPath = path2.resolve(trimmedSource);
243
282
  if (await fs.pathExists(resolvedPath)) {
244
283
  try {
245
284
  const data = await fs.readJson(resolvedPath);
@@ -263,193 +302,11 @@ async function loadJsonFromSource(source, options) {
263
302
  }
264
303
  }
265
304
 
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
305
  // src/core/asset-resolver.ts
446
- import { fileURLToPath } from "url";
447
- import { existsSync } from "fs";
448
- import path3 from "path";
449
306
  var cachedAssetDir;
450
307
  function getAssetDir() {
451
308
  if (cachedAssetDir) return cachedAssetDir;
452
- const currentFile = fileURLToPath(import.meta.url);
309
+ const currentFile = fileURLToPath2(import.meta.url);
453
310
  let dir = path3.dirname(currentFile);
454
311
  while (dir !== path3.dirname(dir)) {
455
312
  if (existsSync(path3.join(dir, "examples"))) {
@@ -482,22 +339,22 @@ function getErrorMessage(error) {
482
339
 
483
340
  // src/core/local-packages.ts
484
341
  import path4 from "path";
485
- import fs3 from "fs-extra";
342
+ import fs2 from "fs-extra";
486
343
  async function resolveLocalPackage(packageName, localPath, configDir, logger2) {
487
344
  const absolutePath = path4.isAbsolute(localPath) ? localPath : path4.resolve(configDir, localPath);
488
- if (!await fs3.pathExists(absolutePath)) {
345
+ if (!await fs2.pathExists(absolutePath)) {
489
346
  throw new Error(
490
347
  `Local package path not found: ${localPath} (resolved to ${absolutePath})`
491
348
  );
492
349
  }
493
350
  const pkgJsonPath = path4.join(absolutePath, "package.json");
494
- if (!await fs3.pathExists(pkgJsonPath)) {
351
+ if (!await fs2.pathExists(pkgJsonPath)) {
495
352
  throw new Error(
496
353
  `No package.json found at ${absolutePath}. Is this a valid package directory?`
497
354
  );
498
355
  }
499
356
  const distPath = path4.join(absolutePath, "dist");
500
- const hasDistFolder = await fs3.pathExists(distPath);
357
+ const hasDistFolder = await fs2.pathExists(distPath);
501
358
  if (!hasDistFolder) {
502
359
  logger2.warn(
503
360
  `\u26A0\uFE0F ${packageName}: No dist/ folder found. Using package root.`
@@ -512,18 +369,18 @@ async function resolveLocalPackage(packageName, localPath, configDir, logger2) {
512
369
  }
513
370
  async function copyLocalPackage(localPkg, targetDir, logger2) {
514
371
  const packageDir = path4.join(targetDir, "node_modules", localPkg.name);
515
- await fs3.ensureDir(path4.dirname(packageDir));
516
- await fs3.copy(
372
+ await fs2.ensureDir(path4.dirname(packageDir));
373
+ await fs2.copy(
517
374
  path4.join(localPkg.absolutePath, "package.json"),
518
375
  path4.join(packageDir, "package.json")
519
376
  );
520
377
  if (localPkg.hasDistFolder) {
521
- await fs3.copy(localPkg.distPath, path4.join(packageDir, "dist"));
378
+ await fs2.copy(localPkg.distPath, path4.join(packageDir, "dist"));
522
379
  } else {
523
- const entries = await fs3.readdir(localPkg.absolutePath);
380
+ const entries = await fs2.readdir(localPkg.absolutePath);
524
381
  for (const entry of entries) {
525
382
  if (!["node_modules", ".turbo", ".git"].includes(entry)) {
526
- await fs3.copy(
383
+ await fs2.copy(
527
384
  path4.join(localPkg.absolutePath, entry),
528
385
  path4.join(packageDir, entry)
529
386
  );
@@ -534,6 +391,33 @@ async function copyLocalPackage(localPkg, targetDir, logger2) {
534
391
  return packageDir;
535
392
  }
536
393
 
394
+ // src/core/input-detector.ts
395
+ import fs3 from "fs-extra";
396
+ async function detectInput(inputPath, platformOverride) {
397
+ const content = await loadContent(inputPath);
398
+ try {
399
+ JSON.parse(content);
400
+ return { type: "config", content };
401
+ } catch {
402
+ const platform = platformOverride ?? detectPlatformFromPath(inputPath);
403
+ return { type: "bundle", content, platform };
404
+ }
405
+ }
406
+ function detectPlatformFromPath(inputPath) {
407
+ const cleanPath = inputPath.split("?")[0];
408
+ return cleanPath.endsWith(".mjs") ? "server" : "web";
409
+ }
410
+ async function loadContent(inputPath) {
411
+ if (isUrl(inputPath)) {
412
+ const response = await fetch(inputPath);
413
+ if (!response.ok) {
414
+ throw new Error(`Failed to fetch ${inputPath}: ${response.status}`);
415
+ }
416
+ return response.text();
417
+ }
418
+ return fs3.readFile(inputPath, "utf8");
419
+ }
420
+
537
421
  // src/config/validators.ts
538
422
  import { schemas } from "@walkeros/core/dev";
539
423
  var { safeParseSetup } = schemas;
@@ -544,8 +428,8 @@ function validateFlowSetup(data) {
544
428
  const result = safeParseSetup(data);
545
429
  if (!result.success) {
546
430
  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}`;
431
+ const path14 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
432
+ return ` - ${path14}: ${issue.message}`;
549
433
  }).join("\n");
550
434
  throw new Error(`Invalid configuration:
551
435
  ${errors}`);
@@ -564,7 +448,6 @@ var WEB_BUILD_DEFAULTS = {
564
448
  minify: true,
565
449
  sourcemap: false,
566
450
  cache: true,
567
- tempDir: ".tmp",
568
451
  windowCollector: "collector",
569
452
  windowElb: "elb"
570
453
  };
@@ -574,8 +457,7 @@ var SERVER_BUILD_DEFAULTS = {
574
457
  target: "node20",
575
458
  minify: true,
576
459
  sourcemap: false,
577
- cache: true,
578
- tempDir: ".tmp"
460
+ cache: true
579
461
  };
580
462
  var DEFAULT_OUTPUT_PATHS = {
581
463
  web: "./dist/walker.js",
@@ -606,14 +488,8 @@ function loadBundleConfig(rawConfig, options) {
606
488
  }
607
489
  const buildDefaults = getBuildDefaults(platform);
608
490
  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
- }
491
+ const output = options.buildOverrides?.output || getDefaultOutput(platform);
492
+ const configDir = isUrl(options.configPath) ? process.cwd() : path5.dirname(options.configPath);
617
493
  let includes = setup.include;
618
494
  if (!includes) {
619
495
  const defaultIncludePath = path5.resolve(configDir, DEFAULT_INCLUDE_FOLDER);
@@ -676,6 +552,10 @@ function loadAllFlows(rawConfig, options) {
676
552
  })
677
553
  );
678
554
  }
555
+ async function loadFlowConfig(configPath, options) {
556
+ const rawConfig = await loadJsonConfig(configPath);
557
+ return loadBundleConfig(rawConfig, { configPath, ...options });
558
+ }
679
559
 
680
560
  // src/commands/bundle/bundler.ts
681
561
  import esbuild from "esbuild";
@@ -689,7 +569,7 @@ import path6 from "path";
689
569
  import fs5 from "fs-extra";
690
570
 
691
571
  // src/core/cache-utils.ts
692
- import { getHashServer as getHashServer2 } from "@walkeros/server-core";
572
+ import { getHashServer } from "@walkeros/server-core";
693
573
  var HASH_LENGTH = 12;
694
574
  function isMutableVersion(version) {
695
575
  return version === "latest" || version.includes("^") || version.includes("~") || version.includes("*") || version.includes("x");
@@ -702,10 +582,10 @@ async function getPackageCacheKey(packageName, version, date) {
702
582
  if (isMutableVersion(version)) {
703
583
  const dateStr = date ?? getTodayDate();
704
584
  const input2 = `${safeName}@${version}:${dateStr}`;
705
- return getHashServer2(input2, HASH_LENGTH);
585
+ return getHashServer(input2, HASH_LENGTH);
706
586
  }
707
587
  const input = `${safeName}@${version}`;
708
- return getHashServer2(input, HASH_LENGTH);
588
+ return getHashServer(input, HASH_LENGTH);
709
589
  }
710
590
  function normalizeJson(content) {
711
591
  const parsed = JSON.parse(content);
@@ -715,20 +595,27 @@ async function getFlowConfigCacheKey(content, date) {
715
595
  const dateStr = date ?? getTodayDate();
716
596
  const normalized = normalizeJson(content);
717
597
  const input = `${normalized}:${dateStr}`;
718
- return getHashServer2(input, HASH_LENGTH);
598
+ return getHashServer(input, HASH_LENGTH);
719
599
  }
720
600
 
721
601
  // src/commands/bundle/package-manager.ts
602
+ var PACKAGE_DOWNLOAD_TIMEOUT_MS = 6e4;
603
+ async function withTimeout(promise, ms, errorMessage) {
604
+ const timeout = new Promise(
605
+ (_, reject) => setTimeout(() => reject(new Error(errorMessage)), ms)
606
+ );
607
+ return Promise.race([promise, timeout]);
608
+ }
722
609
  function getPackageDirectory(baseDir, packageName, version) {
723
610
  return path6.join(baseDir, "node_modules", packageName);
724
611
  }
725
- async function getCachedPackagePath(pkg, tempDir) {
726
- const cacheDir = path6.join(".tmp", "cache", "packages");
612
+ async function getCachedPackagePath(pkg, tmpDir) {
613
+ const cacheDir = getTmpPath(tmpDir, "cache", "packages");
727
614
  const cacheKey = await getPackageCacheKey(pkg.name, pkg.version);
728
615
  return path6.join(cacheDir, cacheKey);
729
616
  }
730
- async function isPackageCached(pkg, tempDir) {
731
- const cachedPath = await getCachedPackagePath(pkg, tempDir);
617
+ async function isPackageCached(pkg, tmpDir) {
618
+ const cachedPath = await getCachedPackagePath(pkg, tmpDir);
732
619
  return fs5.pathExists(cachedPath);
733
620
  }
734
621
  function validateNoDuplicatePackages(packages) {
@@ -765,10 +652,10 @@ async function resolveDependencies(pkg, packageDir, logger2, visited = /* @__PUR
765
652
  try {
766
653
  const packageJsonPath = path6.join(packageDir, "package.json");
767
654
  if (await fs5.pathExists(packageJsonPath)) {
768
- const packageJson2 = await fs5.readJson(packageJsonPath);
655
+ const packageJson = await fs5.readJson(packageJsonPath);
769
656
  const deps = {
770
- ...packageJson2.dependencies,
771
- ...packageJson2.peerDependencies
657
+ ...packageJson.dependencies,
658
+ ...packageJson.peerDependencies
772
659
  };
773
660
  for (const [name, versionSpec] of Object.entries(deps)) {
774
661
  if (typeof versionSpec === "string") {
@@ -785,6 +672,7 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
785
672
  const packagePaths = /* @__PURE__ */ new Map();
786
673
  const downloadQueue = [...packages];
787
674
  const processed = /* @__PURE__ */ new Set();
675
+ const userSpecifiedPackages = new Set(packages.map((p) => p.name));
788
676
  const localPackageMap = /* @__PURE__ */ new Map();
789
677
  for (const pkg of packages) {
790
678
  if (pkg.path) {
@@ -823,9 +711,11 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
823
711
  }
824
712
  const packageSpec = `${pkg.name}@${pkg.version}`;
825
713
  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}...`);
714
+ const cachedPath = await getCachedPackagePath(pkg);
715
+ if (useCache && await isPackageCached(pkg)) {
716
+ if (userSpecifiedPackages.has(pkg.name)) {
717
+ logger2.debug(`Downloading ${packageSpec} (cached)`);
718
+ }
829
719
  try {
830
720
  await fs5.ensureDir(path6.dirname(packageDir));
831
721
  await fs5.copy(cachedPath, packageDir);
@@ -844,27 +734,34 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
844
734
  );
845
735
  }
846
736
  }
847
- logger2.debug(`Downloading ${packageSpec}...`);
848
737
  try {
849
738
  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
- });
739
+ const cacheDir = process.env.NPM_CACHE_DIR || getTmpPath(void 0, "cache", "npm");
740
+ await withTimeout(
741
+ pacote.extract(packageSpec, packageDir, {
742
+ // Force npm registry download, prevent workspace resolution
743
+ registry: "https://registry.npmjs.org",
744
+ // Force online fetching from registry (don't use cached workspace packages)
745
+ preferOnline: true,
746
+ // Cache for performance
747
+ cache: cacheDir,
748
+ // Don't resolve relative to workspace context
749
+ where: void 0
750
+ }),
751
+ PACKAGE_DOWNLOAD_TIMEOUT_MS,
752
+ `Package download timed out after ${PACKAGE_DOWNLOAD_TIMEOUT_MS / 1e3}s: ${packageSpec}`
753
+ );
754
+ if (userSpecifiedPackages.has(pkg.name)) {
755
+ const pkgStats = await fs5.stat(path6.join(packageDir, "package.json"));
756
+ const pkgJsonSize = pkgStats.size;
757
+ const sizeKB = (pkgJsonSize / 1024).toFixed(1);
758
+ logger2.debug(`Downloading ${packageSpec} (${sizeKB} KB)`);
759
+ }
861
760
  if (useCache) {
862
761
  try {
863
762
  await fs5.ensureDir(path6.dirname(cachedPath));
864
763
  await fs5.copy(packageDir, cachedPath);
865
- logger2.debug(`Cached ${packageSpec} for future use`);
866
764
  } catch (cacheError) {
867
- logger2.debug(`Failed to cache ${packageSpec}: ${cacheError}`);
868
765
  }
869
766
  }
870
767
  packagePaths.set(pkg.name, packageDir);
@@ -885,22 +782,22 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
885
782
  // src/core/build-cache.ts
886
783
  import fs6 from "fs-extra";
887
784
  import path7 from "path";
888
- var BUILD_CACHE_DIR = path7.join(".tmp", "cache", "builds");
889
- async function getBuildCachePath(configContent, cacheDir = BUILD_CACHE_DIR) {
785
+ async function getBuildCachePath(configContent, tmpDir) {
786
+ const cacheDir = getTmpPath(tmpDir, "cache", "builds");
890
787
  const cacheKey = await getFlowConfigCacheKey(configContent);
891
788
  return path7.join(cacheDir, `${cacheKey}.js`);
892
789
  }
893
- async function isBuildCached(configContent, cacheDir = BUILD_CACHE_DIR) {
894
- const cachePath = await getBuildCachePath(configContent, cacheDir);
790
+ async function isBuildCached(configContent, tmpDir) {
791
+ const cachePath = await getBuildCachePath(configContent, tmpDir);
895
792
  return fs6.pathExists(cachePath);
896
793
  }
897
- async function cacheBuild(configContent, buildOutput, cacheDir = BUILD_CACHE_DIR) {
898
- const cachePath = await getBuildCachePath(configContent, cacheDir);
794
+ async function cacheBuild(configContent, buildOutput, tmpDir) {
795
+ const cachePath = await getBuildCachePath(configContent, tmpDir);
899
796
  await fs6.ensureDir(path7.dirname(cachePath));
900
797
  await fs6.writeFile(cachePath, buildOutput, "utf-8");
901
798
  }
902
- async function getCachedBuild(configContent, cacheDir = BUILD_CACHE_DIR) {
903
- const cachePath = await getBuildCachePath(configContent, cacheDir);
799
+ async function getCachedBuild(configContent, tmpDir) {
800
+ const cachePath = await getBuildCachePath(configContent, tmpDir);
904
801
  if (await fs6.pathExists(cachePath)) {
905
802
  return await fs6.readFile(cachePath, "utf-8");
906
803
  }
@@ -935,21 +832,22 @@ function generateCacheKeyContent(flowConfig, buildOptions) {
935
832
  }
936
833
  async function bundleCore(flowConfig, buildOptions, logger2, showStats = false) {
937
834
  const bundleStartTime = Date.now();
938
- const TEMP_DIR = buildOptions.tempDir ? path8.isAbsolute(buildOptions.tempDir) ? buildOptions.tempDir : path8.resolve(buildOptions.tempDir) : getTempDir();
835
+ const TEMP_DIR = buildOptions.tempDir || getTmpPath();
939
836
  if (buildOptions.cache !== false) {
940
837
  const configContent = generateCacheKeyContent(flowConfig, buildOptions);
941
838
  const cached = await isBuildCached(configContent);
942
839
  if (cached) {
943
840
  const cachedBuild = await getCachedBuild(configContent);
944
841
  if (cachedBuild) {
945
- logger2.info("\u2728 Using cached build");
842
+ logger2.debug("Using cached build");
946
843
  const outputPath = path8.resolve(buildOptions.output);
947
844
  await fs7.ensureDir(path8.dirname(outputPath));
948
845
  await fs7.writeFile(outputPath, cachedBuild);
949
- logger2.gray(`Output: ${outputPath}`);
950
- logger2.success("\u2705 Build completed (from cache)");
846
+ const stats = await fs7.stat(outputPath);
847
+ const sizeKB = (stats.size / 1024).toFixed(1);
848
+ logger2.log(`Output: ${outputPath} (${sizeKB} KB, cached)`);
951
849
  if (showStats) {
952
- const stats = await fs7.stat(outputPath);
850
+ const stats2 = await fs7.stat(outputPath);
953
851
  const packageStats = Object.entries(buildOptions.packages).map(
954
852
  ([name, pkg]) => ({
955
853
  name: `${name}@${pkg.version || "latest"}`,
@@ -958,7 +856,7 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
958
856
  })
959
857
  );
960
858
  return {
961
- totalSize: stats.size,
859
+ totalSize: stats2.size,
962
860
  packages: packageStats,
963
861
  buildTime: Date.now() - bundleStartTime,
964
862
  treeshakingEffective: true
@@ -969,11 +867,8 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
969
867
  }
970
868
  }
971
869
  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...");
870
+ await fs7.ensureDir(TEMP_DIR);
871
+ logger2.debug("Downloading packages");
977
872
  const packagesArray = Object.entries(buildOptions.packages).map(
978
873
  ([name, packageConfig]) => ({
979
874
  name,
@@ -1010,7 +905,7 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
1010
905
  packageJsonPath,
1011
906
  JSON.stringify({ type: "module" }, null, 2)
1012
907
  );
1013
- logger2.info("\u{1F4DD} Creating entry point...");
908
+ logger2.debug("Creating entry point");
1014
909
  const entryContent = await createEntryPoint(
1015
910
  flowConfig,
1016
911
  buildOptions,
@@ -1018,7 +913,9 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
1018
913
  );
1019
914
  const entryPath = path8.join(TEMP_DIR, "entry.js");
1020
915
  await fs7.writeFile(entryPath, entryContent);
1021
- logger2.info("\u26A1 Bundling with esbuild...");
916
+ logger2.debug(
917
+ `Running esbuild (target: ${buildOptions.target || "es2018"}, format: ${buildOptions.format})`
918
+ );
1022
919
  const outputPath = path8.resolve(buildOptions.output);
1023
920
  await fs7.ensureDir(path8.dirname(outputPath));
1024
921
  const esbuildOptions = createEsbuildOptions(
@@ -1037,7 +934,10 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
1037
934
  buildOptions.code || ""
1038
935
  );
1039
936
  }
1040
- logger2.gray(`Output: ${outputPath}`);
937
+ const outputStats = await fs7.stat(outputPath);
938
+ const sizeKB = (outputStats.size / 1024).toFixed(1);
939
+ const buildTime = ((Date.now() - bundleStartTime) / 1e3).toFixed(1);
940
+ logger2.log(`Output: ${outputPath} (${sizeKB} KB, ${buildTime}s)`);
1041
941
  if (buildOptions.cache !== false) {
1042
942
  const configContent = generateCacheKeyContent(flowConfig, buildOptions);
1043
943
  const buildOutput = await fs7.readFile(outputPath, "utf-8");
@@ -1062,16 +962,8 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
1062
962
  logger2
1063
963
  );
1064
964
  }
1065
- if (!buildOptions.tempDir) {
1066
- await fs7.remove(TEMP_DIR);
1067
- logger2.debug("Cleaned up temporary files");
1068
- }
1069
965
  return stats;
1070
966
  } catch (error) {
1071
- if (!buildOptions.tempDir) {
1072
- await fs7.remove(TEMP_DIR).catch(() => {
1073
- });
1074
- }
1075
967
  throw error;
1076
968
  }
1077
969
  }
@@ -1404,6 +1296,11 @@ function generatePlatformWrapper(configObject, userCode, buildOptions) {
1404
1296
  ` : "";
1405
1297
  return `export default async function(context = {}) {
1406
1298
  const config = ${configObject};${codeSection}
1299
+ // Apply context overrides (e.g., logger config from CLI)
1300
+ if (context.logger) {
1301
+ config.logger = { ...config.logger, ...context.logger };
1302
+ }
1303
+
1407
1304
  return await startFlow(config);
1408
1305
  }`;
1409
1306
  }
@@ -1437,130 +1334,111 @@ async function bundleCommand(options) {
1437
1334
  const timer = createTimer();
1438
1335
  timer.start();
1439
1336
  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 () => {
1337
+ if (options.dryRun) {
1338
+ logger2.log(`[DRY-RUN] Would execute bundle with config: ${options.config}`);
1339
+ return;
1340
+ }
1341
+ try {
1342
+ if (options.flow && options.all) {
1343
+ throw new Error("Cannot use both --flow and --all flags together");
1344
+ }
1345
+ const configPath = resolveAsset(options.config, "config");
1346
+ const rawConfig = await loadJsonConfig(configPath);
1347
+ const configsToBundle = options.all ? loadAllFlows(rawConfig, { configPath, logger: logger2 }) : [
1348
+ loadBundleConfig(rawConfig, {
1349
+ configPath,
1350
+ flowName: options.flow,
1351
+ logger: logger2
1352
+ })
1353
+ ];
1354
+ const results = [];
1355
+ for (const {
1356
+ flowConfig,
1357
+ buildOptions,
1358
+ flowName,
1359
+ isMultiFlow
1360
+ } of configsToBundle) {
1447
1361
  try {
1448
- if (options.flow && options.all) {
1449
- throw new Error("Cannot use both --flow and --all flags together");
1362
+ if (options.cache !== void 0) {
1363
+ buildOptions.cache = options.cache;
1450
1364
  }
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 {
1365
+ const configBasename = path9.basename(configPath);
1366
+ if (isMultiFlow || options.all) {
1367
+ logger2.log(`Bundling ${configBasename} (flow: ${flowName})...`);
1368
+ } else {
1369
+ logger2.log(`Bundling ${configBasename}...`);
1370
+ }
1371
+ const shouldCollectStats = options.stats || options.json;
1372
+ const stats = await bundleCore(
1463
1373
  flowConfig,
1464
1374
  buildOptions,
1375
+ logger2,
1376
+ shouldCollectStats
1377
+ );
1378
+ results.push({
1465
1379
  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
- }
1380
+ success: true,
1381
+ stats
1382
+ });
1383
+ if (!options.json && !options.all && options.stats && stats) {
1384
+ displayStats(stats, logger2);
1543
1385
  }
1544
1386
  } catch (error) {
1545
- const duration = timer.getElapsed() / 1e3;
1546
1387
  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);
1388
+ results.push({
1389
+ flowName,
1390
+ success: false,
1391
+ error: errorMessage
1392
+ });
1393
+ if (!options.all) {
1394
+ throw error;
1554
1395
  }
1555
- process.exit(1);
1556
1396
  }
1557
- },
1558
- "bundle",
1559
- dockerArgs,
1560
- options,
1561
- logger2,
1562
- options.config
1563
- );
1397
+ }
1398
+ const duration = timer.end() / 1e3;
1399
+ const successCount = results.filter((r) => r.success).length;
1400
+ const failureCount = results.filter((r) => !r.success).length;
1401
+ if (options.json) {
1402
+ const output = failureCount === 0 ? createSuccessOutput(
1403
+ {
1404
+ flows: results,
1405
+ summary: {
1406
+ total: results.length,
1407
+ success: successCount,
1408
+ failed: failureCount
1409
+ }
1410
+ },
1411
+ duration
1412
+ ) : createErrorOutput(
1413
+ `${failureCount} flow(s) failed to build`,
1414
+ duration
1415
+ );
1416
+ logger2.json(output);
1417
+ } else {
1418
+ if (options.all) {
1419
+ logger2.log(
1420
+ `
1421
+ Build Summary: ${successCount}/${results.length} succeeded`
1422
+ );
1423
+ if (failureCount > 0) {
1424
+ logger2.error(`Failed: ${failureCount}`);
1425
+ }
1426
+ }
1427
+ if (failureCount > 0) {
1428
+ throw new Error(`${failureCount} flow(s) failed to build`);
1429
+ }
1430
+ }
1431
+ } catch (error) {
1432
+ const duration = timer.getElapsed() / 1e3;
1433
+ const errorMessage = getErrorMessage(error);
1434
+ if (options.json) {
1435
+ const output = createErrorOutput(errorMessage, duration);
1436
+ logger2.json(output);
1437
+ } else {
1438
+ logger2.error(`Error: ${errorMessage}`);
1439
+ }
1440
+ process.exit(1);
1441
+ }
1564
1442
  }
1565
1443
  async function bundle(configOrPath, options = {}) {
1566
1444
  let rawConfig;
@@ -1627,9 +1505,9 @@ var CallTracker = class {
1627
1505
  }
1628
1506
  for (const fullPath of paths) {
1629
1507
  const [destKey, ...pathParts] = fullPath.split(":");
1630
- const path15 = pathParts.join(":");
1631
- if (!path15) continue;
1632
- const cleanPath = path15.replace(/^call:/, "");
1508
+ const path14 = pathParts.join(":");
1509
+ if (!path14) continue;
1510
+ const cleanPath = path14.replace(/^call:/, "");
1633
1511
  const parts = cleanPath.split(".");
1634
1512
  let current = wrapped;
1635
1513
  let source = env;
@@ -1710,11 +1588,11 @@ function buildSandboxFromEnvs(envs, destinations, tracker) {
1710
1588
  return sandbox;
1711
1589
  }
1712
1590
  function waitForWindowProperty(window, prop, timeout = 5e3) {
1713
- return new Promise((resolve, reject) => {
1591
+ return new Promise((resolve3, reject) => {
1714
1592
  const start = Date.now();
1715
1593
  const check = () => {
1716
1594
  if (window[prop] !== void 0) {
1717
- resolve();
1595
+ resolve3();
1718
1596
  } else if (Date.now() - start > timeout) {
1719
1597
  reject(
1720
1598
  new Error(
@@ -1813,7 +1691,7 @@ function injectGlobalMocks(mocks) {
1813
1691
  }
1814
1692
  };
1815
1693
  }
1816
- async function executeInNode(bundlePath, destinations, event, tracker, envs, timeout = 3e4) {
1694
+ async function executeInNode(bundlePath, destinations, event, tracker, envs, timeout = 3e4, context = {}) {
1817
1695
  const start = Date.now();
1818
1696
  const globalMocks = buildGlobalMocksFromEnvs(envs, destinations, tracker);
1819
1697
  const cleanupMocks = injectGlobalMocks(globalMocks);
@@ -1824,16 +1702,19 @@ async function executeInNode(bundlePath, destinations, event, tracker, envs, tim
1824
1702
  if (!module.default || typeof module.default !== "function") {
1825
1703
  throw new Error("Bundle does not export default factory function");
1826
1704
  }
1827
- const result = await module.default();
1828
- if (!result || !result.elb || typeof result.elb !== "function") {
1705
+ const result = await module.default(context);
1706
+ if (!result || !result.collector || typeof result.collector.push !== "function") {
1829
1707
  throw new Error(
1830
- "Factory function did not return valid result with elb"
1708
+ "Factory function did not return valid result with collector"
1831
1709
  );
1832
1710
  }
1833
1711
  const { collector, elb } = result;
1834
1712
  let elbResult;
1835
1713
  try {
1836
- elbResult = await elb(event.name, event.data);
1714
+ elbResult = await collector.push({
1715
+ name: event.name,
1716
+ data: event.data
1717
+ });
1837
1718
  } catch (error) {
1838
1719
  throw new Error(`Event execution failed: ${getErrorMessage(error)}`);
1839
1720
  }
@@ -1881,10 +1762,7 @@ async function loadDestinationEnvs(destinations) {
1881
1762
  simulation: envModule.simulation || []
1882
1763
  };
1883
1764
  }
1884
- } catch (error) {
1885
- console.warn(
1886
- `Warning: Could not load env for destination "${destKey}": ${error instanceof Error ? error.message : String(error)}`
1887
- );
1765
+ } catch {
1888
1766
  }
1889
1767
  }
1890
1768
  return envs;
@@ -1894,29 +1772,21 @@ async function loadDestinationEnvs(destinations) {
1894
1772
  function generateId() {
1895
1773
  return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
1896
1774
  }
1897
- async function simulateCore(configPath, event, options = {}) {
1775
+ async function simulateCore(inputPath, event, options = {}) {
1898
1776
  const logger2 = createLogger({
1899
1777
  verbose: options.verbose || false,
1900
1778
  silent: options.silent || false,
1901
1779
  json: options.json || false
1902
1780
  });
1903
1781
  try {
1904
- logger2.info("\u{1F3AF} Starting walkerOS simulation...");
1905
- logger2.info("\u{1F4E6} Loading bundle configuration...");
1906
- const fullConfigPath = path10.resolve(configPath);
1907
- const rawConfig = await loadJsonConfig(fullConfigPath);
1908
- loadBundleConfig(rawConfig, { configPath: fullConfigPath });
1909
- logger2.info(`\u{1F680} Executing simulation with event: ${JSON.stringify(event)}`);
1910
- const result = await executeSimulation(event, fullConfigPath);
1911
- if (result.success) {
1912
- logger2.info(`\u2705 Simulation completed successfully`);
1913
- } else {
1914
- logger2.error(`\u274C Simulation failed: ${result.error}`);
1915
- }
1782
+ logger2.debug(`Simulating event: ${JSON.stringify(event)}`);
1783
+ const result = await executeSimulation(event, inputPath, options.platform, {
1784
+ logger: logger2,
1785
+ verbose: options.verbose
1786
+ });
1916
1787
  return result;
1917
1788
  } catch (error) {
1918
1789
  const errorMessage = getErrorMessage(error);
1919
- logger2.error(`\u{1F4A5} Simulation error: ${errorMessage}`);
1920
1790
  return {
1921
1791
  success: false,
1922
1792
  error: errorMessage
@@ -1933,87 +1803,43 @@ function formatSimulationResult(result, options = {}) {
1933
1803
  return JSON.stringify(output, null, 2);
1934
1804
  }
1935
1805
  if (result.success) {
1936
- return "\u2705 Simulation completed successfully";
1806
+ return "Simulation completed";
1937
1807
  } else {
1938
- return `\u274C Simulation failed: ${result.error}`;
1808
+ return `Simulation failed: ${result.error}`;
1939
1809
  }
1940
1810
  }
1941
- async function executeSimulation(event, configPath) {
1811
+ async function executeSimulation(event, inputPath, platformOverride, options = {}) {
1942
1812
  const startTime = Date.now();
1943
- let bundlePath;
1944
- const tempDir = getTempDir();
1813
+ const tempDir = getTmpPath();
1814
+ const collectorLoggerConfig = options.logger ? createCollectorLoggerConfig(options.logger, options.verbose) : void 0;
1945
1815
  try {
1816
+ await fs9.ensureDir(tempDir);
1817
+ const detected = await detectInput(inputPath, platformOverride);
1946
1818
  if (!isObject(event) || !("name" in event) || typeof event.name !== "string") {
1947
1819
  throw new Error(
1948
1820
  'Event must be an object with a "name" property of type string'
1949
1821
  );
1950
1822
  }
1951
1823
  const typedEvent = event;
1952
- await fs9.ensureDir(tempDir);
1953
- const rawConfig = await loadJsonConfig(configPath);
1954
- const { flowConfig, buildOptions } = loadBundleConfig(rawConfig, {
1955
- configPath
1956
- });
1957
- const platform = getPlatform2(flowConfig);
1958
- const tracker = new CallTracker();
1959
- const tempOutput = path10.join(
1960
- tempDir,
1961
- `simulation-bundle-${generateId()}.${platform === "web" ? "js" : "mjs"}`
1962
- );
1963
- const destinations = flowConfig.destinations;
1964
- const simulationBuildOptions = {
1965
- ...buildOptions,
1966
- code: buildOptions.code || "",
1967
- output: tempOutput,
1968
- tempDir,
1969
- ...platform === "web" ? {
1970
- format: "iife",
1971
- platform: "browser",
1972
- windowCollector: "collector",
1973
- windowElb: "elb"
1974
- } : {
1975
- format: "esm",
1976
- platform: "node"
1977
- }
1978
- };
1979
- await bundleCore(
1980
- flowConfig,
1981
- simulationBuildOptions,
1982
- createLogger({ silent: true }),
1983
- false
1984
- );
1985
- bundlePath = tempOutput;
1986
- const envs = await loadDestinationEnvs(destinations || {});
1987
- let result;
1988
- if (platform === "web") {
1989
- result = await executeInJSDOM(
1990
- tempOutput,
1991
- destinations || {},
1824
+ if (detected.type === "config") {
1825
+ return await executeConfigSimulation(
1826
+ detected.content,
1827
+ inputPath,
1992
1828
  typedEvent,
1993
- tracker,
1994
- envs,
1995
- 1e4
1829
+ tempDir,
1830
+ startTime,
1831
+ collectorLoggerConfig
1996
1832
  );
1997
1833
  } else {
1998
- result = await executeInNode(
1999
- tempOutput,
2000
- destinations || {},
1834
+ return await executeBundleSimulation(
1835
+ detected.content,
1836
+ detected.platform,
2001
1837
  typedEvent,
2002
- tracker,
2003
- envs,
2004
- 3e4
1838
+ tempDir,
1839
+ startTime,
1840
+ collectorLoggerConfig
2005
1841
  );
2006
1842
  }
2007
- const elbResult = result.elbResult;
2008
- const usage = result.usage;
2009
- const duration = Date.now() - startTime;
2010
- return {
2011
- success: true,
2012
- elbResult,
2013
- usage,
2014
- duration,
2015
- logs: []
2016
- };
2017
1843
  } catch (error) {
2018
1844
  const duration = Date.now() - startTime;
2019
1845
  return {
@@ -2028,63 +1854,152 @@ async function executeSimulation(event, configPath) {
2028
1854
  }
2029
1855
  }
2030
1856
  }
1857
+ async function executeConfigSimulation(_content, configPath, typedEvent, tempDir, startTime, loggerConfig2) {
1858
+ const { flowConfig, buildOptions } = await loadFlowConfig(configPath);
1859
+ const platform = getPlatform2(flowConfig);
1860
+ const tracker = new CallTracker();
1861
+ const tempOutput = path10.join(
1862
+ tempDir,
1863
+ `simulation-bundle-${generateId()}.${platform === "web" ? "js" : "mjs"}`
1864
+ );
1865
+ const destinations = flowConfig.destinations;
1866
+ const simulationBuildOptions = {
1867
+ ...buildOptions,
1868
+ code: buildOptions.code || "",
1869
+ output: tempOutput,
1870
+ tempDir,
1871
+ ...platform === "web" ? {
1872
+ format: "iife",
1873
+ platform: "browser",
1874
+ windowCollector: "collector",
1875
+ windowElb: "elb"
1876
+ } : {
1877
+ format: "esm",
1878
+ platform: "node"
1879
+ }
1880
+ };
1881
+ await bundleCore(
1882
+ flowConfig,
1883
+ simulationBuildOptions,
1884
+ createLogger({ silent: true }),
1885
+ false
1886
+ );
1887
+ const envs = await loadDestinationEnvs(destinations || {});
1888
+ let result;
1889
+ if (platform === "web") {
1890
+ result = await executeInJSDOM(
1891
+ tempOutput,
1892
+ destinations || {},
1893
+ typedEvent,
1894
+ tracker,
1895
+ envs,
1896
+ 1e4
1897
+ );
1898
+ } else {
1899
+ result = await executeInNode(
1900
+ tempOutput,
1901
+ destinations || {},
1902
+ typedEvent,
1903
+ tracker,
1904
+ envs,
1905
+ 3e4,
1906
+ loggerConfig2 ? { logger: loggerConfig2 } : {}
1907
+ );
1908
+ }
1909
+ const duration = Date.now() - startTime;
1910
+ return {
1911
+ success: true,
1912
+ elbResult: result.elbResult,
1913
+ usage: result.usage,
1914
+ duration,
1915
+ logs: []
1916
+ };
1917
+ }
1918
+ async function executeBundleSimulation(bundleContent, platform, typedEvent, tempDir, startTime, loggerConfig2) {
1919
+ const tempOutput = path10.join(
1920
+ tempDir,
1921
+ `bundle-${generateId()}.${platform === "server" ? "mjs" : "js"}`
1922
+ );
1923
+ await fs9.writeFile(tempOutput, bundleContent, "utf8");
1924
+ const tracker = new CallTracker();
1925
+ let result;
1926
+ if (platform === "web") {
1927
+ result = await executeInJSDOM(
1928
+ tempOutput,
1929
+ {},
1930
+ typedEvent,
1931
+ tracker,
1932
+ {},
1933
+ 1e4
1934
+ );
1935
+ } else {
1936
+ result = await executeInNode(
1937
+ tempOutput,
1938
+ {},
1939
+ typedEvent,
1940
+ tracker,
1941
+ {},
1942
+ 3e4,
1943
+ loggerConfig2 ? { logger: loggerConfig2 } : {}
1944
+ );
1945
+ }
1946
+ const duration = Date.now() - startTime;
1947
+ return {
1948
+ success: true,
1949
+ elbResult: result.elbResult,
1950
+ usage: result.usage,
1951
+ duration,
1952
+ logs: []
1953
+ };
1954
+ }
2031
1955
 
2032
1956
  // src/commands/simulate/index.ts
2033
1957
  async function simulateCommand(options) {
2034
1958
  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
- );
1959
+ if (options.dryRun) {
1960
+ logger2.log(
1961
+ `[DRY-RUN] Would execute simulate with config: ${options.config}`
1962
+ );
1963
+ return;
1964
+ }
1965
+ const startTime = Date.now();
1966
+ try {
1967
+ const event = await loadJsonFromSource(options.event, {
1968
+ name: "event"
1969
+ });
1970
+ const result = await simulateCore(options.config, event, {
1971
+ json: options.json,
1972
+ verbose: options.verbose,
1973
+ silent: options.silent
1974
+ });
1975
+ const resultWithDuration = {
1976
+ ...result,
1977
+ duration: (Date.now() - startTime) / 1e3
1978
+ };
1979
+ if (options.json) {
1980
+ logger2.json(resultWithDuration);
1981
+ } else {
1982
+ const output = formatSimulationResult(resultWithDuration, {
1983
+ json: false
1984
+ });
1985
+ logger2.log(output);
1986
+ }
1987
+ if (!result.success) {
1988
+ process.exit(1);
1989
+ }
1990
+ } catch (error) {
1991
+ const errorMessage = getErrorMessage(error);
1992
+ if (options.json) {
1993
+ logger2.json({
1994
+ success: false,
1995
+ error: errorMessage,
1996
+ duration: (Date.now() - startTime) / 1e3
1997
+ });
1998
+ } else {
1999
+ logger2.error(`Error: ${errorMessage}`);
2000
+ }
2001
+ process.exit(1);
2002
+ }
2088
2003
  }
2089
2004
  async function simulate(configOrPath, event, options = {}) {
2090
2005
  if (typeof configOrPath !== "string") {
@@ -2102,152 +2017,182 @@ async function simulate(configOrPath, event, options = {}) {
2102
2017
  import path11 from "path";
2103
2018
  import { JSDOM as JSDOM2, VirtualConsole as VirtualConsole2 } from "jsdom";
2104
2019
  import fs10 from "fs-extra";
2105
- import { getPlatform as getPlatform3 } from "@walkeros/core";
2020
+ import {
2021
+ getPlatform as getPlatform3
2022
+ } from "@walkeros/core";
2106
2023
  import { schemas as schemas2 } from "@walkeros/core/dev";
2107
2024
  async function pushCommand(options) {
2108
2025
  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
- );
2026
+ const startTime = Date.now();
2027
+ let tempDir;
2028
+ try {
2029
+ logger2.debug("Loading event");
2030
+ const event = await loadJsonFromSource(options.event, {
2031
+ name: "event"
2032
+ });
2033
+ const eventResult = schemas2.PartialEventSchema.safeParse(event);
2034
+ if (!eventResult.success) {
2035
+ const errors = eventResult.error.issues.map((issue) => `${String(issue.path.join("."))}: ${issue.message}`).join(", ");
2036
+ throw new Error(`Invalid event: ${errors}`);
2037
+ }
2038
+ const parsedEvent = eventResult.data;
2039
+ if (!parsedEvent.name) {
2040
+ throw new Error('Invalid event: Missing required "name" property');
2041
+ }
2042
+ const validatedEvent = {
2043
+ name: parsedEvent.name,
2044
+ data: parsedEvent.data || {}
2045
+ };
2046
+ if (!validatedEvent.name.includes(" ")) {
2047
+ logger2.log(
2048
+ `Warning: Event name "${validatedEvent.name}" should follow "ENTITY ACTION" format (e.g., "page view")`
2049
+ );
2050
+ }
2051
+ logger2.debug("Detecting input type");
2052
+ const detected = await detectInput(options.config, options.platform);
2053
+ let result;
2054
+ if (detected.type === "config") {
2055
+ result = await executeConfigPush(
2056
+ options,
2057
+ validatedEvent,
2058
+ logger2,
2059
+ (dir) => {
2060
+ tempDir = dir;
2137
2061
  }
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"
2062
+ );
2063
+ } else {
2064
+ const collectorLoggerConfig = createCollectorLoggerConfig(
2065
+ logger2,
2066
+ options.verbose
2067
+ );
2068
+ result = await executeBundlePush(
2069
+ detected.content,
2070
+ detected.platform,
2071
+ validatedEvent,
2072
+ logger2,
2073
+ (dir) => {
2074
+ tempDir = dir;
2075
+ },
2076
+ { logger: collectorLoggerConfig }
2077
+ );
2078
+ }
2079
+ const duration = Date.now() - startTime;
2080
+ if (options.json) {
2081
+ logger2.json({
2082
+ success: result.success,
2083
+ event: result.elbResult,
2084
+ duration
2085
+ });
2086
+ } else {
2087
+ if (result.success) {
2088
+ logger2.log("Event pushed successfully");
2089
+ if (result.elbResult && typeof result.elbResult === "object") {
2090
+ const pushResult = result.elbResult;
2091
+ if ("id" in pushResult && pushResult.id) {
2092
+ logger2.log(` Event ID: ${pushResult.id}`);
2168
2093
  }
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);
2094
+ if ("entity" in pushResult && pushResult.entity) {
2095
+ logger2.log(` Entity: ${pushResult.entity}`);
2096
+ }
2097
+ if ("action" in pushResult && pushResult.action) {
2098
+ logger2.log(` Action: ${pushResult.action}`);
2216
2099
  }
2217
2100
  }
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
- }
2101
+ logger2.log(` Duration: ${duration}ms`);
2102
+ } else {
2103
+ logger2.error(`Error: ${result.error}`);
2242
2104
  process.exit(1);
2243
2105
  }
2244
- },
2245
- "push",
2246
- dockerArgs,
2247
- options,
2248
- logger2,
2249
- options.config
2106
+ }
2107
+ } catch (error) {
2108
+ const duration = Date.now() - startTime;
2109
+ const errorMessage = getErrorMessage(error);
2110
+ if (options.json) {
2111
+ logger2.json({
2112
+ success: false,
2113
+ error: errorMessage,
2114
+ duration
2115
+ });
2116
+ } else {
2117
+ logger2.error(`Error: ${errorMessage}`);
2118
+ }
2119
+ process.exit(1);
2120
+ } finally {
2121
+ if (tempDir) {
2122
+ await fs10.remove(tempDir).catch(() => {
2123
+ });
2124
+ }
2125
+ }
2126
+ }
2127
+ async function executeConfigPush(options, validatedEvent, logger2, setTempDir) {
2128
+ logger2.debug("Loading flow configuration");
2129
+ const { flowConfig, buildOptions } = await loadFlowConfig(options.config, {
2130
+ flowName: options.flow,
2131
+ logger: logger2
2132
+ });
2133
+ const platform = getPlatform3(flowConfig);
2134
+ logger2.debug("Bundling flow configuration");
2135
+ const configDir = buildOptions.configDir || process.cwd();
2136
+ const tempDir = path11.join(
2137
+ configDir,
2138
+ ".tmp",
2139
+ `push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
2140
+ );
2141
+ setTempDir(tempDir);
2142
+ await fs10.ensureDir(tempDir);
2143
+ const tempPath = path11.join(
2144
+ tempDir,
2145
+ `bundle.${platform === "web" ? "js" : "mjs"}`
2250
2146
  );
2147
+ const pushBuildOptions = {
2148
+ ...buildOptions,
2149
+ output: tempPath,
2150
+ format: platform === "web" ? "iife" : "esm",
2151
+ platform: platform === "web" ? "browser" : "node",
2152
+ ...platform === "web" && {
2153
+ windowCollector: "collector",
2154
+ windowElb: "elb"
2155
+ }
2156
+ };
2157
+ await bundleCore(flowConfig, pushBuildOptions, logger2, false);
2158
+ logger2.debug(`Bundle created: ${tempPath}`);
2159
+ if (platform === "web") {
2160
+ logger2.debug("Executing in web environment (JSDOM)");
2161
+ return executeWebPush(tempPath, validatedEvent, logger2);
2162
+ } else if (platform === "server") {
2163
+ logger2.debug("Executing in server environment (Node.js)");
2164
+ const collectorLoggerConfig = createCollectorLoggerConfig(
2165
+ logger2,
2166
+ options.verbose
2167
+ );
2168
+ return executeServerPush(tempPath, validatedEvent, logger2, 6e4, {
2169
+ logger: collectorLoggerConfig
2170
+ });
2171
+ } else {
2172
+ throw new Error(`Unsupported platform: ${platform}`);
2173
+ }
2174
+ }
2175
+ async function executeBundlePush(bundleContent, platform, validatedEvent, logger2, setTempDir, context = {}) {
2176
+ const tempDir = path11.join(
2177
+ process.cwd(),
2178
+ ".tmp",
2179
+ `push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
2180
+ );
2181
+ setTempDir(tempDir);
2182
+ await fs10.ensureDir(tempDir);
2183
+ const tempPath = path11.join(
2184
+ tempDir,
2185
+ `bundle.${platform === "server" ? "mjs" : "js"}`
2186
+ );
2187
+ await fs10.writeFile(tempPath, bundleContent, "utf8");
2188
+ logger2.debug(`Bundle written to: ${tempPath}`);
2189
+ if (platform === "web") {
2190
+ logger2.debug("Executing in web environment (JSDOM)");
2191
+ return executeWebPush(tempPath, validatedEvent, logger2);
2192
+ } else {
2193
+ logger2.debug("Executing in server environment (Node.js)");
2194
+ return executeServerPush(tempPath, validatedEvent, logger2, 6e4, context);
2195
+ }
2251
2196
  }
2252
2197
  async function executeWebPush(bundlePath, event, logger2) {
2253
2198
  const startTime = Date.now();
@@ -2263,16 +2208,19 @@ async function executeWebPush(bundlePath, event, logger2) {
2263
2208
  logger2.debug("Loading bundle...");
2264
2209
  const bundleCode = await fs10.readFile(bundlePath, "utf8");
2265
2210
  window.eval(bundleCode);
2266
- logger2.debug("Waiting for elb...");
2211
+ logger2.debug("Waiting for collector...");
2267
2212
  await waitForWindowProperty2(
2268
2213
  window,
2269
- "elb",
2214
+ "collector",
2270
2215
  5e3
2271
2216
  );
2272
2217
  const windowObj = window;
2273
- const elb = windowObj.elb;
2274
- logger2.info(`Pushing event: ${event.name}`);
2275
- const elbResult = await elb(event.name, event.data);
2218
+ const collector = windowObj.collector;
2219
+ logger2.log(`Pushing event: ${event.name}`);
2220
+ const elbResult = await collector.push({
2221
+ name: event.name,
2222
+ data: event.data
2223
+ });
2276
2224
  return {
2277
2225
  success: true,
2278
2226
  elbResult,
@@ -2286,7 +2234,7 @@ async function executeWebPush(bundlePath, event, logger2) {
2286
2234
  };
2287
2235
  }
2288
2236
  }
2289
- async function executeServerPush(bundlePath, event, logger2, timeout = 6e4) {
2237
+ async function executeServerPush(bundlePath, event, logger2, timeout = 6e4, context = {}) {
2290
2238
  const startTime = Date.now();
2291
2239
  try {
2292
2240
  const timeoutPromise = new Promise((_, reject) => {
@@ -2302,15 +2250,18 @@ async function executeServerPush(bundlePath, event, logger2, timeout = 6e4) {
2302
2250
  throw new Error("Bundle does not export default factory function");
2303
2251
  }
2304
2252
  logger2.debug("Calling factory function...");
2305
- const result = await flowModule.default();
2306
- if (!result || !result.elb || typeof result.elb !== "function") {
2253
+ const result = await flowModule.default(context);
2254
+ if (!result || !result.collector || typeof result.collector.push !== "function") {
2307
2255
  throw new Error(
2308
- "Factory function did not return valid result with elb"
2256
+ "Factory function did not return valid result with collector"
2309
2257
  );
2310
2258
  }
2311
- const { elb } = result;
2312
- logger2.info(`Pushing event: ${event.name}`);
2313
- const elbResult = await elb(event.name, event.data);
2259
+ const { collector } = result;
2260
+ logger2.log(`Pushing event: ${event.name}`);
2261
+ const elbResult = await collector.push({
2262
+ name: event.name,
2263
+ data: event.data
2264
+ });
2314
2265
  return {
2315
2266
  success: true,
2316
2267
  elbResult,
@@ -2327,11 +2278,11 @@ async function executeServerPush(bundlePath, event, logger2, timeout = 6e4) {
2327
2278
  }
2328
2279
  }
2329
2280
  function waitForWindowProperty2(window, prop, timeout = 5e3) {
2330
- return new Promise((resolve, reject) => {
2281
+ return new Promise((resolve3, reject) => {
2331
2282
  const start = Date.now();
2332
2283
  const check = () => {
2333
2284
  if (window[prop] !== void 0) {
2334
- resolve();
2285
+ resolve3();
2335
2286
  } else if (Date.now() - start > timeout) {
2336
2287
  reject(
2337
2288
  new Error(
@@ -2430,9 +2381,132 @@ function isPreBuiltConfig(configPath) {
2430
2381
 
2431
2382
  // src/commands/run/execution.ts
2432
2383
  import { createLogger as createLogger2, Level } from "@walkeros/core";
2433
- import { runFlow, runServeMode } from "@walkeros/docker";
2384
+
2385
+ // src/runtime/runner.ts
2386
+ import { pathToFileURL as pathToFileURL2 } from "url";
2387
+ import { resolve, dirname as dirname2 } from "path";
2388
+ async function runFlow(file, config, logger2, loggerConfig2) {
2389
+ logger2.info(`Loading flow from ${file}`);
2390
+ try {
2391
+ const absolutePath = resolve(file);
2392
+ const flowDir = dirname2(absolutePath);
2393
+ process.chdir(flowDir);
2394
+ const fileUrl = pathToFileURL2(absolutePath).href;
2395
+ const module = await import(fileUrl);
2396
+ if (!module.default || typeof module.default !== "function") {
2397
+ logger2.throw(
2398
+ `Invalid flow bundle: ${file} must export a default function`
2399
+ );
2400
+ }
2401
+ const flowContext = loggerConfig2 ? { ...config, logger: loggerConfig2 } : config;
2402
+ const result = await module.default(flowContext);
2403
+ if (!result || !result.collector) {
2404
+ logger2.throw(`Invalid flow bundle: ${file} must return { collector }`);
2405
+ }
2406
+ const { collector } = result;
2407
+ logger2.info("Flow running");
2408
+ if (config?.port) {
2409
+ logger2.info(`Port: ${config.port}`);
2410
+ }
2411
+ const shutdown = async (signal) => {
2412
+ logger2.info(`Received ${signal}, shutting down gracefully...`);
2413
+ try {
2414
+ if (collector.command) {
2415
+ await collector.command("shutdown");
2416
+ }
2417
+ logger2.info("Shutdown complete");
2418
+ process.exit(0);
2419
+ } catch (error) {
2420
+ const message = error instanceof Error ? error.message : String(error);
2421
+ logger2.error(`Error during shutdown: ${message}`);
2422
+ process.exit(1);
2423
+ }
2424
+ };
2425
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
2426
+ process.on("SIGINT", () => shutdown("SIGINT"));
2427
+ await new Promise(() => {
2428
+ });
2429
+ } catch (error) {
2430
+ const message = error instanceof Error ? error.message : String(error);
2431
+ logger2.error(`Failed to run flow: ${message}`);
2432
+ if (error instanceof Error && error.stack) {
2433
+ logger2.debug("Stack trace:", { stack: error.stack });
2434
+ }
2435
+ throw error;
2436
+ }
2437
+ }
2438
+
2439
+ // src/runtime/serve.ts
2440
+ import express from "express";
2441
+ import { resolve as resolve2 } from "path";
2442
+ async function runServeMode(config, logger2) {
2443
+ const port = process.env.PORT ? parseInt(process.env.PORT, 10) : config?.port || 8080;
2444
+ const host = process.env.HOST || config?.host || "0.0.0.0";
2445
+ const file = resolve2(process.env.FILE || config?.file || "./dist/walker.js");
2446
+ const serveName = process.env.SERVE_NAME || config?.serveName || "walker.js";
2447
+ const servePath = process.env.SERVE_PATH || config?.servePath || "";
2448
+ const urlPath = servePath ? `/${servePath}/${serveName}` : `/${serveName}`;
2449
+ logger2.info("Starting single-file server...");
2450
+ logger2.info(`File: ${file}`);
2451
+ logger2.info(`URL: http://${host}:${port}${urlPath}`);
2452
+ try {
2453
+ const app = express();
2454
+ app.get("/health", (req, res) => {
2455
+ res.json({
2456
+ status: "ok",
2457
+ version: VERSION,
2458
+ timestamp: Date.now(),
2459
+ mode: "serve",
2460
+ file,
2461
+ url: urlPath
2462
+ });
2463
+ });
2464
+ app.get(urlPath, (req, res) => {
2465
+ res.type("application/javascript");
2466
+ res.sendFile(file, { dotfiles: "allow" }, (err) => {
2467
+ if (err && !res.headersSent) {
2468
+ const errCode = err.code;
2469
+ const errStatus = err.status || err.statusCode;
2470
+ if (errCode !== "ECONNABORTED") {
2471
+ logger2.error(
2472
+ `sendFile error for ${file}: ${err.message} (code: ${errCode}, status: ${errStatus})`
2473
+ );
2474
+ }
2475
+ if (errStatus === 404 || errCode === "ENOENT" || errCode === "EISDIR" || errCode === "ENOTDIR") {
2476
+ res.status(404).send("File not found");
2477
+ } else if (errCode !== "ECONNABORTED") {
2478
+ res.status(500).send("Internal server error");
2479
+ }
2480
+ }
2481
+ });
2482
+ });
2483
+ const server = app.listen(port, host, () => {
2484
+ logger2.info(`Server listening on http://${host}:${port}`);
2485
+ logger2.info(`GET ${urlPath} - Bundle file`);
2486
+ logger2.info(`GET /health - Health check`);
2487
+ });
2488
+ const shutdownHandler = (signal) => {
2489
+ logger2.info(`Received ${signal}, shutting down...`);
2490
+ server.close(() => {
2491
+ logger2.info("Server closed");
2492
+ process.exit(0);
2493
+ });
2494
+ };
2495
+ process.on("SIGTERM", () => shutdownHandler("SIGTERM"));
2496
+ process.on("SIGINT", () => shutdownHandler("SIGINT"));
2497
+ await new Promise(() => {
2498
+ });
2499
+ } catch (error) {
2500
+ const message = error instanceof Error ? error.message : String(error);
2501
+ logger2.error(`Server failed: ${message}`);
2502
+ process.exit(1);
2503
+ }
2504
+ }
2505
+
2506
+ // src/commands/run/execution.ts
2434
2507
  var logLevel = process.env.VERBOSE === "true" ? Level.DEBUG : Level.INFO;
2435
- var logger = createLogger2({ level: logLevel });
2508
+ var loggerConfig = { level: logLevel };
2509
+ var logger = createLogger2(loggerConfig);
2436
2510
  async function executeRunLocal(mode, flowPath, options) {
2437
2511
  switch (mode) {
2438
2512
  case "collect": {
@@ -2443,7 +2517,7 @@ async function executeRunLocal(mode, flowPath, options) {
2443
2517
  port: options.port,
2444
2518
  host: options.host
2445
2519
  };
2446
- await runFlow(flowPath, config, logger.scope("runner"));
2520
+ await runFlow(flowPath, config, logger.scope("runner"), loggerConfig);
2447
2521
  break;
2448
2522
  }
2449
2523
  case "serve": {
@@ -2478,76 +2552,40 @@ async function runCommand(mode, options) {
2478
2552
  if (mode === "collect") {
2479
2553
  if (isPreBuilt) {
2480
2554
  flowPath = path13.resolve(configPath);
2481
- if (!options.json && !options.silent) {
2482
- logger2.info(`\u{1F4E6} Using pre-built flow: ${path13.basename(flowPath)}`);
2483
- }
2555
+ logger2.debug(`Using pre-built flow: ${path13.basename(flowPath)}`);
2484
2556
  } else {
2485
- if (!options.json && !options.silent) {
2486
- logger2.info("\u{1F528} Building flow bundle...");
2487
- }
2557
+ logger2.debug("Building flow bundle");
2488
2558
  flowPath = await prepareBundleForRun(configPath, {
2489
2559
  verbose: options.verbose,
2490
2560
  silent: options.json || options.silent
2491
2561
  });
2492
- if (!options.json && !options.silent) {
2493
- logger2.success("\u2705 Bundle ready");
2494
- }
2562
+ logger2.debug("Bundle ready");
2495
2563
  }
2496
2564
  }
2497
- const executionMode = getExecutionMode(options);
2498
2565
  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
- }
2566
+ logger2.log(`[DRY-RUN] Would execute locally: run ${mode}`);
2506
2567
  return;
2507
2568
  }
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
- }
2569
+ const modeLabel = mode === "collect" ? "Collector" : "Server";
2570
+ logger2.log(`Starting ${modeLabel}...`);
2571
+ await executeRunLocal(mode, flowPath, {
2572
+ port: options.port,
2573
+ host: options.host,
2574
+ serveName: options.serveName,
2575
+ servePath: options.servePath
2576
+ });
2537
2577
  } catch (error) {
2538
2578
  const duration = timer.getElapsed() / 1e3;
2539
2579
  const errorMessage = getErrorMessage(error);
2540
2580
  if (options.json) {
2541
- const output = {
2581
+ logger2.json({
2542
2582
  success: false,
2543
2583
  mode,
2544
2584
  error: errorMessage,
2545
2585
  duration
2546
- };
2547
- console.log(JSON.stringify(output, null, 2));
2586
+ });
2548
2587
  } else {
2549
- logger2.error("\u274C Run failed:");
2550
- logger2.error(errorMessage);
2588
+ logger2.error(`Error: ${errorMessage}`);
2551
2589
  }
2552
2590
  process.exit(1);
2553
2591
  }
@@ -2598,30 +2636,40 @@ async function run(mode, options) {
2598
2636
 
2599
2637
  // src/commands/cache.ts
2600
2638
  import fs12 from "fs-extra";
2601
- import path14 from "path";
2602
- var CACHE_DIR = path14.join(".tmp", "cache");
2603
2639
  function registerCacheCommand(program2) {
2604
2640
  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) => {
2641
+ 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) => {
2642
+ const logger2 = createLogger({ silent: options.silent });
2643
+ const tmpDir = options.tmpDir;
2606
2644
  if (options.packages) {
2607
- await fs12.remove(path14.join(CACHE_DIR, "packages"));
2608
- console.log("Package cache cleared");
2645
+ await fs12.remove(getTmpPath(tmpDir, "cache", "packages"));
2646
+ logger2.log("Package cache cleared");
2609
2647
  } else if (options.builds) {
2610
- await fs12.remove(path14.join(CACHE_DIR, "builds"));
2611
- console.log("Build cache cleared");
2648
+ await fs12.remove(getTmpPath(tmpDir, "cache", "builds"));
2649
+ logger2.log("Build cache cleared");
2612
2650
  } else {
2613
- await fs12.remove(CACHE_DIR);
2614
- console.log("All caches cleared");
2651
+ await fs12.remove(getTmpPath(tmpDir, "cache"));
2652
+ logger2.log("All caches cleared");
2615
2653
  }
2616
2654
  });
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");
2655
+ cache.command("info").description("Show cache statistics").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
2656
+ const logger2 = createLogger({ silent: options.silent });
2657
+ const tmpDir = options.tmpDir;
2658
+ const packagesDir = getTmpPath(tmpDir, "cache", "packages");
2659
+ const buildsDir = getTmpPath(tmpDir, "cache", "builds");
2620
2660
  const packageCount = await countEntries(packagesDir);
2621
2661
  const buildCount = await countEntries(buildsDir);
2622
- console.log(`Cache directory: ${CACHE_DIR}`);
2623
- console.log(`Cached packages: ${packageCount}`);
2624
- console.log(`Cached builds: ${buildCount}`);
2662
+ logger2.log(`Cache directory: ${getTmpPath(tmpDir, "cache")}`);
2663
+ logger2.log(`Cached packages: ${packageCount}`);
2664
+ logger2.log(`Cached builds: ${buildCount}`);
2665
+ });
2666
+ }
2667
+ function registerCleanCommand(program2) {
2668
+ program2.command("clean").description("Clear the entire temp directory (.tmp/)").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
2669
+ const logger2 = createLogger({ silent: options.silent });
2670
+ const tmpDir = options.tmpDir || getDefaultTmpRoot();
2671
+ await fs12.remove(tmpDir);
2672
+ logger2.log(`Temp directory cleared: ${tmpDir}`);
2625
2673
  });
2626
2674
  }
2627
2675
  async function countEntries(dir) {
@@ -2631,22 +2679,15 @@ async function countEntries(dir) {
2631
2679
  }
2632
2680
 
2633
2681
  // 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
2682
  var program = new Command();
2641
2683
  program.name("walkeros").description("walkerOS CLI - Bundle and deploy walkerOS components").version(VERSION);
2642
2684
  program.hook("preAction", (thisCommand, actionCommand) => {
2643
2685
  const options = actionCommand.opts();
2644
2686
  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}`);
2687
+ console.log(chalk2.hex("#01b5e2")(`walkerOS v${VERSION}`));
2647
2688
  }
2648
2689
  });
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) => {
2690
+ 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
2691
  await bundleCommand({
2651
2692
  config: file || "bundle.config.json",
2652
2693
  flow: options.flow,
@@ -2655,7 +2696,6 @@ program.command("bundle [file]").description("Bundle NPM packages with custom co
2655
2696
  json: options.json,
2656
2697
  cache: options.cache,
2657
2698
  verbose: options.verbose,
2658
- local: options.local,
2659
2699
  dryRun: options.dryRun,
2660
2700
  silent: options.silent
2661
2701
  });
@@ -2663,13 +2703,13 @@ program.command("bundle [file]").description("Bundle NPM packages with custom co
2663
2703
  program.command("simulate [file]").description("Simulate event processing and capture API calls").option(
2664
2704
  "-e, --event <source>",
2665
2705
  "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) => {
2706
+ ).option("-p, --platform <platform>", "Platform override (web or server)").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
2707
  await simulateCommand({
2668
2708
  config: file || "bundle.config.json",
2669
2709
  event: options.event,
2710
+ platform: options.platform,
2670
2711
  json: options.json,
2671
2712
  verbose: options.verbose,
2672
- local: options.local,
2673
2713
  dryRun: options.dryRun,
2674
2714
  silent: options.silent
2675
2715
  });
@@ -2677,35 +2717,34 @@ program.command("simulate [file]").description("Simulate event processing and ca
2677
2717
  program.command("push [file]").description("Push an event through the flow with real API execution").requiredOption(
2678
2718
  "-e, --event <source>",
2679
2719
  "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) => {
2720
+ ).option("--flow <name>", "Flow name (for multi-flow configs)").option("-p, --platform <platform>", "Platform override (web or server)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("-s, --silent", "Suppress output").action(async (file, options) => {
2681
2721
  await pushCommand({
2682
2722
  config: file || "bundle.config.json",
2683
2723
  event: options.event,
2684
2724
  flow: options.flow,
2725
+ platform: options.platform,
2685
2726
  json: options.json,
2686
2727
  verbose: options.verbose,
2687
- silent: options.silent,
2688
- local: options.local
2728
+ silent: options.silent
2689
2729
  });
2690
2730
  });
2691
2731
  var runCmd = program.command("run").description("Run walkerOS flows in collect or serve mode");
2692
2732
  runCmd.command("collect [file]").description(
2693
2733
  "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) => {
2734
+ ).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
2735
  await runCommand("collect", {
2696
2736
  config: file || "server-collect.mjs",
2697
2737
  port: options.port,
2698
2738
  host: options.host,
2699
2739
  json: options.json,
2700
2740
  verbose: options.verbose,
2701
- local: options.local,
2702
2741
  dryRun: options.dryRun,
2703
2742
  silent: options.silent
2704
2743
  });
2705
2744
  });
2706
2745
  runCmd.command("serve [file]").description(
2707
2746
  "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) => {
2747
+ ).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
2748
  await runCommand("serve", {
2710
2749
  config: file || "web-serve.js",
2711
2750
  port: options.port,
@@ -2714,12 +2753,12 @@ runCmd.command("serve [file]").description(
2714
2753
  servePath: options.path,
2715
2754
  json: options.json,
2716
2755
  verbose: options.verbose,
2717
- local: options.local,
2718
2756
  dryRun: options.dryRun,
2719
2757
  silent: options.silent
2720
2758
  });
2721
2759
  });
2722
2760
  registerCacheCommand(program);
2761
+ registerCleanCommand(program);
2723
2762
  program.parse();
2724
2763
  export {
2725
2764
  bundle,