@walkeros/cli 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +247 -46
  3. package/dist/__tests__/bundle/bundler-helpers.test.js +0 -134
  4. package/dist/__tests__/bundle/bundler-helpers.test.js.map +1 -1
  5. package/dist/__tests__/bundle/bundler.test.js +253 -183
  6. package/dist/__tests__/bundle/bundler.test.js.map +1 -1
  7. package/dist/__tests__/bundle/programmatic.test.js +74 -53
  8. package/dist/__tests__/bundle/programmatic.test.js.map +1 -1
  9. package/dist/__tests__/cli.test.js +58 -46
  10. package/dist/__tests__/cli.test.js.map +1 -1
  11. package/dist/__tests__/config-loader.test.d.ts +1 -1
  12. package/dist/__tests__/config-loader.test.js +229 -212
  13. package/dist/__tests__/config-loader.test.js.map +1 -1
  14. package/dist/__tests__/core/build-cache.test.d.ts +2 -0
  15. package/dist/__tests__/core/build-cache.test.d.ts.map +1 -0
  16. package/dist/__tests__/core/build-cache.test.js +55 -0
  17. package/dist/__tests__/core/build-cache.test.js.map +1 -0
  18. package/dist/__tests__/core/cache-utils.test.d.ts +2 -0
  19. package/dist/__tests__/core/cache-utils.test.d.ts.map +1 -0
  20. package/dist/__tests__/core/cache-utils.test.js +70 -0
  21. package/dist/__tests__/core/cache-utils.test.js.map +1 -0
  22. package/dist/__tests__/integration/bundle-run.integration.test.js +8 -4
  23. package/dist/__tests__/integration/bundle-run.integration.test.js.map +1 -1
  24. package/dist/__tests__/simulate/node-executor.test.d.ts +5 -0
  25. package/dist/__tests__/simulate/node-executor.test.d.ts.map +1 -0
  26. package/dist/__tests__/simulate/node-executor.test.js +25 -0
  27. package/dist/__tests__/simulate/node-executor.test.js.map +1 -0
  28. package/dist/__tests__/simulate/server-simulate.integration.test.d.ts +5 -0
  29. package/dist/__tests__/simulate/server-simulate.integration.test.d.ts.map +1 -0
  30. package/dist/__tests__/simulate/server-simulate.integration.test.js +58 -0
  31. package/dist/__tests__/simulate/server-simulate.integration.test.js.map +1 -0
  32. package/dist/__tests__/smoke/production.smoke.test.js +9 -2
  33. package/dist/__tests__/smoke/production.smoke.test.js.map +1 -1
  34. package/dist/commands/bundle/bundler.d.ts +18 -0
  35. package/dist/commands/bundle/bundler.d.ts.map +1 -1
  36. package/dist/commands/bundle/bundler.js +286 -80
  37. package/dist/commands/bundle/bundler.js.map +1 -1
  38. package/dist/commands/bundle/index.d.ts +16 -10
  39. package/dist/commands/bundle/index.d.ts.map +1 -1
  40. package/dist/commands/bundle/index.js +44 -32
  41. package/dist/commands/bundle/index.js.map +1 -1
  42. package/dist/commands/bundle/package-manager.d.ts +2 -1
  43. package/dist/commands/bundle/package-manager.d.ts.map +1 -1
  44. package/dist/commands/bundle/package-manager.js +34 -7
  45. package/dist/commands/bundle/package-manager.js.map +1 -1
  46. package/dist/commands/cache.d.ts +3 -0
  47. package/dist/commands/cache.d.ts.map +1 -0
  48. package/dist/commands/cache.js +44 -0
  49. package/dist/commands/cache.js.map +1 -0
  50. package/dist/commands/push/index.d.ts.map +1 -1
  51. package/dist/commands/push/index.js +49 -44
  52. package/dist/commands/push/index.js.map +1 -1
  53. package/dist/commands/push/types.d.ts +1 -1
  54. package/dist/commands/push/types.d.ts.map +1 -1
  55. package/dist/commands/run/__tests__/run.integration.test.js +14 -15
  56. package/dist/commands/run/__tests__/run.integration.test.js.map +1 -1
  57. package/dist/commands/run/execution.d.ts.map +1 -1
  58. package/dist/commands/run/execution.js +6 -2
  59. package/dist/commands/run/execution.js.map +1 -1
  60. package/dist/commands/run/utils.d.ts +4 -1
  61. package/dist/commands/run/utils.d.ts.map +1 -1
  62. package/dist/commands/run/utils.js +18 -24
  63. package/dist/commands/run/utils.js.map +1 -1
  64. package/dist/commands/run/validators.d.ts +9 -5
  65. package/dist/commands/run/validators.d.ts.map +1 -1
  66. package/dist/commands/run/validators.js +14 -11
  67. package/dist/commands/run/validators.js.map +1 -1
  68. package/dist/commands/simulate/index.d.ts +1 -0
  69. package/dist/commands/simulate/index.d.ts.map +1 -1
  70. package/dist/commands/simulate/index.js +1 -0
  71. package/dist/commands/simulate/index.js.map +1 -1
  72. package/dist/commands/simulate/node-executor.d.ts +28 -0
  73. package/dist/commands/simulate/node-executor.d.ts.map +1 -0
  74. package/dist/commands/simulate/node-executor.js +94 -0
  75. package/dist/commands/simulate/node-executor.js.map +1 -0
  76. package/dist/commands/simulate/simulator.d.ts.map +1 -1
  77. package/dist/commands/simulate/simulator.js +36 -32
  78. package/dist/commands/simulate/simulator.js.map +1 -1
  79. package/dist/config/build-defaults.d.ts +49 -0
  80. package/dist/config/build-defaults.d.ts.map +1 -0
  81. package/dist/config/build-defaults.js +70 -0
  82. package/dist/config/build-defaults.js.map +1 -0
  83. package/dist/config/index.d.ts +6 -7
  84. package/dist/config/index.d.ts.map +1 -1
  85. package/dist/config/index.js +6 -7
  86. package/dist/config/index.js.map +1 -1
  87. package/dist/config/loader.d.ts +34 -27
  88. package/dist/config/loader.d.ts.map +1 -1
  89. package/dist/config/loader.js +107 -92
  90. package/dist/config/loader.js.map +1 -1
  91. package/dist/config/validators.d.ts +34 -8
  92. package/dist/config/validators.d.ts.map +1 -1
  93. package/dist/config/validators.js +59 -21
  94. package/dist/config/validators.js.map +1 -1
  95. package/dist/core/asset-resolver.d.ts +9 -16
  96. package/dist/core/asset-resolver.d.ts.map +1 -1
  97. package/dist/core/asset-resolver.js +30 -41
  98. package/dist/core/asset-resolver.js.map +1 -1
  99. package/dist/core/build-cache.d.ts +23 -0
  100. package/dist/core/build-cache.d.ts.map +1 -0
  101. package/dist/core/build-cache.js +43 -0
  102. package/dist/core/build-cache.js.map +1 -0
  103. package/dist/core/cache-utils.d.ts +27 -0
  104. package/dist/core/cache-utils.d.ts.map +1 -0
  105. package/dist/core/cache-utils.js +60 -0
  106. package/dist/core/cache-utils.js.map +1 -0
  107. package/dist/core/docker.d.ts.map +1 -1
  108. package/dist/core/docker.js +14 -27
  109. package/dist/core/docker.js.map +1 -1
  110. package/dist/core/index.d.ts +1 -0
  111. package/dist/core/index.d.ts.map +1 -1
  112. package/dist/core/index.js +1 -0
  113. package/dist/core/index.js.map +1 -1
  114. package/dist/core/local-packages.d.ts +19 -0
  115. package/dist/core/local-packages.d.ts.map +1 -0
  116. package/dist/core/local-packages.js +60 -0
  117. package/dist/core/local-packages.js.map +1 -0
  118. package/dist/examples/.npm-cache/content-v2/sha512/0d/2d/7581c288670eaf8538ddd9df145b78756ce3be0791c6e0b9cd33429b3bae894525b9bda287a3cedffbcdd2c7b3107bafc03f2b0367eea489eee1cc042abb +1 -0
  119. package/dist/examples/.npm-cache/content-v2/sha512/12/20/bc4f5acca143809f7e07da1fdafb38137d93243de4d5b403e6e10b92d0d3a6e51eab24fe9dbc9d3ed1cd72e8f7a406085e99c422bb2c7d1166cf9f1f564e +0 -0
  120. package/dist/examples/.npm-cache/content-v2/sha512/22/ee/fb2695b01871c1d36946bdcfb49f1b520a57200d0a0b221b1e7d5f047ab38a8b2ab0e5f0e25a00acde1f3f2f9d24430a18f1092d438bc1a9e9891cc45f75 +0 -0
  121. package/dist/examples/.npm-cache/content-v2/sha512/24/89/da1ce6a61bca6de7e132f241a675c01c83738bf6b78af25b5cce01d3030361332b3fe938571e2b721f1555da9ddf930fdcf8c02f0471556071590e68cc09 +0 -0
  122. package/dist/examples/.npm-cache/content-v2/sha512/47/fd/c6be997da99228c3e279b95d4a46d6913947078a178f54ac71795a159f3513b1483232f4c2d0a1f403178bf9f96bb19615de32a9e2133e949880c6bc15e2 +0 -0
  123. package/dist/examples/.npm-cache/content-v2/sha512/4b/1c/c1cb7f8b32102071a89fef97158daa32080ebaedfbbd596880d2213d84e305abc76d2a95a412ded55c1c3d487adcb1ceff87fc2c85d7e2856ebd9d3f16f3 +0 -0
  124. package/dist/examples/.npm-cache/content-v2/sha512/6e/53/ff864769671f44f39d8a3bf904cd646535b745cc4824a8bb3189193b474678049f43b5178ba15cad7f0289046105e70f1565afc84e907120b35a466690fd +1 -0
  125. package/dist/examples/.npm-cache/content-v2/sha512/70/4c/4c8837d446965c5551b4ea527e95fa011744fb727581d82cf35bb5599ea0b57d18baa490f7af93ef9a16e8e45e5c0802737da20575f4056a4a5c9a3cd288 +0 -0
  126. package/dist/examples/.npm-cache/content-v2/sha512/96/ad/05de3bbb12d7de8ea353f962bdaea7d2eb44f707f2973462a6635daf537c67b46cca7764fed7d464fe62152c3f783a07aba1ceb35e09ad446bff05a4b466 +1 -0
  127. package/dist/examples/.npm-cache/content-v2/sha512/b5/20/52dde94e6cef7170f6089c64a4843e57be18be450d956f4e455905aed047ae6a368451c93035e6ac3ee59576b600f03f815afba0836b3a16e10a9aaca4ba +1 -0
  128. package/dist/examples/.npm-cache/content-v2/sha512/c7/a9/d166a1c39f97df312c59261319ba1cf9aac178bda0a0cb697d5ddd78bd8dd38ef1bf40017bcc8633c2049896c2d70696d9bff9280851f270792ff38bb3a0 +1 -0
  129. package/dist/examples/.npm-cache/content-v2/sha512/e0/d0/8c14083b633e6adbd3c6a93da5fc0f6bbd456c5512ef276920bedd8d85d551052adff992de977aff326616a211aaa2d6ddcc801149e9b7f914f566359b6a +1 -0
  130. package/dist/examples/.npm-cache/content-v2/sha512/e7/c5/06ad3fd79ac4f1031fe0b16ea5e54e232ca397bbcd7592c679021cbfb027276099f8c848f3f7a7691f0102ad53aa64f9141e61d729b037a678bd60440d17 +1 -0
  131. package/dist/examples/.npm-cache/content-v2/sha512/f3/28/d5d32329604ed7d471a4949105daa2cc98858cf24f45b0b97c41d0eb0d5a9fe7bf1f69c792161cc6693e4fc1b52e886ac41875ebfb8fe47fafe417ca3e6e +0 -0
  132. package/dist/examples/.npm-cache/index-v5/04/5a/2b5d7a7c407d85d746baa0f5c9388a333e35a717a8a0a81943daa6cb1364 +3 -0
  133. package/dist/examples/.npm-cache/index-v5/12/9a/eba560cbace295d8ee04cf283015377bd77b379e70968fb6bc407c7fc410 +15 -0
  134. package/dist/examples/.npm-cache/index-v5/2f/a2/7b047564b0ee21ac835ec609e89153dd6549be554d098584d5bfd19fe043 +15 -0
  135. package/dist/examples/.npm-cache/index-v5/32/8e/322d58dd8d1e000be248ada51385bf96288e56039de9feec1a4c6a467653 +3 -0
  136. package/dist/examples/.npm-cache/index-v5/57/93/d1d7cd1402e3e26468db03f2870822bb2c9018a506cdfb3b405f38cd3e1c +3 -0
  137. package/dist/examples/.npm-cache/index-v5/5d/f8/0a1f4fa7149e4ff33e09eb6aea41ac8d1730c868a5d3ace91f762698acff +3 -0
  138. package/dist/examples/.npm-cache/index-v5/69/a4/a92c72d838259b051cdf8e0acfb2bc680b6d4cfc642314a7836c3f7b2c50 +15 -0
  139. package/dist/examples/.npm-cache/index-v5/71/31/6da3423bb203f3de5eb16c942431073f89be2cfcb40058ec91dcb5ce0abc +15 -0
  140. package/dist/examples/.npm-cache/index-v5/7b/94/72b6bffa050d9ef52a558dd220663695bc606f756be0dfa196ef4f3913ba +3 -0
  141. package/dist/examples/.npm-cache/index-v5/85/9e/99e97fdd562517e56285337db91d1a8f2f416b8d631cf4d7d754fa671299 +15 -0
  142. package/dist/examples/.npm-cache/index-v5/92/4c/9416ada81a9b3c679539fd1ab53f8de3d41ff268f35eba7a194389a85b06 +3 -0
  143. package/dist/examples/.npm-cache/index-v5/c1/5a/13df76b218deed8a6ef12961116af5183db98c53fad1b922fd9edc075247 +3 -0
  144. package/dist/examples/.npm-cache/index-v5/cb/11/253c55410a8ab7c4a9ea9d6e1bf8ef1450a581da64c478074dfd82c8bff6 +3 -0
  145. package/dist/examples/.npm-cache/index-v5/d5/ae/b57fad3a62b5ba2dbdf24b042a9e7b70820f3db00e5a630f02e1fea020dc +3 -0
  146. package/dist/examples/.npm-cache/index-v5/d6/32/2f620f83c7d14451de98de8298c2408e05a16cc0829bd16c891ac19d7a67 +3 -0
  147. package/dist/examples/.npm-cache/index-v5/dd/b5/01dc7a3cd8b6a03a69aee9af500d51ae19cb0aa12631a4aafd152148b8e5 +15 -0
  148. package/dist/examples/.npm-cache/index-v5/e0/cf/6b862c15d74630d3871cd813d305210ab741311deb10baf8813014e0bc30 +3 -0
  149. package/dist/examples/.npm-cache/index-v5/e2/be/e880ccd35950a814d3c1dded34d3938ac61b15a195321dc51357f801aad4 +15 -0
  150. package/dist/examples/.npm-cache/index-v5/e5/1f/f4affe0b392cd03288f23cc03abcb274ff11a2c8f8965299de681914abb2 +3 -0
  151. package/dist/examples/.npm-cache/index-v5/f3/5b/9ebe450958ff0d7cc44ab0a00080cb8a3ff1389744b5eab5f97b68a6a6af +3 -0
  152. package/dist/examples/.npm-cache/index-v5/fb/c1/0de405e902866d53e7c30cf36a97dc2578838622b261816f44dc377c9a80 +3 -0
  153. package/dist/examples/README.md +355 -0
  154. package/dist/examples/event.json +53 -0
  155. package/dist/examples/flow-order-complete.json +67 -0
  156. package/dist/examples/flow-simple.json +31 -0
  157. package/dist/examples/flow.json +82 -0
  158. package/dist/examples/server-collect.json +60 -0
  159. package/dist/examples/server-collect.mjs +13540 -0
  160. package/dist/examples/test.html +43 -0
  161. package/dist/examples/web-serve.js +25503 -0
  162. package/dist/examples/web-serve.json +74 -0
  163. package/dist/index.d.ts +80 -310
  164. package/dist/index.d.ts.map +1 -1
  165. package/dist/index.js +924 -736
  166. package/dist/index.js.map +1 -1
  167. package/dist/schemas/index.d.ts +9 -0
  168. package/dist/schemas/index.d.ts.map +1 -0
  169. package/dist/schemas/index.js +9 -0
  170. package/dist/schemas/index.js.map +1 -0
  171. package/dist/schemas/primitives.d.ts +37 -0
  172. package/dist/schemas/primitives.d.ts.map +1 -0
  173. package/dist/schemas/primitives.js +43 -0
  174. package/dist/schemas/primitives.js.map +1 -0
  175. package/dist/schemas/run.d.ts +23 -0
  176. package/dist/schemas/run.d.ts.map +1 -0
  177. package/dist/schemas/run.js +20 -0
  178. package/dist/schemas/run.js.map +1 -0
  179. package/dist/types/bundle.d.ts +64 -191
  180. package/dist/types/bundle.d.ts.map +1 -1
  181. package/dist/types/bundle.js +2 -2
  182. package/dist/walker.js +1 -0
  183. package/examples/README.md +55 -30
  184. package/examples/flow-order-complete.json +56 -57
  185. package/examples/flow-simple.json +24 -25
  186. package/examples/flow.json +69 -69
  187. package/examples/server-collect.json +51 -44
  188. package/examples/server-collect.mjs +1 -1
  189. package/examples/web-serve.json +62 -63
  190. package/package.json +2 -4
  191. package/dist/__tests__/bundle/serializer.test.d.ts +0 -2
  192. package/dist/__tests__/bundle/serializer.test.d.ts.map +0 -1
  193. package/dist/__tests__/bundle/serializer.test.js +0 -173
  194. package/dist/__tests__/bundle/serializer.test.js.map +0 -1
  195. package/dist/__tests__/bundle/template-engine.test.d.ts +0 -2
  196. package/dist/__tests__/bundle/template-engine.test.d.ts.map +0 -1
  197. package/dist/__tests__/bundle/template-engine.test.js +0 -107
  198. package/dist/__tests__/bundle/template-engine.test.js.map +0 -1
  199. package/dist/commands/bundle/serializer.d.ts +0 -23
  200. package/dist/commands/bundle/serializer.d.ts.map +0 -1
  201. package/dist/commands/bundle/serializer.js +0 -127
  202. package/dist/commands/bundle/serializer.js.map +0 -1
  203. package/dist/commands/bundle/template-engine.d.ts +0 -20
  204. package/dist/commands/bundle/template-engine.d.ts.map +0 -1
  205. package/dist/commands/bundle/template-engine.js +0 -54
  206. package/dist/commands/bundle/template-engine.js.map +0 -1
  207. package/dist/config/defaults.d.ts +0 -33
  208. package/dist/config/defaults.d.ts.map +0 -1
  209. package/dist/config/defaults.js +0 -69
  210. package/dist/config/defaults.js.map +0 -1
  211. package/dist/config/parser.d.ts +0 -128
  212. package/dist/config/parser.d.ts.map +0 -1
  213. package/dist/config/parser.js +0 -256
  214. package/dist/config/parser.js.map +0 -1
  215. package/dist/types/template.d.ts +0 -108
  216. package/dist/types/template.d.ts.map +0 -1
  217. package/dist/types/template.js +0 -10
  218. package/dist/types/template.js.map +0 -1
  219. package/templates/server.hbs +0 -29
  220. package/templates/web.hbs +0 -45
package/dist/index.js CHANGED
@@ -2,9 +2,13 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
- import { readFileSync as readFileSync2 } from "fs";
6
- import { fileURLToPath as fileURLToPath3 } from "url";
5
+ import { readFileSync } from "fs";
6
+ import { fileURLToPath as fileURLToPath2 } from "url";
7
7
  import { dirname, join } from "path";
8
+ import { VERSION as DOCKER_VERSION2 } from "@walkeros/docker";
9
+
10
+ // src/commands/bundle/index.ts
11
+ import path9 from "path";
8
12
 
9
13
  // src/core/logger.ts
10
14
  import chalk from "chalk";
@@ -131,8 +135,6 @@ function formatBytes(bytes) {
131
135
  // src/core/docker.ts
132
136
  import { spawn } from "child_process";
133
137
  import path2 from "path";
134
- import { readFileSync } from "fs";
135
- import { fileURLToPath } from "url";
136
138
  import { VERSION as DOCKER_VERSION } from "@walkeros/docker";
137
139
 
138
140
  // src/config/utils.ts
@@ -262,20 +264,7 @@ async function loadJsonFromSource(source, options) {
262
264
  }
263
265
 
264
266
  // src/core/docker.ts
265
- function readPackageVersion() {
266
- const moduleFilename = fileURLToPath(import.meta.url);
267
- const moduleDir = path2.dirname(moduleFilename);
268
- const prodPath = path2.join(moduleDir, "../package.json");
269
- try {
270
- const pkg = JSON.parse(readFileSync(prodPath, "utf-8"));
271
- return pkg.version;
272
- } catch {
273
- const devPath = path2.join(moduleDir, "../../package.json");
274
- const pkg = JSON.parse(readFileSync(devPath, "utf-8"));
275
- return pkg.version;
276
- }
277
- }
278
- var CLI_VERSION = readPackageVersion();
267
+ var CLI_VERSION = true ? "0.5.0" : "0.0.0";
279
268
  var CLI_DOCKER_IMAGE = process.env.WALKEROS_CLI_DOCKER_IMAGE || `walkeros/cli:${CLI_VERSION}`;
280
269
  var RUNTIME_DOCKER_IMAGE = process.env.WALKEROS_RUNTIME_DOCKER_IMAGE || `walkeros/docker:${DOCKER_VERSION}`;
281
270
  function buildCommonDockerArgs(options) {
@@ -335,7 +324,7 @@ async function executeInDocker(command, args, options = {}, configFile) {
335
324
  if (code === 0) {
336
325
  resolve();
337
326
  } else {
338
- reject(new Error(`Docker command exited with code ${code}`));
327
+ process.exit(code || 1);
339
328
  }
340
329
  });
341
330
  });
@@ -355,8 +344,10 @@ function buildDockerRunCommand(mode, flowPath, options = {}) {
355
344
  cmd.push("-e", `MODE=${mode}`);
356
345
  if (mode === "collect" && flowPath) {
357
346
  const absoluteFlowPath = path2.resolve(cwd, flowPath);
358
- cmd.push("-v", `${absoluteFlowPath}:/app/flow.mjs:ro`);
359
- cmd.push("-e", "FLOW=/app/flow.mjs");
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}`);
360
351
  }
361
352
  if (mode === "serve" && flowPath) {
362
353
  const absoluteFilePath = path2.resolve(cwd, flowPath);
@@ -402,7 +393,7 @@ async function executeRunInDocker(mode, flowPath, options = {}) {
402
393
  if (code === 0) {
403
394
  resolve();
404
395
  } else {
405
- reject(new Error(`Docker command exited with code ${code}`));
396
+ process.exit(code || 1);
406
397
  }
407
398
  });
408
399
  });
@@ -415,22 +406,22 @@ function getExecutionMode(options) {
415
406
  }
416
407
  return "docker";
417
408
  }
418
- async function executeCommand(localHandler, dockerCommand, dockerArgs, options, logger, configFile) {
409
+ async function executeCommand(localHandler, dockerCommand, dockerArgs, options, logger2, configFile) {
419
410
  const mode = getExecutionMode(options);
420
411
  if (options.dryRun) {
421
412
  if (mode === "docker") {
422
413
  const cmd = `docker run walkeros/cli:latest ${dockerCommand} ${dockerArgs.join(" ")}`;
423
- logger?.info(`[DRY-RUN] Would execute: ${cmd}`);
414
+ logger2?.info(`[DRY-RUN] Would execute: ${cmd}`);
424
415
  } else {
425
- logger?.info(
416
+ logger2?.info(
426
417
  `[DRY-RUN] Would execute locally: ${dockerCommand} ${dockerArgs.join(" ")}`
427
418
  );
428
419
  }
429
420
  return;
430
421
  }
431
422
  if (mode === "local") {
432
- if (logger && !options.silent) {
433
- logger.info("\u{1F5A5}\uFE0F Executing locally...");
423
+ if (logger2 && !options.silent) {
424
+ logger2.info("\u{1F5A5}\uFE0F Executing locally...");
434
425
  }
435
426
  await localHandler();
436
427
  } else {
@@ -440,8 +431,8 @@ async function executeCommand(localHandler, dockerCommand, dockerArgs, options,
440
431
  "Docker is not available. Please install Docker or use --local flag to execute locally."
441
432
  );
442
433
  }
443
- if (logger && !options.silent) {
444
- logger.info("\u{1F433} Executing in Docker container...");
434
+ if (logger2 && !options.silent) {
435
+ logger2.info("\u{1F433} Executing in Docker container...");
445
436
  }
446
437
  await executeInDocker(dockerCommand, dockerArgs, options, configFile);
447
438
  }
@@ -452,33 +443,33 @@ import { getHashServer } from "@walkeros/server-core";
452
443
  import fs2 from "fs-extra";
453
444
 
454
445
  // src/core/asset-resolver.ts
455
- import { fileURLToPath as fileURLToPath2 } from "url";
446
+ import { fileURLToPath } from "url";
447
+ import { existsSync } from "fs";
456
448
  import path3 from "path";
457
- function getPackageRoot() {
458
- const currentFile = fileURLToPath2(import.meta.url);
459
- if (currentFile.includes("/src/")) {
460
- const srcIndex = currentFile.indexOf("/src/");
461
- return currentFile.substring(0, srcIndex);
462
- }
463
- if (currentFile.includes("/dist/")) {
464
- const distIndex = currentFile.indexOf("/dist/");
465
- return currentFile.substring(0, distIndex);
449
+ var cachedAssetDir;
450
+ function getAssetDir() {
451
+ if (cachedAssetDir) return cachedAssetDir;
452
+ const currentFile = fileURLToPath(import.meta.url);
453
+ let dir = path3.dirname(currentFile);
454
+ while (dir !== path3.dirname(dir)) {
455
+ if (existsSync(path3.join(dir, "examples"))) {
456
+ cachedAssetDir = dir;
457
+ return dir;
458
+ }
459
+ dir = path3.dirname(dir);
466
460
  }
467
- return path3.resolve(currentFile, "../..");
461
+ cachedAssetDir = path3.dirname(currentFile);
462
+ return cachedAssetDir;
468
463
  }
469
464
  function resolveAsset(assetPath, assetType, baseDir) {
470
- const packageRoot = getPackageRoot();
471
465
  if (!assetPath.includes("/") && !assetPath.includes("\\")) {
472
- if (assetType === "template") {
473
- return path3.join(packageRoot, "templates", assetPath);
474
- }
475
- return path3.join(packageRoot, "examples", assetPath);
466
+ const assetDir = getAssetDir();
467
+ return path3.join(assetDir, "examples", assetPath);
476
468
  }
477
469
  if (path3.isAbsolute(assetPath)) {
478
470
  return assetPath;
479
471
  }
480
- const resolveBase = baseDir || process.cwd();
481
- return path3.resolve(resolveBase, assetPath);
472
+ return path3.resolve(baseDir || process.cwd(), assetPath);
482
473
  }
483
474
 
484
475
  // src/core/utils.ts
@@ -486,273 +477,256 @@ function getErrorMessage(error) {
486
477
  return error instanceof Error ? error.message : String(error);
487
478
  }
488
479
 
489
- // src/config/validators.ts
490
- function isObject(value) {
491
- return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
492
- }
493
- function validatePlatform(platform) {
494
- return platform === "web" || platform === "server";
495
- }
496
- function isMultiEnvConfig(data) {
497
- return isObject(data) && "version" in data && data.version === 1 && "environments" in data && isObject(data.environments);
498
- }
499
- function isSingleEnvConfig(data) {
500
- return isObject(data) && "flow" in data && "build" in data && isObject(data.flow) && isObject(data.build) && "platform" in data.flow;
501
- }
502
-
503
- // src/config/parser.ts
480
+ // src/core/local-packages.ts
504
481
  import path4 from "path";
505
- function parseConfigStructure(rawConfig, options = {}) {
506
- if (isMultiEnvConfig(rawConfig)) {
507
- const setup = rawConfig;
508
- const availableEnvironments = Object.keys(setup.environments);
509
- if (!options.environment) {
510
- throw new Error(
511
- `Multi-environment configuration detected. Please specify an environment using --env flag.
512
- Available environments: ${availableEnvironments.join(", ")}`
513
- );
514
- }
515
- const selectedEnv = options.environment;
516
- if (!setup.environments[selectedEnv]) {
517
- throw new Error(
518
- `Environment "${selectedEnv}" not found in configuration.
519
- Available environments: ${availableEnvironments.join(", ")}`
520
- );
521
- }
522
- const envConfig = setup.environments[selectedEnv];
523
- return {
524
- flowConfig: envConfig.flow,
525
- buildOptions: envConfig.build,
526
- metadata: {
527
- environment: selectedEnv,
528
- isMultiEnvironment: true,
529
- availableEnvironments
530
- }
531
- };
532
- }
533
- if (isSingleEnvConfig(rawConfig)) {
534
- const config = rawConfig;
535
- return {
536
- flowConfig: config.flow,
537
- buildOptions: config.build,
538
- metadata: {
539
- environment: "default",
540
- isMultiEnvironment: false
541
- }
542
- };
543
- }
544
- const configPath = options.configPath || "configuration";
545
- const configType = isObject(rawConfig) ? "platform" in rawConfig ? `invalid platform value: "${rawConfig.platform}"` : 'missing "flow" and "build" fields' : `not an object (got ${typeof rawConfig})`;
546
- throw new Error(
547
- `Invalid configuration format at ${configPath}.
548
- Configuration ${configType}.
549
-
550
- Expected either:
551
- 1. Multi-environment: { version: 1, environments: { prod: { flow: {...}, build: {...} } } }
552
- 2. Single-environment: { flow: { platform: "web" | "server", ... }, build: { packages: {...}, ... } }`
553
- );
554
- }
555
- function normalizeAndValidate(flowConfig, buildOptions, configPath) {
556
- if (!isObject(flowConfig) || !("platform" in flowConfig)) {
482
+ import fs3 from "fs-extra";
483
+ async function resolveLocalPackage(packageName, localPath, configDir, logger2) {
484
+ const absolutePath = path4.isAbsolute(localPath) ? localPath : path4.resolve(configDir, localPath);
485
+ if (!await fs3.pathExists(absolutePath)) {
557
486
  throw new Error(
558
- `Invalid flow config: missing "platform" field. Expected "web" or "server".`
487
+ `Local package path not found: ${localPath} (resolved to ${absolutePath})`
559
488
  );
560
489
  }
561
- const platform = flowConfig.platform;
562
- if (!validatePlatform(platform)) {
490
+ const pkgJsonPath = path4.join(absolutePath, "package.json");
491
+ if (!await fs3.pathExists(pkgJsonPath)) {
563
492
  throw new Error(
564
- `Invalid platform "${platform}". Must be "web" or "server".`
493
+ `No package.json found at ${absolutePath}. Is this a valid package directory?`
565
494
  );
566
495
  }
567
- if (!isObject(buildOptions)) {
568
- throw new Error(
569
- `Invalid build options: expected object, got ${typeof buildOptions}`
496
+ const distPath = path4.join(absolutePath, "dist");
497
+ const hasDistFolder = await fs3.pathExists(distPath);
498
+ if (!hasDistFolder) {
499
+ logger2.warn(
500
+ `\u26A0\uFE0F ${packageName}: No dist/ folder found. Using package root.`
570
501
  );
571
502
  }
572
- const platformDefaults = platform === "web" ? {
573
- platform: "browser",
574
- format: "iife",
575
- target: "es2020",
576
- minify: false,
577
- sourcemap: false,
578
- tempDir: ".tmp",
579
- cache: true
580
- } : {
581
- platform: "node",
582
- format: "esm",
583
- target: "node20",
584
- minify: false,
585
- sourcemap: false,
586
- tempDir: ".tmp",
587
- cache: true
588
- };
589
- const merged = {
590
- ...platformDefaults,
591
- ...buildOptions
592
- };
593
- if (merged.template === void 0) {
594
- merged.template = platform === "server" ? "server.hbs" : "web.hbs";
595
- }
596
- if (merged.format === "iife" && merged.platform === "browser") {
597
- if (merged.windowCollector === void 0) {
598
- merged.windowCollector = "collector";
599
- }
600
- if (merged.windowElb === void 0) {
601
- merged.windowElb = "elb";
602
- }
603
- }
604
- if (configPath && merged.template && !path4.isAbsolute(merged.template) && (merged.template.startsWith("./") || merged.template.startsWith("../"))) {
605
- const configDir = path4.dirname(configPath);
606
- merged.template = path4.resolve(configDir, merged.template);
607
- }
608
- if (!merged.output || merged.output === "") {
609
- merged.output = platform === "web" ? "./dist/walker.js" : "./dist/bundle.js";
610
- }
611
- if (configPath && configPath !== "/unknown/path" && merged.output && !path4.isAbsolute(merged.output)) {
612
- const configDir = path4.dirname(configPath);
613
- merged.output = path4.resolve(configDir, merged.output);
614
- }
615
- if (!merged.packages) {
616
- merged.packages = {};
617
- }
618
- if (merged.code === void 0 || merged.code === "") {
619
- merged.code = "";
620
- }
621
503
  return {
622
- flowConfig,
623
- buildOptions: merged
504
+ name: packageName,
505
+ absolutePath,
506
+ distPath: hasDistFolder ? distPath : absolutePath,
507
+ hasDistFolder
624
508
  };
625
509
  }
626
- function parseBundleConfig(data) {
627
- if (!isObject(data)) {
628
- throw new Error(`Invalid config: expected object, got ${typeof data}`);
629
- }
630
- if (!("flow" in data) || !isObject(data.flow)) {
631
- throw new Error(
632
- `Invalid config: missing "flow" field. Expected format: { flow: { platform: "web" | "server", ... }, build: { ... } }`
633
- );
634
- }
635
- if (!("build" in data) || !isObject(data.build)) {
636
- throw new Error(
637
- `Invalid config: missing "build" field. Expected format: { flow: { platform: "web" | "server", ... }, build: { ... } }`
638
- );
510
+ async function copyLocalPackage(localPkg, targetDir, logger2) {
511
+ const packageDir = path4.join(targetDir, "node_modules", localPkg.name);
512
+ await fs3.ensureDir(path4.dirname(packageDir));
513
+ await fs3.copy(
514
+ path4.join(localPkg.absolutePath, "package.json"),
515
+ path4.join(packageDir, "package.json")
516
+ );
517
+ if (localPkg.hasDistFolder) {
518
+ await fs3.copy(localPkg.distPath, path4.join(packageDir, "dist"));
519
+ } else {
520
+ const entries = await fs3.readdir(localPkg.absolutePath);
521
+ for (const entry of entries) {
522
+ if (!["node_modules", ".turbo", ".git"].includes(entry)) {
523
+ await fs3.copy(
524
+ path4.join(localPkg.absolutePath, entry),
525
+ path4.join(packageDir, entry)
526
+ );
527
+ }
528
+ }
639
529
  }
640
- const buildData = data.build;
641
- if ("packages" in buildData && !isObject(buildData.packages)) {
642
- throw new Error(
643
- `Invalid config: build.packages must be an object, got ${typeof buildData.packages}`
644
- );
530
+ logger2.info(`\u{1F4E6} Using local: ${localPkg.name} from ${localPkg.absolutePath}`);
531
+ return packageDir;
532
+ }
533
+
534
+ // src/config/validators.ts
535
+ import { schemas } from "@walkeros/core/dev";
536
+ var { safeParseSetup } = schemas;
537
+ function isObject(value) {
538
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
539
+ }
540
+ function validateFlowSetup(data) {
541
+ const result = safeParseSetup(data);
542
+ if (!result.success) {
543
+ const errors = result.error.issues.map((issue) => {
544
+ const path15 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
545
+ return ` - ${path15}: ${issue.message}`;
546
+ }).join("\n");
547
+ throw new Error(`Invalid configuration:
548
+ ${errors}`);
645
549
  }
646
- return normalizeAndValidate(data.flow, data.build, "/unknown/path");
550
+ return result.data;
551
+ }
552
+ function getAvailableFlows(setup) {
553
+ return Object.keys(setup.flows);
554
+ }
555
+
556
+ // src/config/build-defaults.ts
557
+ var WEB_BUILD_DEFAULTS = {
558
+ format: "iife",
559
+ platform: "browser",
560
+ target: "es2020",
561
+ minify: true,
562
+ sourcemap: false,
563
+ cache: true,
564
+ tempDir: ".tmp",
565
+ windowCollector: "collector",
566
+ windowElb: "elb"
567
+ };
568
+ var SERVER_BUILD_DEFAULTS = {
569
+ format: "esm",
570
+ platform: "node",
571
+ target: "node20",
572
+ minify: true,
573
+ sourcemap: false,
574
+ cache: true,
575
+ tempDir: ".tmp"
576
+ };
577
+ var DEFAULT_OUTPUT_PATHS = {
578
+ web: "./dist/walker.js",
579
+ server: "./dist/bundle.mjs"
580
+ };
581
+ function getBuildDefaults(platform) {
582
+ return platform === "web" ? WEB_BUILD_DEFAULTS : SERVER_BUILD_DEFAULTS;
647
583
  }
648
- function normalizeConfigs(config, configPath) {
649
- return normalizeAndValidate(config.flow, config.build, configPath);
584
+ function getDefaultOutput(platform) {
585
+ return DEFAULT_OUTPUT_PATHS[platform];
650
586
  }
651
587
 
652
588
  // src/config/loader.ts
589
+ import path5 from "path";
590
+ import fs4 from "fs-extra";
591
+ import { getFlowConfig, getPlatform } from "@walkeros/core";
592
+ var DEFAULT_INCLUDE_FOLDER = "./shared";
653
593
  function loadBundleConfig(rawConfig, options) {
654
- const { flowConfig, buildOptions, metadata } = parseConfigStructure(
655
- rawConfig,
656
- {
657
- configPath: options.configPath,
658
- environment: options.environment
659
- }
660
- );
661
- const normalized = normalizeAndValidate(
662
- flowConfig,
663
- buildOptions,
664
- options.configPath
665
- );
666
- if (metadata.isMultiEnvironment && options.logger) {
667
- options.logger.info(
668
- `\u{1F4E6} Using environment: ${metadata.environment} (${metadata.availableEnvironments?.length || 0} total)`
669
- );
670
- }
671
- if (!metadata.isMultiEnvironment && options.environment && options.logger) {
672
- options.logger.warn(
673
- `--env flag specified but configuration is single-environment. Ignoring flag.`
674
- );
675
- }
676
- return {
677
- ...normalized,
678
- ...metadata
679
- };
680
- }
681
- function loadMultiEnvironmentConfig(setup, options) {
682
- const availableEnvironments = Object.keys(setup.environments);
683
- if (!options.environment) {
684
- throw new Error(
685
- `Multi-environment configuration detected. Please specify an environment using --env flag.
686
- Available environments: ${availableEnvironments.join(", ")}`
687
- );
688
- }
689
- const selectedEnv = options.environment;
690
- if (!setup.environments[selectedEnv]) {
594
+ const setup = validateFlowSetup(rawConfig);
595
+ const availableFlows = getAvailableFlows(setup);
596
+ const flowName = resolveFlow(setup, options.flowName, availableFlows);
597
+ const flowConfig = getFlowConfig(setup, flowName);
598
+ const platform = getPlatform(flowConfig);
599
+ if (!platform) {
691
600
  throw new Error(
692
- `Environment "${selectedEnv}" not found in configuration.
693
- Available environments: ${availableEnvironments.join(", ")}`
601
+ `Invalid configuration: flow "${flowName}" must have a "web" or "server" key.`
694
602
  );
695
603
  }
696
- const envConfig = setup.environments[selectedEnv];
697
- const { flowConfig, buildOptions } = normalizeConfigs(
698
- envConfig,
699
- options.configPath
700
- );
701
- if (options.logger) {
604
+ const buildDefaults = getBuildDefaults(platform);
605
+ const packages = flowConfig.packages || {};
606
+ let output = getDefaultOutput(platform);
607
+ if (options.buildOverrides?.output) {
608
+ output = options.buildOverrides.output;
609
+ }
610
+ const configDir = path5.dirname(options.configPath);
611
+ if (!path5.isAbsolute(output)) {
612
+ output = path5.resolve(configDir, output);
613
+ }
614
+ let includes = setup.include;
615
+ if (!includes) {
616
+ const defaultIncludePath = path5.resolve(configDir, DEFAULT_INCLUDE_FOLDER);
617
+ if (fs4.pathExistsSync(defaultIncludePath)) {
618
+ includes = [DEFAULT_INCLUDE_FOLDER];
619
+ }
620
+ }
621
+ const buildOptions = {
622
+ ...buildDefaults,
623
+ packages,
624
+ output,
625
+ include: includes,
626
+ configDir,
627
+ ...options.buildOverrides
628
+ };
629
+ const isMultiFlow = availableFlows.length > 1;
630
+ if (isMultiFlow && options.logger) {
702
631
  options.logger.info(
703
- `\u{1F4E6} Using environment: ${selectedEnv} (${availableEnvironments.length} total)`
632
+ `\u{1F4E6} Using flow: ${flowName} (${availableFlows.length} total)`
704
633
  );
705
634
  }
706
635
  return {
707
636
  flowConfig,
708
637
  buildOptions,
709
- environment: selectedEnv,
710
- isMultiEnvironment: true,
711
- availableEnvironments
638
+ flowName,
639
+ isMultiFlow,
640
+ availableFlows
712
641
  };
713
642
  }
714
- function loadAllEnvironments(rawConfig, options) {
715
- if (!isMultiEnvConfig(rawConfig)) {
643
+ function resolveFlow(setup, requestedFlow, available) {
644
+ if (available.length === 1) {
645
+ return available[0];
646
+ }
647
+ if (!requestedFlow) {
716
648
  throw new Error(
717
- `--all flag requires a multi-environment configuration (Setup format).
718
- Your configuration appears to be single-environment.`
649
+ `Multiple flows found. Please specify a flow using --flow flag.
650
+ Available flows: ${available.join(", ")}`
719
651
  );
720
652
  }
721
- const setup = rawConfig;
722
- const environments = Object.keys(setup.environments);
653
+ if (!available.includes(requestedFlow)) {
654
+ throw new Error(
655
+ `Flow "${requestedFlow}" not found in configuration.
656
+ Available flows: ${available.join(", ")}`
657
+ );
658
+ }
659
+ return requestedFlow;
660
+ }
661
+ function loadAllFlows(rawConfig, options) {
662
+ const setup = validateFlowSetup(rawConfig);
663
+ const flows = getAvailableFlows(setup);
723
664
  if (options.logger) {
724
665
  options.logger.info(
725
- `\u{1F4E6} Loading all ${environments.length} environments: ${environments.join(", ")}`
666
+ `\u{1F4E6} Loading all ${flows.length} flows: ${flows.join(", ")}`
726
667
  );
727
668
  }
728
- return environments.map(
729
- (envName) => loadMultiEnvironmentConfig(setup, {
669
+ return flows.map(
670
+ (name) => loadBundleConfig(rawConfig, {
730
671
  ...options,
731
- environment: envName
672
+ flowName: name
732
673
  })
733
674
  );
734
675
  }
735
676
 
736
677
  // src/commands/bundle/bundler.ts
737
678
  import esbuild from "esbuild";
679
+ import path8 from "path";
680
+ import fs7 from "fs-extra";
681
+ import { packageNameToVariable } from "@walkeros/core";
682
+
683
+ // src/commands/bundle/package-manager.ts
684
+ import pacote from "pacote";
738
685
  import path6 from "path";
739
686
  import fs5 from "fs-extra";
740
687
 
688
+ // src/core/cache-utils.ts
689
+ import { getHashServer as getHashServer2 } from "@walkeros/server-core";
690
+ var HASH_LENGTH = 12;
691
+ function isMutableVersion(version) {
692
+ return version === "latest" || version.includes("^") || version.includes("~") || version.includes("*") || version.includes("x");
693
+ }
694
+ function getTodayDate() {
695
+ return (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
696
+ }
697
+ async function getPackageCacheKey(packageName, version, date) {
698
+ const safeName = packageName.replace(/\//g, "-").replace(/@/g, "");
699
+ if (isMutableVersion(version)) {
700
+ const dateStr = date ?? getTodayDate();
701
+ const input2 = `${safeName}@${version}:${dateStr}`;
702
+ return getHashServer2(input2, HASH_LENGTH);
703
+ }
704
+ const input = `${safeName}@${version}`;
705
+ return getHashServer2(input, HASH_LENGTH);
706
+ }
707
+ function normalizeJson(content) {
708
+ const parsed = JSON.parse(content);
709
+ return JSON.stringify(parsed);
710
+ }
711
+ async function getFlowConfigCacheKey(content, date) {
712
+ const dateStr = date ?? getTodayDate();
713
+ const normalized = normalizeJson(content);
714
+ const input = `${normalized}:${dateStr}`;
715
+ return getHashServer2(input, HASH_LENGTH);
716
+ }
717
+
741
718
  // src/commands/bundle/package-manager.ts
742
- import pacote from "pacote";
743
- import path5 from "path";
744
- import fs3 from "fs-extra";
745
719
  function getPackageDirectory(baseDir, packageName, version) {
746
- return path5.join(baseDir, "node_modules", packageName);
720
+ return path6.join(baseDir, "node_modules", packageName);
747
721
  }
748
- function getCachedPackagePath(pkg, tempDir) {
749
- const cacheDir = path5.join(".tmp", "cache", "packages");
750
- const safeName = pkg.name.replace(/\//g, "-").replace(/@/g, "");
751
- return path5.join(cacheDir, `${safeName}-${pkg.version}`);
722
+ async function getCachedPackagePath(pkg, tempDir) {
723
+ const cacheDir = path6.join(".tmp", "cache", "packages");
724
+ const cacheKey = await getPackageCacheKey(pkg.name, pkg.version);
725
+ return path6.join(cacheDir, cacheKey);
752
726
  }
753
727
  async function isPackageCached(pkg, tempDir) {
754
- const cachedPath = getCachedPackagePath(pkg, tempDir);
755
- return fs3.pathExists(cachedPath);
728
+ const cachedPath = await getCachedPackagePath(pkg, tempDir);
729
+ return fs5.pathExists(cachedPath);
756
730
  }
757
731
  function validateNoDuplicatePackages(packages) {
758
732
  const packageMap = /* @__PURE__ */ new Map();
@@ -778,7 +752,7 @@ Each package must use the same version across all declarations. Please update yo
778
752
  );
779
753
  }
780
754
  }
781
- async function resolveDependencies(pkg, packageDir, logger, visited = /* @__PURE__ */ new Set()) {
755
+ async function resolveDependencies(pkg, packageDir, logger2, visited = /* @__PURE__ */ new Set()) {
782
756
  const dependencies = [];
783
757
  const pkgKey = `${pkg.name}@${pkg.version}`;
784
758
  if (visited.has(pkgKey)) {
@@ -786,9 +760,9 @@ async function resolveDependencies(pkg, packageDir, logger, visited = /* @__PURE
786
760
  }
787
761
  visited.add(pkgKey);
788
762
  try {
789
- const packageJsonPath = path5.join(packageDir, "package.json");
790
- if (await fs3.pathExists(packageJsonPath)) {
791
- const packageJson2 = await fs3.readJson(packageJsonPath);
763
+ const packageJsonPath = path6.join(packageDir, "package.json");
764
+ if (await fs5.pathExists(packageJsonPath)) {
765
+ const packageJson2 = await fs5.readJson(packageJsonPath);
792
766
  const deps = {
793
767
  ...packageJson2.dependencies,
794
768
  ...packageJson2.peerDependencies
@@ -800,16 +774,22 @@ async function resolveDependencies(pkg, packageDir, logger, visited = /* @__PURE
800
774
  }
801
775
  }
802
776
  } catch (error) {
803
- logger.debug(`Failed to read dependencies for ${pkgKey}: ${error}`);
777
+ logger2.debug(`Failed to read dependencies for ${pkgKey}: ${error}`);
804
778
  }
805
779
  return dependencies;
806
780
  }
807
- async function downloadPackages(packages, targetDir, logger, useCache = true) {
781
+ async function downloadPackages(packages, targetDir, logger2, useCache = true, configDir) {
808
782
  const packagePaths = /* @__PURE__ */ new Map();
809
783
  const downloadQueue = [...packages];
810
784
  const processed = /* @__PURE__ */ new Set();
785
+ const localPackageMap = /* @__PURE__ */ new Map();
786
+ for (const pkg of packages) {
787
+ if (pkg.path) {
788
+ localPackageMap.set(pkg.name, pkg.path);
789
+ }
790
+ }
811
791
  validateNoDuplicatePackages(packages);
812
- await fs3.ensureDir(targetDir);
792
+ await fs5.ensureDir(targetDir);
813
793
  while (downloadQueue.length > 0) {
814
794
  const pkg = downloadQueue.shift();
815
795
  const pkgKey = `${pkg.name}@${pkg.version}`;
@@ -817,16 +797,37 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
817
797
  continue;
818
798
  }
819
799
  processed.add(pkgKey);
800
+ if (!pkg.path && localPackageMap.has(pkg.name)) {
801
+ pkg.path = localPackageMap.get(pkg.name);
802
+ }
803
+ if (pkg.path) {
804
+ const localPkg = await resolveLocalPackage(
805
+ pkg.name,
806
+ pkg.path,
807
+ configDir || process.cwd(),
808
+ logger2
809
+ );
810
+ const installedPath = await copyLocalPackage(localPkg, targetDir, logger2);
811
+ packagePaths.set(pkg.name, installedPath);
812
+ const deps = await resolveDependencies(pkg, installedPath, logger2);
813
+ for (const dep of deps) {
814
+ const depKey = `${dep.name}@${dep.version}`;
815
+ if (!processed.has(depKey)) {
816
+ downloadQueue.push(dep);
817
+ }
818
+ }
819
+ continue;
820
+ }
820
821
  const packageSpec = `${pkg.name}@${pkg.version}`;
821
822
  const packageDir = getPackageDirectory(targetDir, pkg.name, pkg.version);
822
- const cachedPath = getCachedPackagePath(pkg, targetDir);
823
+ const cachedPath = await getCachedPackagePath(pkg, targetDir);
823
824
  if (useCache && await isPackageCached(pkg, targetDir)) {
824
- logger.debug(`Using cached ${packageSpec}...`);
825
+ logger2.debug(`Using cached ${packageSpec}...`);
825
826
  try {
826
- await fs3.ensureDir(path5.dirname(packageDir));
827
- await fs3.copy(cachedPath, packageDir);
827
+ await fs5.ensureDir(path6.dirname(packageDir));
828
+ await fs5.copy(cachedPath, packageDir);
828
829
  packagePaths.set(pkg.name, packageDir);
829
- const deps = await resolveDependencies(pkg, packageDir, logger);
830
+ const deps = await resolveDependencies(pkg, packageDir, logger2);
830
831
  for (const dep of deps) {
831
832
  const depKey = `${dep.name}@${dep.version}`;
832
833
  if (!processed.has(depKey)) {
@@ -835,15 +836,15 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
835
836
  }
836
837
  continue;
837
838
  } catch (error) {
838
- logger.debug(
839
+ logger2.debug(
839
840
  `Failed to use cache for ${packageSpec}, downloading fresh: ${error}`
840
841
  );
841
842
  }
842
843
  }
843
- logger.debug(`Downloading ${packageSpec}...`);
844
+ logger2.debug(`Downloading ${packageSpec}...`);
844
845
  try {
845
- await fs3.ensureDir(path5.dirname(packageDir));
846
- const cacheDir = process.env.NPM_CACHE_DIR || path5.join(process.cwd(), ".npm-cache");
846
+ await fs5.ensureDir(path6.dirname(packageDir));
847
+ const cacheDir = process.env.NPM_CACHE_DIR || path6.join(process.cwd(), ".npm-cache");
847
848
  await pacote.extract(packageSpec, packageDir, {
848
849
  // Force npm registry download, prevent workspace resolution
849
850
  registry: "https://registry.npmjs.org",
@@ -856,15 +857,15 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
856
857
  });
857
858
  if (useCache) {
858
859
  try {
859
- await fs3.ensureDir(path5.dirname(cachedPath));
860
- await fs3.copy(packageDir, cachedPath);
861
- logger.debug(`Cached ${packageSpec} for future use`);
860
+ await fs5.ensureDir(path6.dirname(cachedPath));
861
+ await fs5.copy(packageDir, cachedPath);
862
+ logger2.debug(`Cached ${packageSpec} for future use`);
862
863
  } catch (cacheError) {
863
- logger.debug(`Failed to cache ${packageSpec}: ${cacheError}`);
864
+ logger2.debug(`Failed to cache ${packageSpec}: ${cacheError}`);
864
865
  }
865
866
  }
866
867
  packagePaths.set(pkg.name, packageDir);
867
- const deps = await resolveDependencies(pkg, packageDir, logger);
868
+ const deps = await resolveDependencies(pkg, packageDir, logger2);
868
869
  for (const dep of deps) {
869
870
  const depKey = `${dep.name}@${dep.version}`;
870
871
  if (!processed.has(depKey)) {
@@ -878,188 +879,118 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
878
879
  return packagePaths;
879
880
  }
880
881
 
881
- // src/commands/bundle/template-engine.ts
882
- import fs4 from "fs-extra";
883
- import Handlebars from "handlebars";
884
-
885
- // src/commands/bundle/serializer.ts
886
- function serializeToJS(value, options = {}) {
887
- const { indent = 2, singleQuotes = false } = options;
888
- const quote = singleQuotes ? "'" : '"';
889
- function serialize(val, currentIndent = 0) {
890
- if (val === null) return "null";
891
- if (val === void 0) return "undefined";
892
- if (typeof val === "boolean" || typeof val === "number") {
893
- return String(val);
894
- }
895
- if (typeof val === "string") {
896
- if (val.includes("=>")) {
897
- const arrowPatterns = [
898
- /^\s*\([^)]*\)\s*=>/,
899
- // (param) => or () =>
900
- /^\s*\w+\s*=>/,
901
- // param =>
902
- /^\s*\([^)]*\)\s*=>\s*\{/,
903
- // (param) => {
904
- /^\s*\w+\s*=>\s*\{/
905
- // param => {
906
- ];
907
- if (arrowPatterns.some((pattern) => pattern.test(val))) {
908
- return val;
909
- }
910
- }
911
- return quote + val.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"') + quote;
912
- }
913
- if (Array.isArray(val)) {
914
- if (val.length === 0) return "[]";
915
- const nextIndent = currentIndent + indent;
916
- const spacing = " ".repeat(nextIndent);
917
- const items = val.map((item) => spacing + serialize(item, nextIndent)).join(",\n");
918
- return `[
919
- ${items}
920
- ${" ".repeat(currentIndent)}]`;
921
- }
922
- if (isObject(val)) {
923
- const entries = Object.entries(val);
924
- if (entries.length === 0) return "{}";
925
- const nextIndent = currentIndent + indent;
926
- const spacing = " ".repeat(nextIndent);
927
- const props = entries.map(([key, value2]) => {
928
- const needsQuotes = /[^a-zA-Z0-9_$]/.test(key) || /^[0-9]/.test(key);
929
- const keyStr = needsQuotes ? quote + key + quote : key;
930
- return spacing + keyStr + ": " + serialize(value2, nextIndent);
931
- }).join(",\n");
932
- return `{
933
- ${props}
934
- ${" ".repeat(currentIndent)}}`;
935
- }
936
- return String(val);
937
- }
938
- return serialize(value);
939
- }
940
- function serializeConfig(config) {
941
- if (!config || Object.keys(config).length === 0) {
942
- return "{}";
943
- }
944
- return serializeToJS(config, { indent: 2, singleQuotes: true });
945
- }
946
- function processTemplateVariables(variables) {
947
- const processed = { ...variables };
948
- if (isObject(processed.sources)) {
949
- const sourcesObj = processed.sources;
950
- const processedSources = {};
951
- for (const [name, source] of Object.entries(sourcesObj)) {
952
- const typedSource = source;
953
- const { env: _, ...sourceWithoutEnv } = typedSource;
954
- processedSources[name] = {
955
- ...sourceWithoutEnv,
956
- config: isObject(typedSource.config) ? serializeConfig(typedSource.config) : typedSource.config,
957
- // Pass through string configs unchanged
958
- ...typedSource.env !== void 0 && { env: typedSource.env }
959
- };
960
- }
961
- processed.sources = processedSources;
962
- }
963
- if (isObject(processed.destinations)) {
964
- const destinationsObj = processed.destinations;
965
- const processedDestinations = {};
966
- for (const [name, dest] of Object.entries(destinationsObj)) {
967
- const typedDest = dest;
968
- const { env: _, ...destWithoutEnv } = typedDest;
969
- processedDestinations[name] = {
970
- ...destWithoutEnv,
971
- config: isObject(typedDest.config) ? serializeConfig(typedDest.config) : typedDest.config,
972
- ...typedDest.env !== void 0 && { env: typedDest.env }
973
- };
974
- }
975
- processed.destinations = processedDestinations;
976
- }
977
- if (isObject(processed.collector)) {
978
- processed.collector = serializeConfig(
979
- processed.collector
980
- );
882
+ // src/core/build-cache.ts
883
+ import fs6 from "fs-extra";
884
+ import path7 from "path";
885
+ var BUILD_CACHE_DIR = path7.join(".tmp", "cache", "builds");
886
+ async function getBuildCachePath(configContent, cacheDir = BUILD_CACHE_DIR) {
887
+ const cacheKey = await getFlowConfigCacheKey(configContent);
888
+ return path7.join(cacheDir, `${cacheKey}.js`);
889
+ }
890
+ async function isBuildCached(configContent, cacheDir = BUILD_CACHE_DIR) {
891
+ const cachePath = await getBuildCachePath(configContent, cacheDir);
892
+ return fs6.pathExists(cachePath);
893
+ }
894
+ async function cacheBuild(configContent, buildOutput, cacheDir = BUILD_CACHE_DIR) {
895
+ const cachePath = await getBuildCachePath(configContent, cacheDir);
896
+ await fs6.ensureDir(path7.dirname(cachePath));
897
+ await fs6.writeFile(cachePath, buildOutput, "utf-8");
898
+ }
899
+ async function getCachedBuild(configContent, cacheDir = BUILD_CACHE_DIR) {
900
+ const cachePath = await getBuildCachePath(configContent, cacheDir);
901
+ if (await fs6.pathExists(cachePath)) {
902
+ return await fs6.readFile(cachePath, "utf-8");
981
903
  }
982
- return processed;
904
+ return null;
983
905
  }
984
906
 
985
- // src/commands/bundle/template-engine.ts
986
- var TemplateEngine = class {
987
- handlebars;
988
- constructor() {
989
- this.handlebars = Handlebars.create();
990
- this.handlebars.registerHelper("eq", (a, b) => a === b);
991
- }
992
- /**
993
- * Load template content from file path
994
- *
995
- * @param templatePath - Template path (bare name, relative, or absolute)
996
- */
997
- async loadTemplate(templatePath) {
998
- const resolvedPath = resolveAsset(templatePath, "template");
999
- if (!await fs4.pathExists(resolvedPath)) {
1000
- throw new Error(`Template file not found: ${resolvedPath}`);
907
+ // src/commands/bundle/bundler.ts
908
+ async function copyIncludes(includes, sourceDir, outputDir, logger2) {
909
+ for (const include of includes) {
910
+ const sourcePath = path8.resolve(sourceDir, include);
911
+ const folderName = path8.basename(include);
912
+ const destPath = path8.join(outputDir, folderName);
913
+ if (await fs7.pathExists(sourcePath)) {
914
+ await fs7.copy(sourcePath, destPath);
915
+ logger2.debug(`Copied ${include} to output`);
916
+ } else {
917
+ logger2.debug(`Include folder not found: ${include}`);
1001
918
  }
1002
- return await fs4.readFile(resolvedPath, "utf-8");
1003
- }
1004
- /**
1005
- * Apply template with user code and variable substitution
1006
- */
1007
- applyTemplate(template, userCode, sources, destinations, collector, build) {
1008
- const processedVariables = processTemplateVariables({
1009
- sources,
1010
- destinations,
1011
- collector
1012
- });
1013
- const templateData = {
1014
- CODE: userCode,
1015
- build: build || {},
1016
- ...processedVariables
1017
- };
1018
- const compiledTemplate = this.handlebars.compile(template);
1019
- return compiledTemplate(templateData);
1020
- }
1021
- /**
1022
- * Process template with user code
1023
- */
1024
- async process(templatePath, userCode, sources, destinations, collector, build) {
1025
- const template = await this.loadTemplate(templatePath);
1026
- return this.applyTemplate(
1027
- template,
1028
- userCode,
1029
- sources,
1030
- destinations,
1031
- collector,
1032
- build
1033
- );
1034
919
  }
1035
- };
1036
-
1037
- // src/commands/bundle/bundler.ts
1038
- async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
920
+ }
921
+ function generateCacheKeyContent(flowConfig, buildOptions) {
922
+ const configForCache = {
923
+ flow: flowConfig,
924
+ build: {
925
+ ...buildOptions,
926
+ // Exclude non-deterministic fields from cache key
927
+ tempDir: void 0,
928
+ output: void 0
929
+ }
930
+ };
931
+ return JSON.stringify(configForCache);
932
+ }
933
+ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false) {
1039
934
  const bundleStartTime = Date.now();
1040
- const TEMP_DIR = buildOptions.tempDir ? path6.isAbsolute(buildOptions.tempDir) ? buildOptions.tempDir : path6.resolve(buildOptions.tempDir) : getTempDir();
935
+ const TEMP_DIR = buildOptions.tempDir ? path8.isAbsolute(buildOptions.tempDir) ? buildOptions.tempDir : path8.resolve(buildOptions.tempDir) : getTempDir();
936
+ if (buildOptions.cache !== false) {
937
+ const configContent = generateCacheKeyContent(flowConfig, buildOptions);
938
+ const cached = await isBuildCached(configContent);
939
+ if (cached) {
940
+ const cachedBuild = await getCachedBuild(configContent);
941
+ if (cachedBuild) {
942
+ logger2.info("\u2728 Using cached build");
943
+ const outputPath = path8.resolve(buildOptions.output);
944
+ await fs7.ensureDir(path8.dirname(outputPath));
945
+ await fs7.writeFile(outputPath, cachedBuild);
946
+ logger2.gray(`Output: ${outputPath}`);
947
+ logger2.success("\u2705 Build completed (from cache)");
948
+ if (showStats) {
949
+ const stats = await fs7.stat(outputPath);
950
+ const packageStats = Object.entries(buildOptions.packages).map(
951
+ ([name, pkg]) => ({
952
+ name: `${name}@${pkg.version || "latest"}`,
953
+ size: 0
954
+ // Size estimation not available for cached builds
955
+ })
956
+ );
957
+ return {
958
+ totalSize: stats.size,
959
+ packages: packageStats,
960
+ buildTime: Date.now() - bundleStartTime,
961
+ treeshakingEffective: true
962
+ };
963
+ }
964
+ return;
965
+ }
966
+ }
967
+ }
1041
968
  try {
1042
969
  if (!buildOptions.tempDir) {
1043
- await fs5.emptyDir(TEMP_DIR);
970
+ await fs7.emptyDir(TEMP_DIR);
1044
971
  }
1045
- logger.debug("Cleaned temporary directory");
1046
- logger.info("\u{1F4E5} Downloading packages...");
972
+ logger2.debug("Cleaned temporary directory");
973
+ logger2.info("\u{1F4E5} Downloading packages...");
1047
974
  const packagesArray = Object.entries(buildOptions.packages).map(
1048
975
  ([name, packageConfig]) => ({
1049
976
  name,
1050
- version: packageConfig.version || "latest"
977
+ version: packageConfig.version || "latest",
978
+ path: packageConfig.path
979
+ // Pass local path if defined
1051
980
  })
1052
981
  );
1053
982
  const packagePaths = await downloadPackages(
1054
983
  packagesArray,
1055
984
  TEMP_DIR,
1056
- logger,
1057
- buildOptions.cache
985
+ logger2,
986
+ buildOptions.cache,
987
+ buildOptions.configDir
988
+ // For resolving relative local paths
1058
989
  );
1059
990
  for (const [pkgName, pkgPath] of packagePaths.entries()) {
1060
991
  if (pkgName.startsWith("@walkeros/")) {
1061
- const pkgJsonPath = path6.join(pkgPath, "package.json");
1062
- const pkgJson = await fs5.readJSON(pkgJsonPath);
992
+ const pkgJsonPath = path8.join(pkgPath, "package.json");
993
+ const pkgJson = await fs7.readJSON(pkgJsonPath);
1063
994
  if (!pkgJson.exports && pkgJson.module) {
1064
995
  pkgJson.exports = {
1065
996
  ".": {
@@ -1067,33 +998,33 @@ async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
1067
998
  require: pkgJson.main
1068
999
  }
1069
1000
  };
1070
- await fs5.writeJSON(pkgJsonPath, pkgJson, { spaces: 2 });
1001
+ await fs7.writeJSON(pkgJsonPath, pkgJson, { spaces: 2 });
1071
1002
  }
1072
1003
  }
1073
1004
  }
1074
- const packageJsonPath = path6.join(TEMP_DIR, "package.json");
1075
- await fs5.writeFile(
1005
+ const packageJsonPath = path8.join(TEMP_DIR, "package.json");
1006
+ await fs7.writeFile(
1076
1007
  packageJsonPath,
1077
1008
  JSON.stringify({ type: "module" }, null, 2)
1078
1009
  );
1079
- logger.info("\u{1F4DD} Creating entry point...");
1010
+ logger2.info("\u{1F4DD} Creating entry point...");
1080
1011
  const entryContent = await createEntryPoint(
1081
1012
  flowConfig,
1082
1013
  buildOptions,
1083
1014
  packagePaths
1084
1015
  );
1085
- const entryPath = path6.join(TEMP_DIR, "entry.js");
1086
- await fs5.writeFile(entryPath, entryContent);
1087
- logger.info("\u26A1 Bundling with esbuild...");
1088
- const outputPath = path6.resolve(buildOptions.output);
1089
- await fs5.ensureDir(path6.dirname(outputPath));
1016
+ const entryPath = path8.join(TEMP_DIR, "entry.js");
1017
+ await fs7.writeFile(entryPath, entryContent);
1018
+ logger2.info("\u26A1 Bundling with esbuild...");
1019
+ const outputPath = path8.resolve(buildOptions.output);
1020
+ await fs7.ensureDir(path8.dirname(outputPath));
1090
1021
  const esbuildOptions = createEsbuildOptions(
1091
1022
  buildOptions,
1092
1023
  entryPath,
1093
1024
  outputPath,
1094
1025
  TEMP_DIR,
1095
1026
  packagePaths,
1096
- logger
1027
+ logger2
1097
1028
  );
1098
1029
  try {
1099
1030
  await esbuild.build(esbuildOptions);
@@ -1103,7 +1034,13 @@ async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
1103
1034
  buildOptions.code || ""
1104
1035
  );
1105
1036
  }
1106
- logger.gray(`Output: ${outputPath}`);
1037
+ logger2.gray(`Output: ${outputPath}`);
1038
+ if (buildOptions.cache !== false) {
1039
+ const configContent = generateCacheKeyContent(flowConfig, buildOptions);
1040
+ const buildOutput = await fs7.readFile(outputPath, "utf-8");
1041
+ await cacheBuild(configContent, buildOutput);
1042
+ logger2.debug("Build cached for future use");
1043
+ }
1107
1044
  let stats;
1108
1045
  if (showStats) {
1109
1046
  stats = await collectBundleStats(
@@ -1113,21 +1050,30 @@ async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
1113
1050
  entryContent
1114
1051
  );
1115
1052
  }
1053
+ if (buildOptions.include && buildOptions.include.length > 0) {
1054
+ const outputDir = path8.dirname(outputPath);
1055
+ await copyIncludes(
1056
+ buildOptions.include,
1057
+ buildOptions.configDir || process.cwd(),
1058
+ outputDir,
1059
+ logger2
1060
+ );
1061
+ }
1116
1062
  if (!buildOptions.tempDir) {
1117
- await fs5.remove(TEMP_DIR);
1118
- logger.debug("Cleaned up temporary files");
1063
+ await fs7.remove(TEMP_DIR);
1064
+ logger2.debug("Cleaned up temporary files");
1119
1065
  }
1120
1066
  return stats;
1121
1067
  } catch (error) {
1122
1068
  if (!buildOptions.tempDir) {
1123
- await fs5.remove(TEMP_DIR).catch(() => {
1069
+ await fs7.remove(TEMP_DIR).catch(() => {
1124
1070
  });
1125
1071
  }
1126
1072
  throw error;
1127
1073
  }
1128
1074
  }
1129
1075
  async function collectBundleStats(outputPath, packages, startTime, entryContent) {
1130
- const stats = await fs5.stat(outputPath);
1076
+ const stats = await fs7.stat(outputPath);
1131
1077
  const totalSize = stats.size;
1132
1078
  const buildTime = Date.now() - startTime;
1133
1079
  const packageStats = Object.entries(packages).map(([name, pkg]) => {
@@ -1153,7 +1099,7 @@ async function collectBundleStats(outputPath, packages, startTime, entryContent)
1153
1099
  treeshakingEffective
1154
1100
  };
1155
1101
  }
1156
- function createEsbuildOptions(buildOptions, entryPath, outputPath, tempDir, packagePaths, logger) {
1102
+ function createEsbuildOptions(buildOptions, entryPath, outputPath, tempDir, packagePaths, logger2) {
1157
1103
  const alias = {};
1158
1104
  const baseOptions = {
1159
1105
  entryPoints: [entryPath],
@@ -1206,6 +1152,11 @@ function createEsbuildOptions(buildOptions, entryPath, outputPath, tempDir, pack
1206
1152
  ];
1207
1153
  const npmPackages = ["express", "express/*", "cors", "cors/*"];
1208
1154
  baseOptions.external = buildOptions.external ? [...nodeBuiltins, ...npmPackages, ...buildOptions.external] : [...nodeBuiltins, ...npmPackages];
1155
+ if (buildOptions.format === "esm") {
1156
+ baseOptions.banner = {
1157
+ js: `import { createRequire } from 'module';const require = createRequire(import.meta.url);`
1158
+ };
1159
+ }
1209
1160
  }
1210
1161
  if (buildOptions.target) {
1211
1162
  baseOptions.target = buildOptions.target;
@@ -1216,11 +1167,6 @@ function createEsbuildOptions(buildOptions, entryPath, outputPath, tempDir, pack
1216
1167
  }
1217
1168
  return baseOptions;
1218
1169
  }
1219
- function packageNameToVariable(packageName) {
1220
- return packageName.replace("@", "_").replace(/[/-]/g, "_").split("_").map(
1221
- (part, i) => i === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1)
1222
- ).join("");
1223
- }
1224
1170
  function detectDestinationPackages(flowConfig) {
1225
1171
  const destinationPackages = /* @__PURE__ */ new Set();
1226
1172
  const destinations = flowConfig.destinations;
@@ -1233,10 +1179,57 @@ function detectDestinationPackages(flowConfig) {
1233
1179
  }
1234
1180
  return destinationPackages;
1235
1181
  }
1236
- function generateImportStatements(packages, destinationPackages) {
1182
+ function detectSourcePackages(flowConfig) {
1183
+ const sourcePackages = /* @__PURE__ */ new Set();
1184
+ const sources = flowConfig.sources;
1185
+ if (sources) {
1186
+ for (const [sourceKey, sourceConfig] of Object.entries(sources)) {
1187
+ if (typeof sourceConfig === "object" && sourceConfig !== null && "package" in sourceConfig && typeof sourceConfig.package === "string") {
1188
+ sourcePackages.add(sourceConfig.package);
1189
+ }
1190
+ }
1191
+ }
1192
+ return sourcePackages;
1193
+ }
1194
+ function detectExplicitCodeImports(flowConfig) {
1195
+ const explicitCodeImports = /* @__PURE__ */ new Map();
1196
+ const destinations = flowConfig.destinations;
1197
+ if (destinations) {
1198
+ for (const [destKey, destConfig] of Object.entries(destinations)) {
1199
+ if (typeof destConfig === "object" && destConfig !== null && "package" in destConfig && typeof destConfig.package === "string" && "code" in destConfig && typeof destConfig.code === "string") {
1200
+ const isAutoGenerated = destConfig.code.startsWith("_");
1201
+ if (!isAutoGenerated) {
1202
+ if (!explicitCodeImports.has(destConfig.package)) {
1203
+ explicitCodeImports.set(destConfig.package, /* @__PURE__ */ new Set());
1204
+ }
1205
+ explicitCodeImports.get(destConfig.package).add(destConfig.code);
1206
+ }
1207
+ }
1208
+ }
1209
+ }
1210
+ const sources = flowConfig.sources;
1211
+ if (sources) {
1212
+ for (const [sourceKey, sourceConfig] of Object.entries(sources)) {
1213
+ if (typeof sourceConfig === "object" && sourceConfig !== null && "package" in sourceConfig && typeof sourceConfig.package === "string" && "code" in sourceConfig && typeof sourceConfig.code === "string") {
1214
+ const isAutoGenerated = sourceConfig.code.startsWith("_");
1215
+ if (!isAutoGenerated) {
1216
+ if (!explicitCodeImports.has(sourceConfig.package)) {
1217
+ explicitCodeImports.set(sourceConfig.package, /* @__PURE__ */ new Set());
1218
+ }
1219
+ explicitCodeImports.get(sourceConfig.package).add(sourceConfig.code);
1220
+ }
1221
+ }
1222
+ }
1223
+ }
1224
+ return explicitCodeImports;
1225
+ }
1226
+ function generateImportStatements(packages, destinationPackages, sourcePackages, explicitCodeImports) {
1237
1227
  const importStatements = [];
1238
1228
  const examplesMappings = [];
1229
+ const usedPackages = /* @__PURE__ */ new Set([...destinationPackages, ...sourcePackages]);
1239
1230
  for (const [packageName, packageConfig] of Object.entries(packages)) {
1231
+ const isUsedByDestOrSource = usedPackages.has(packageName);
1232
+ const hasExplicitCode = explicitCodeImports.has(packageName);
1240
1233
  if (packageConfig.imports && packageConfig.imports.length > 0) {
1241
1234
  const uniqueImports = [...new Set(packageConfig.imports)];
1242
1235
  const defaultImports = [];
@@ -1276,76 +1269,45 @@ function generateImportStatements(packages, destinationPackages) {
1276
1269
  );
1277
1270
  }
1278
1271
  }
1279
- } else {
1280
- const varName = packageNameToVariable(packageName);
1272
+ } else if (hasExplicitCode) {
1273
+ const codes = Array.from(explicitCodeImports.get(packageName));
1281
1274
  importStatements.push(
1282
- `import * as ${varName} from '${packageName}'; // Consider specifying explicit imports`
1275
+ `import { ${codes.join(", ")} } from '${packageName}';`
1283
1276
  );
1277
+ } else if (isUsedByDestOrSource) {
1278
+ const varName = packageNameToVariable(packageName);
1279
+ importStatements.push(`import ${varName} from '${packageName}';`);
1284
1280
  }
1285
1281
  }
1286
1282
  return { importStatements, examplesMappings };
1287
1283
  }
1288
- async function processTemplate(flowConfig, buildOptions) {
1289
- if (buildOptions.template) {
1290
- const templateEngine = new TemplateEngine();
1291
- const flowWithProps = flowConfig;
1292
- return await templateEngine.process(
1293
- buildOptions.template,
1294
- buildOptions.code || "",
1295
- // Pass user code as parameter (empty if undefined)
1296
- flowWithProps.sources || {},
1297
- flowWithProps.destinations || {},
1298
- flowWithProps.collector || {},
1299
- buildOptions
1300
- // Pass build config to template
1301
- );
1302
- } else {
1303
- return buildOptions.code || "";
1304
- }
1305
- }
1306
- function wrapCodeForFormat(code, format, hasTemplate) {
1307
- if (hasTemplate) {
1308
- return code;
1309
- }
1310
- if (format === "esm") {
1311
- const hasExport = /^\s*export\s/m.test(code);
1312
- if (!hasExport) {
1313
- return `export default ${code}`;
1314
- }
1315
- }
1316
- return code;
1317
- }
1318
- function assembleFinalCode(importStatements, examplesObject, wrappedCode, format) {
1319
- const importsCode = importStatements.join("\n");
1320
- let finalCode = importsCode ? `${importsCode}
1321
-
1322
- ${examplesObject}${wrappedCode}` : `${examplesObject}${wrappedCode}`;
1323
- if (examplesObject && format === "esm") {
1324
- finalCode += `
1325
-
1326
- export { examples };`;
1327
- }
1328
- return finalCode;
1329
- }
1330
1284
  async function createEntryPoint(flowConfig, buildOptions, packagePaths) {
1331
1285
  const destinationPackages = detectDestinationPackages(flowConfig);
1286
+ const sourcePackages = detectSourcePackages(flowConfig);
1287
+ const explicitCodeImports = detectExplicitCodeImports(flowConfig);
1332
1288
  const { importStatements } = generateImportStatements(
1333
1289
  buildOptions.packages,
1334
- destinationPackages
1335
- );
1336
- const examplesObject = "";
1337
- const templatedCode = await processTemplate(flowConfig, buildOptions);
1338
- const wrappedCode = wrapCodeForFormat(
1339
- templatedCode,
1340
- buildOptions.format,
1341
- !!buildOptions.template
1290
+ destinationPackages,
1291
+ sourcePackages,
1292
+ explicitCodeImports
1342
1293
  );
1343
- return assembleFinalCode(
1344
- importStatements,
1345
- examplesObject,
1346
- wrappedCode,
1347
- buildOptions.format
1294
+ const importsCode = importStatements.join("\n");
1295
+ const hasFlow = destinationPackages.size > 0 || sourcePackages.size > 0;
1296
+ if (!hasFlow) {
1297
+ const userCode = buildOptions.code || "";
1298
+ return importsCode ? `${importsCode}
1299
+
1300
+ ${userCode}` : userCode;
1301
+ }
1302
+ const configObject = buildConfigObject(flowConfig, explicitCodeImports);
1303
+ const wrappedCode = generatePlatformWrapper(
1304
+ configObject,
1305
+ buildOptions.code || "",
1306
+ buildOptions
1348
1307
  );
1308
+ return importsCode ? `${importsCode}
1309
+
1310
+ ${wrappedCode}` : wrappedCode;
1349
1311
  }
1350
1312
  function createBuildError(buildError, code) {
1351
1313
  if (!buildError.errors || buildError.errors.length === 0) {
@@ -1370,92 +1332,165 @@ ${firstError.text}`
1370
1332
  ` + (location ? ` at ${location.file}:${location.line}:${location.column}` : "")
1371
1333
  );
1372
1334
  }
1335
+ function buildConfigObject(flowConfig, explicitCodeImports) {
1336
+ const flowWithProps = flowConfig;
1337
+ const sources = flowWithProps.sources || {};
1338
+ const destinations = flowWithProps.destinations || {};
1339
+ const sourcesEntries = Object.entries(sources).map(([key, source]) => {
1340
+ const hasExplicitCode = source.code && explicitCodeImports.has(source.package);
1341
+ const codeVar = hasExplicitCode ? source.code : packageNameToVariable(source.package);
1342
+ const configStr = source.config ? processConfigValue(source.config) : "{}";
1343
+ const envStr = source.env ? `,
1344
+ env: ${processConfigValue(source.env)}` : "";
1345
+ return ` ${key}: {
1346
+ code: ${codeVar},
1347
+ config: ${configStr}${envStr}
1348
+ }`;
1349
+ });
1350
+ const destinationsEntries = Object.entries(destinations).map(
1351
+ ([key, dest]) => {
1352
+ const hasExplicitCode = dest.code && explicitCodeImports.has(dest.package);
1353
+ const codeVar = hasExplicitCode ? dest.code : packageNameToVariable(dest.package);
1354
+ const configStr = dest.config ? processConfigValue(dest.config) : "{}";
1355
+ const envStr = dest.env ? `,
1356
+ env: ${processConfigValue(dest.env)}` : "";
1357
+ return ` ${key}: {
1358
+ code: ${codeVar},
1359
+ config: ${configStr}${envStr}
1360
+ }`;
1361
+ }
1362
+ );
1363
+ const collectorStr = flowWithProps.collector ? `,
1364
+ ...${processConfigValue(flowWithProps.collector)}` : "";
1365
+ return `{
1366
+ sources: {
1367
+ ${sourcesEntries.join(",\n")}
1368
+ },
1369
+ destinations: {
1370
+ ${destinationsEntries.join(",\n")}
1371
+ }${collectorStr}
1372
+ }`;
1373
+ }
1374
+ function processConfigValue(value) {
1375
+ return JSON.stringify(value, null, 2);
1376
+ }
1377
+ function generatePlatformWrapper(configObject, userCode, buildOptions) {
1378
+ if (buildOptions.platform === "browser") {
1379
+ const windowAssignments = [];
1380
+ if (buildOptions.windowCollector) {
1381
+ windowAssignments.push(
1382
+ ` if (typeof window !== 'undefined') window['${buildOptions.windowCollector}'] = collector;`
1383
+ );
1384
+ }
1385
+ if (buildOptions.windowElb) {
1386
+ windowAssignments.push(
1387
+ ` if (typeof window !== 'undefined') window['${buildOptions.windowElb}'] = elb;`
1388
+ );
1389
+ }
1390
+ const assignments = windowAssignments.length > 0 ? "\n" + windowAssignments.join("\n") : "";
1391
+ return `(async () => {
1392
+ const config = ${configObject};
1393
+
1394
+ ${userCode}
1395
+
1396
+ const { collector, elb } = await startFlow(config);${assignments}
1397
+ })();`;
1398
+ } else {
1399
+ const codeSection = userCode ? `
1400
+ ${userCode}
1401
+ ` : "";
1402
+ return `export default async function(context = {}) {
1403
+ const config = ${configObject};${codeSection}
1404
+ return await startFlow(config);
1405
+ }`;
1406
+ }
1407
+ }
1373
1408
 
1374
1409
  // src/commands/bundle/stats.ts
1375
- function displayStats(stats, logger) {
1376
- logger.info("\n\u{1F4CA} Bundle Statistics");
1377
- logger.info("\u2500".repeat(50));
1410
+ function displayStats(stats, logger2) {
1411
+ logger2.info("\n\u{1F4CA} Bundle Statistics");
1412
+ logger2.info("\u2500".repeat(50));
1378
1413
  const sizeKB = formatBytes(stats.totalSize);
1379
- logger.info(`Total Size: ${sizeKB} KB`);
1414
+ logger2.info(`Total Size: ${sizeKB} KB`);
1380
1415
  const timeSeconds = (stats.buildTime / 1e3).toFixed(2);
1381
- logger.info(`Build Time: ${timeSeconds}s`);
1416
+ logger2.info(`Build Time: ${timeSeconds}s`);
1382
1417
  const treeshakingStatus = stats.treeshakingEffective ? "\u2705 Effective" : "\u26A0\uFE0F Not optimal (consider using named imports)";
1383
- logger.info(`Tree-shaking: ${treeshakingStatus}`);
1418
+ logger2.info(`Tree-shaking: ${treeshakingStatus}`);
1384
1419
  if (stats.packages.length > 0) {
1385
- logger.info(`
1420
+ logger2.info(`
1386
1421
  Package Breakdown:`);
1387
1422
  stats.packages.forEach((pkg) => {
1388
1423
  if (pkg.size > 0) {
1389
1424
  const pkgSizeKB = formatBytes(pkg.size);
1390
- logger.info(` \u2022 ${pkg.name}: ${pkgSizeKB} KB`);
1425
+ logger2.info(` \u2022 ${pkg.name}: ${pkgSizeKB} KB`);
1391
1426
  }
1392
1427
  });
1393
1428
  }
1394
- logger.info("\u2500".repeat(50));
1429
+ logger2.info("\u2500".repeat(50));
1395
1430
  }
1396
1431
 
1397
1432
  // src/commands/bundle/index.ts
1398
1433
  async function bundleCommand(options) {
1399
1434
  const timer = createTimer();
1400
1435
  timer.start();
1401
- const logger = createCommandLogger(options);
1436
+ const logger2 = createCommandLogger(options);
1402
1437
  const dockerArgs = buildCommonDockerArgs(options);
1403
- if (options.env) dockerArgs.push("--env", options.env);
1438
+ if (options.flow) dockerArgs.push("--flow", options.flow);
1404
1439
  if (options.all) dockerArgs.push("--all");
1405
1440
  if (options.stats) dockerArgs.push("--stats");
1406
1441
  if (options.cache === false) dockerArgs.push("--no-cache");
1407
1442
  await executeCommand(
1408
1443
  async () => {
1409
1444
  try {
1410
- if (options.env && options.all) {
1411
- throw new Error("Cannot use both --env and --all flags together");
1445
+ if (options.flow && options.all) {
1446
+ throw new Error("Cannot use both --flow and --all flags together");
1412
1447
  }
1413
- logger.info("\u{1F4E6} Reading configuration...");
1414
- const configPath = options.config;
1448
+ logger2.info("\u{1F4E6} Reading configuration...");
1449
+ const configPath = resolveAsset(options.config, "config");
1415
1450
  const rawConfig = await loadJsonConfig(configPath);
1416
- const configsToBundle = options.all ? loadAllEnvironments(rawConfig, { configPath, logger }) : [
1451
+ const configsToBundle = options.all ? loadAllFlows(rawConfig, { configPath, logger: logger2 }) : [
1417
1452
  loadBundleConfig(rawConfig, {
1418
1453
  configPath,
1419
- environment: options.env,
1420
- logger
1454
+ flowName: options.flow,
1455
+ logger: logger2
1421
1456
  })
1422
1457
  ];
1423
1458
  const results = [];
1424
1459
  for (const {
1425
1460
  flowConfig,
1426
1461
  buildOptions,
1427
- environment,
1428
- isMultiEnvironment
1462
+ flowName,
1463
+ isMultiFlow
1429
1464
  } of configsToBundle) {
1430
1465
  try {
1431
1466
  if (options.cache !== void 0) {
1432
1467
  buildOptions.cache = options.cache;
1433
1468
  }
1434
- if (isMultiEnvironment || options.all) {
1435
- logger.info(`
1436
- \u{1F527} Building environment: ${environment}`);
1469
+ if (isMultiFlow || options.all) {
1470
+ logger2.info(`
1471
+ \u{1F527} Building flow: ${flowName}`);
1437
1472
  } else {
1438
- logger.info("\u{1F527} Starting bundle process...");
1473
+ logger2.info("\u{1F527} Starting bundle process...");
1439
1474
  }
1440
1475
  const shouldCollectStats = options.stats || options.json;
1441
1476
  const stats = await bundleCore(
1442
1477
  flowConfig,
1443
1478
  buildOptions,
1444
- logger,
1479
+ logger2,
1445
1480
  shouldCollectStats
1446
1481
  );
1447
1482
  results.push({
1448
- environment,
1483
+ flowName,
1449
1484
  success: true,
1450
1485
  stats
1451
1486
  });
1452
1487
  if (!options.json && !options.all && options.stats && stats) {
1453
- displayStats(stats, logger);
1488
+ displayStats(stats, logger2);
1454
1489
  }
1455
1490
  } catch (error) {
1456
1491
  const errorMessage = getErrorMessage(error);
1457
1492
  results.push({
1458
- environment,
1493
+ flowName,
1459
1494
  success: false,
1460
1495
  error: errorMessage
1461
1496
  });
@@ -1471,7 +1506,7 @@ async function bundleCommand(options) {
1471
1506
  const outputLogger = createLogger({ silent: false, json: false });
1472
1507
  const output = failureCount === 0 ? createSuccessOutput(
1473
1508
  {
1474
- environments: results,
1509
+ flows: results,
1475
1510
  summary: {
1476
1511
  total: results.length,
1477
1512
  success: successCount,
@@ -1480,27 +1515,27 @@ async function bundleCommand(options) {
1480
1515
  },
1481
1516
  duration
1482
1517
  ) : createErrorOutput(
1483
- `${failureCount} environment(s) failed to build`,
1518
+ `${failureCount} flow(s) failed to build`,
1484
1519
  duration
1485
1520
  );
1486
1521
  outputLogger.log("white", JSON.stringify(output, null, 2));
1487
1522
  } else {
1488
1523
  if (options.all) {
1489
- logger.info(`
1524
+ logger2.info(`
1490
1525
  \u{1F4CA} Build Summary:`);
1491
- logger.info(` Total: ${results.length}`);
1492
- logger.success(` \u2705 Success: ${successCount}`);
1526
+ logger2.info(` Total: ${results.length}`);
1527
+ logger2.success(` \u2705 Success: ${successCount}`);
1493
1528
  if (failureCount > 0) {
1494
- logger.error(` \u274C Failed: ${failureCount}`);
1529
+ logger2.error(` \u274C Failed: ${failureCount}`);
1495
1530
  }
1496
1531
  }
1497
1532
  if (failureCount === 0) {
1498
- logger.success(
1533
+ logger2.success(
1499
1534
  `
1500
1535
  \u2705 Bundle created successfully in ${timer.format()}`
1501
1536
  );
1502
1537
  } else {
1503
- throw new Error(`${failureCount} environment(s) failed to build`);
1538
+ throw new Error(`${failureCount} flow(s) failed to build`);
1504
1539
  }
1505
1540
  }
1506
1541
  } catch (error) {
@@ -1511,8 +1546,8 @@ async function bundleCommand(options) {
1511
1546
  const output = createErrorOutput(errorMessage, duration);
1512
1547
  outputLogger.log("white", JSON.stringify(output, null, 2));
1513
1548
  } else {
1514
- logger.error("\u274C Bundle failed:");
1515
- logger.error(errorMessage);
1549
+ logger2.error("\u274C Bundle failed:");
1550
+ logger2.error(errorMessage);
1516
1551
  }
1517
1552
  process.exit(1);
1518
1553
  }
@@ -1520,33 +1555,40 @@ async function bundleCommand(options) {
1520
1555
  "bundle",
1521
1556
  dockerArgs,
1522
1557
  options,
1523
- logger,
1558
+ logger2,
1524
1559
  options.config
1525
1560
  );
1526
1561
  }
1527
1562
  async function bundle(configOrPath, options = {}) {
1528
1563
  let rawConfig;
1564
+ let configPath = path9.resolve(process.cwd(), "walkeros.config.json");
1529
1565
  if (typeof configOrPath === "string") {
1530
- rawConfig = await loadJsonConfig(configOrPath);
1566
+ configPath = resolveAsset(configOrPath, "config");
1567
+ rawConfig = await loadJsonConfig(configPath);
1531
1568
  } else {
1532
1569
  rawConfig = configOrPath;
1533
1570
  }
1534
- const { flowConfig, buildOptions } = parseBundleConfig(rawConfig);
1571
+ const { flowConfig, buildOptions } = loadBundleConfig(rawConfig, {
1572
+ configPath,
1573
+ flowName: options.flowName,
1574
+ buildOverrides: options.buildOverrides
1575
+ });
1535
1576
  if (options.cache !== void 0) {
1536
1577
  buildOptions.cache = options.cache;
1537
1578
  }
1538
- const logger = createCommandLogger(options);
1579
+ const logger2 = createCommandLogger(options);
1539
1580
  return await bundleCore(
1540
1581
  flowConfig,
1541
1582
  buildOptions,
1542
- logger,
1583
+ logger2,
1543
1584
  options.stats ?? false
1544
1585
  );
1545
1586
  }
1546
1587
 
1547
1588
  // src/commands/simulate/simulator.ts
1548
- import path7 from "path";
1549
- import fs7 from "fs-extra";
1589
+ import path10 from "path";
1590
+ import fs9 from "fs-extra";
1591
+ import { getPlatform as getPlatform2 } from "@walkeros/core";
1550
1592
 
1551
1593
  // src/commands/simulate/tracker.ts
1552
1594
  var CallTracker = class {
@@ -1582,9 +1624,9 @@ var CallTracker = class {
1582
1624
  }
1583
1625
  for (const fullPath of paths) {
1584
1626
  const [destKey, ...pathParts] = fullPath.split(":");
1585
- const path11 = pathParts.join(":");
1586
- if (!path11) continue;
1587
- const cleanPath = path11.replace(/^call:/, "");
1627
+ const path15 = pathParts.join(":");
1628
+ if (!path15) continue;
1629
+ const cleanPath = path15.replace(/^call:/, "");
1588
1630
  const parts = cleanPath.split(".");
1589
1631
  let current = wrapped;
1590
1632
  let source = env;
@@ -1628,7 +1670,7 @@ var CallTracker = class {
1628
1670
 
1629
1671
  // src/commands/simulate/jsdom-executor.ts
1630
1672
  import { JSDOM, VirtualConsole } from "jsdom";
1631
- import fs6 from "fs-extra";
1673
+ import fs8 from "fs-extra";
1632
1674
  function buildSandboxFromEnvs(envs, destinations, tracker) {
1633
1675
  const baseBrowserMocks = {
1634
1676
  Image: class MockImage {
@@ -1697,7 +1739,7 @@ async function executeInJSDOM(bundlePath, destinations, event, tracker, envs, ti
1697
1739
  const sandbox = buildSandboxFromEnvs(envs, destinations, tracker);
1698
1740
  Object.assign(window, sandbox.window);
1699
1741
  Object.assign(window.document, sandbox.document);
1700
- const bundleCode = await fs6.readFile(bundlePath, "utf8");
1742
+ const bundleCode = await fs8.readFile(bundlePath, "utf8");
1701
1743
  try {
1702
1744
  window.eval(bundleCode);
1703
1745
  } catch (error) {
@@ -1735,6 +1777,85 @@ async function executeInJSDOM(bundlePath, destinations, event, tracker, envs, ti
1735
1777
  };
1736
1778
  }
1737
1779
 
1780
+ // src/commands/simulate/node-executor.ts
1781
+ import { pathToFileURL } from "url";
1782
+ function buildGlobalMocksFromEnvs(envs, destinations, tracker) {
1783
+ const globalMocks = {};
1784
+ for (const [destKey] of Object.entries(destinations)) {
1785
+ const destEnv = envs[destKey];
1786
+ if (!destEnv?.push) continue;
1787
+ const mockEnv = destEnv.push;
1788
+ const trackPaths = destEnv.simulation || [];
1789
+ const trackedEnv = tracker.wrapEnv(
1790
+ mockEnv,
1791
+ trackPaths.map((p) => `${destKey}:${p}`)
1792
+ );
1793
+ Object.assign(globalMocks, trackedEnv);
1794
+ }
1795
+ return globalMocks;
1796
+ }
1797
+ function injectGlobalMocks(mocks) {
1798
+ const originalValues = {};
1799
+ for (const [key, value] of Object.entries(mocks)) {
1800
+ originalValues[key] = globalThis[key];
1801
+ globalThis[key] = value;
1802
+ }
1803
+ return () => {
1804
+ for (const [key, value] of Object.entries(originalValues)) {
1805
+ if (value === void 0) {
1806
+ delete globalThis[key];
1807
+ } else {
1808
+ globalThis[key] = value;
1809
+ }
1810
+ }
1811
+ };
1812
+ }
1813
+ async function executeInNode(bundlePath, destinations, event, tracker, envs, timeout = 3e4) {
1814
+ const start = Date.now();
1815
+ const globalMocks = buildGlobalMocksFromEnvs(envs, destinations, tracker);
1816
+ const cleanupMocks = injectGlobalMocks(globalMocks);
1817
+ try {
1818
+ const executeWithTimeout = async () => {
1819
+ const importUrl = process.env.JEST_WORKER_ID ? bundlePath : `${pathToFileURL(bundlePath).href}?t=${Date.now()}`;
1820
+ const module = await import(importUrl);
1821
+ if (!module.default || typeof module.default !== "function") {
1822
+ throw new Error("Bundle does not export default factory function");
1823
+ }
1824
+ const result = await module.default();
1825
+ if (!result || !result.elb || typeof result.elb !== "function") {
1826
+ throw new Error(
1827
+ "Factory function did not return valid result with elb"
1828
+ );
1829
+ }
1830
+ const { collector, elb } = result;
1831
+ let elbResult;
1832
+ try {
1833
+ elbResult = await elb(event.name, event.data);
1834
+ } catch (error) {
1835
+ throw new Error(`Event execution failed: ${getErrorMessage(error)}`);
1836
+ }
1837
+ return {
1838
+ collector,
1839
+ elb,
1840
+ elbResult,
1841
+ usage: tracker.getCalls(),
1842
+ duration: Date.now() - start
1843
+ };
1844
+ };
1845
+ const timeoutPromise = new Promise((_, reject) => {
1846
+ setTimeout(
1847
+ () => reject(new Error(`Server simulation timeout after ${timeout}ms`)),
1848
+ timeout
1849
+ );
1850
+ });
1851
+ return await Promise.race([executeWithTimeout(), timeoutPromise]);
1852
+ } catch (error) {
1853
+ throw new Error(`Node execution failed: ${getErrorMessage(error)}`);
1854
+ } finally {
1855
+ cleanupMocks();
1856
+ }
1857
+ }
1858
+
1738
1859
  // src/commands/simulate/env-loader.ts
1739
1860
  async function loadDestinationEnvs(destinations) {
1740
1861
  const envs = {};
@@ -1771,28 +1892,28 @@ function generateId() {
1771
1892
  return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
1772
1893
  }
1773
1894
  async function simulateCore(configPath, event, options = {}) {
1774
- const logger = createLogger({
1895
+ const logger2 = createLogger({
1775
1896
  verbose: options.verbose || false,
1776
1897
  silent: options.silent || false,
1777
1898
  json: options.json || false
1778
1899
  });
1779
1900
  try {
1780
- logger.info("\u{1F3AF} Starting walkerOS simulation...");
1781
- logger.info("\u{1F4E6} Loading bundle configuration...");
1782
- const fullConfigPath = path7.resolve(configPath);
1901
+ logger2.info("\u{1F3AF} Starting walkerOS simulation...");
1902
+ logger2.info("\u{1F4E6} Loading bundle configuration...");
1903
+ const fullConfigPath = path10.resolve(configPath);
1783
1904
  const rawConfig = await loadJsonConfig(fullConfigPath);
1784
- parseBundleConfig(rawConfig);
1785
- logger.info(`\u{1F680} Executing simulation with event: ${JSON.stringify(event)}`);
1905
+ loadBundleConfig(rawConfig, { configPath: fullConfigPath });
1906
+ logger2.info(`\u{1F680} Executing simulation with event: ${JSON.stringify(event)}`);
1786
1907
  const result = await executeSimulation(event, fullConfigPath);
1787
1908
  if (result.success) {
1788
- logger.info(`\u2705 Simulation completed successfully`);
1909
+ logger2.info(`\u2705 Simulation completed successfully`);
1789
1910
  } else {
1790
- logger.error(`\u274C Simulation failed: ${result.error}`);
1911
+ logger2.error(`\u274C Simulation failed: ${result.error}`);
1791
1912
  }
1792
1913
  return result;
1793
1914
  } catch (error) {
1794
1915
  const errorMessage = getErrorMessage(error);
1795
- logger.error(`\u{1F4A5} Simulation error: ${errorMessage}`);
1916
+ logger2.error(`\u{1F4A5} Simulation error: ${errorMessage}`);
1796
1917
  return {
1797
1918
  success: false,
1798
1919
  error: errorMessage
@@ -1825,42 +1946,32 @@ async function executeSimulation(event, configPath) {
1825
1946
  );
1826
1947
  }
1827
1948
  const typedEvent = event;
1828
- await fs7.ensureDir(tempDir);
1949
+ await fs9.ensureDir(tempDir);
1829
1950
  const rawConfig = await loadJsonConfig(configPath);
1830
- const { flowConfig, buildOptions } = parseBundleConfig(rawConfig);
1831
- const packagesArray = Object.entries(buildOptions.packages).map(
1832
- ([name, packageConfig]) => ({
1833
- name,
1834
- version: (typeof packageConfig === "object" && packageConfig !== null && "version" in packageConfig && typeof packageConfig.version === "string" ? packageConfig.version : void 0) || "latest"
1835
- })
1836
- );
1837
- const packagePaths = await downloadPackages(
1838
- packagesArray,
1839
- tempDir,
1840
- // downloadPackages will add 'node_modules' subdirectory itself
1841
- createLogger({ silent: true }),
1842
- buildOptions.cache
1843
- );
1951
+ const { flowConfig, buildOptions } = loadBundleConfig(rawConfig, {
1952
+ configPath
1953
+ });
1954
+ const platform = getPlatform2(flowConfig);
1844
1955
  const tracker = new CallTracker();
1845
- const tempOutput = path7.join(
1956
+ const tempOutput = path10.join(
1846
1957
  tempDir,
1847
- `simulation-bundle-${generateId()}.js`
1958
+ `simulation-bundle-${generateId()}.${platform === "web" ? "js" : "mjs"}`
1848
1959
  );
1849
1960
  const destinations = flowConfig.destinations;
1850
1961
  const simulationBuildOptions = {
1851
1962
  ...buildOptions,
1852
1963
  code: buildOptions.code || "",
1853
- // No code modification - use original
1854
1964
  output: tempOutput,
1855
1965
  tempDir,
1856
- // Use same temp dir for bundle
1857
- format: "iife",
1858
- // ← Test actual production format!
1859
- platform: "browser",
1860
- // ← Browser platform for IIFE
1861
- windowCollector: "collector",
1862
- // ← Ensure window assignment
1863
- windowElb: "elb"
1966
+ ...platform === "web" ? {
1967
+ format: "iife",
1968
+ platform: "browser",
1969
+ windowCollector: "collector",
1970
+ windowElb: "elb"
1971
+ } : {
1972
+ format: "esm",
1973
+ platform: "node"
1974
+ }
1864
1975
  };
1865
1976
  await bundleCore(
1866
1977
  flowConfig,
@@ -1870,16 +1981,26 @@ async function executeSimulation(event, configPath) {
1870
1981
  );
1871
1982
  bundlePath = tempOutput;
1872
1983
  const envs = await loadDestinationEnvs(destinations || {});
1873
- const result = await executeInJSDOM(
1874
- tempOutput,
1875
- destinations || {},
1876
- typedEvent,
1877
- tracker,
1878
- envs,
1879
- // Pass dynamically loaded envs
1880
- 1e4
1881
- // 10s timeout
1882
- );
1984
+ let result;
1985
+ if (platform === "web") {
1986
+ result = await executeInJSDOM(
1987
+ tempOutput,
1988
+ destinations || {},
1989
+ typedEvent,
1990
+ tracker,
1991
+ envs,
1992
+ 1e4
1993
+ );
1994
+ } else {
1995
+ result = await executeInNode(
1996
+ tempOutput,
1997
+ destinations || {},
1998
+ typedEvent,
1999
+ tracker,
2000
+ envs,
2001
+ 3e4
2002
+ );
2003
+ }
1883
2004
  const elbResult = result.elbResult;
1884
2005
  const usage = result.usage;
1885
2006
  const duration = Date.now() - startTime;
@@ -1899,7 +2020,7 @@ async function executeSimulation(event, configPath) {
1899
2020
  };
1900
2021
  } finally {
1901
2022
  if (tempDir) {
1902
- await fs7.remove(tempDir).catch(() => {
2023
+ await fs9.remove(tempDir).catch(() => {
1903
2024
  });
1904
2025
  }
1905
2026
  }
@@ -1907,7 +2028,7 @@ async function executeSimulation(event, configPath) {
1907
2028
 
1908
2029
  // src/commands/simulate/index.ts
1909
2030
  async function simulateCommand(options) {
1910
- const logger = createCommandLogger(options);
2031
+ const logger2 = createCommandLogger(options);
1911
2032
  const dockerArgs = buildCommonDockerArgs(options);
1912
2033
  if (options.event) dockerArgs.push("--event", options.event);
1913
2034
  await executeCommand(
@@ -1958,7 +2079,7 @@ async function simulateCommand(options) {
1958
2079
  "simulate",
1959
2080
  dockerArgs,
1960
2081
  options,
1961
- logger,
2082
+ logger2,
1962
2083
  options.config
1963
2084
  );
1964
2085
  }
@@ -1975,74 +2096,83 @@ async function simulate(configOrPath, event, options = {}) {
1975
2096
  }
1976
2097
 
1977
2098
  // src/commands/push/index.ts
1978
- import path8 from "path";
1979
- import os2 from "os";
2099
+ import path11 from "path";
1980
2100
  import { JSDOM as JSDOM2, VirtualConsole as VirtualConsole2 } from "jsdom";
1981
- import fs8 from "fs-extra";
2101
+ import fs10 from "fs-extra";
2102
+ import { getPlatform as getPlatform3 } from "@walkeros/core";
2103
+ import { schemas as schemas2 } from "@walkeros/core/dev";
1982
2104
  async function pushCommand(options) {
1983
- const logger = createCommandLogger(options);
2105
+ const logger2 = createCommandLogger(options);
1984
2106
  const dockerArgs = buildCommonDockerArgs(options);
1985
2107
  dockerArgs.push("--event", options.event);
1986
- if (options.env) dockerArgs.push("--env", options.env);
2108
+ if (options.flow) dockerArgs.push("--flow", options.flow);
1987
2109
  await executeCommand(
1988
2110
  async () => {
1989
2111
  const startTime = Date.now();
1990
2112
  try {
1991
- logger.info("\u{1F4E5} Loading event...");
2113
+ logger2.info("\u{1F4E5} Loading event...");
1992
2114
  const event = await loadJsonFromSource(options.event, {
1993
2115
  name: "event"
1994
2116
  });
1995
- if (!event || typeof event !== "object" || !("name" in event) || typeof event.name !== "string") {
1996
- throw new Error(
1997
- 'Event must be an object with a "name" property (string)'
1998
- );
2117
+ const eventResult = schemas2.PartialEventSchema.safeParse(event);
2118
+ if (!eventResult.success) {
2119
+ const errors = eventResult.error.issues.map((issue) => `${String(issue.path.join("."))}: ${issue.message}`).join(", ");
2120
+ throw new Error(`Invalid event: ${errors}`);
2121
+ }
2122
+ const parsedEvent = eventResult.data;
2123
+ if (!parsedEvent.name) {
2124
+ throw new Error('Invalid event: Missing required "name" property');
1999
2125
  }
2000
- if (!event.name.includes(" ")) {
2001
- logger.warn(
2002
- `Event name "${event.name}" should follow "ENTITY ACTION" format (e.g., "page view")`
2126
+ const validatedEvent = {
2127
+ name: parsedEvent.name,
2128
+ data: parsedEvent.data || {}
2129
+ };
2130
+ if (!validatedEvent.name.includes(" ")) {
2131
+ logger2.warn(
2132
+ `Event name "${validatedEvent.name}" should follow "ENTITY ACTION" format (e.g., "page view")`
2003
2133
  );
2004
2134
  }
2005
- logger.info("\u{1F4E6} Loading flow configuration...");
2006
- const configPath = path8.resolve(options.config);
2135
+ logger2.info("\u{1F4E6} Loading flow configuration...");
2136
+ const configPath = path11.resolve(options.config);
2007
2137
  const rawConfig = await loadJsonConfig(configPath);
2008
- const { flowConfig, buildOptions, environment, isMultiEnvironment } = loadBundleConfig(rawConfig, {
2138
+ const { flowConfig, buildOptions, flowName, isMultiFlow } = loadBundleConfig(rawConfig, {
2009
2139
  configPath: options.config,
2010
- environment: options.env,
2011
- logger
2140
+ flowName: options.flow,
2141
+ logger: logger2
2012
2142
  });
2013
- const platform = flowConfig.platform;
2014
- logger.info("\u{1F528} Bundling flow configuration...");
2015
- const tempPath = path8.join(
2016
- os2.tmpdir(),
2017
- `walkeros-push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.${platform === "web" ? "js" : "mjs"}`
2143
+ const platform = getPlatform3(flowConfig);
2144
+ logger2.info("\u{1F528} Bundling flow configuration...");
2145
+ const configDir = path11.dirname(configPath);
2146
+ const tempDir = path11.join(
2147
+ configDir,
2148
+ ".tmp",
2149
+ `push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
2018
2150
  );
2019
- const configWithOutput = {
2020
- flow: flowConfig,
2021
- build: {
2022
- ...buildOptions,
2023
- output: tempPath,
2024
- // Web uses IIFE for browser-like execution, server uses ESM
2025
- format: platform === "web" ? "iife" : "esm",
2026
- platform: platform === "web" ? "browser" : "node",
2027
- ...platform === "web" && {
2028
- windowCollector: "collector",
2029
- windowElb: "elb"
2030
- }
2151
+ await fs10.ensureDir(tempDir);
2152
+ const tempPath = path11.join(
2153
+ tempDir,
2154
+ `bundle.${platform === "web" ? "js" : "mjs"}`
2155
+ );
2156
+ const pushBuildOptions = {
2157
+ ...buildOptions,
2158
+ output: tempPath,
2159
+ // Web uses IIFE for browser-like execution, server uses ESM
2160
+ format: platform === "web" ? "iife" : "esm",
2161
+ platform: platform === "web" ? "browser" : "node",
2162
+ ...platform === "web" && {
2163
+ windowCollector: "collector",
2164
+ windowElb: "elb"
2031
2165
  }
2032
2166
  };
2033
- await bundle(configWithOutput, {
2034
- cache: true,
2035
- verbose: options.verbose,
2036
- silent: !options.verbose
2037
- });
2038
- logger.debug(`Bundle created: ${tempPath}`);
2167
+ await bundleCore(flowConfig, pushBuildOptions, logger2, false);
2168
+ logger2.debug(`Bundle created: ${tempPath}`);
2039
2169
  let result;
2040
2170
  if (platform === "web") {
2041
- logger.info("\u{1F310} Executing in web environment (JSDOM)...");
2042
- result = await executeWebPush(tempPath, event, logger);
2171
+ logger2.info("\u{1F310} Executing in web environment (JSDOM)...");
2172
+ result = await executeWebPush(tempPath, validatedEvent, logger2);
2043
2173
  } else if (platform === "server") {
2044
- logger.info("\u{1F5A5}\uFE0F Executing in server environment (Node.js)...");
2045
- result = await executeServerPush(tempPath, event, logger);
2174
+ logger2.info("\u{1F5A5}\uFE0F Executing in server environment (Node.js)...");
2175
+ result = await executeServerPush(tempPath, validatedEvent, logger2);
2046
2176
  } else {
2047
2177
  throw new Error(`Unsupported platform: ${platform}`);
2048
2178
  }
@@ -2063,27 +2193,27 @@ async function pushCommand(options) {
2063
2193
  );
2064
2194
  } else {
2065
2195
  if (result.success) {
2066
- logger.success("\u2705 Event pushed successfully");
2196
+ logger2.success("\u2705 Event pushed successfully");
2067
2197
  if (result.elbResult && typeof result.elbResult === "object") {
2068
2198
  const pushResult = result.elbResult;
2069
2199
  if ("id" in pushResult && pushResult.id) {
2070
- logger.info(` Event ID: ${pushResult.id}`);
2200
+ logger2.info(` Event ID: ${pushResult.id}`);
2071
2201
  }
2072
2202
  if ("entity" in pushResult && pushResult.entity) {
2073
- logger.info(` Entity: ${pushResult.entity}`);
2203
+ logger2.info(` Entity: ${pushResult.entity}`);
2074
2204
  }
2075
2205
  if ("action" in pushResult && pushResult.action) {
2076
- logger.info(` Action: ${pushResult.action}`);
2206
+ logger2.info(` Action: ${pushResult.action}`);
2077
2207
  }
2078
2208
  }
2079
- logger.info(` Duration: ${duration}ms`);
2209
+ logger2.info(` Duration: ${duration}ms`);
2080
2210
  } else {
2081
- logger.error(`\u274C Push failed: ${result.error}`);
2211
+ logger2.error(`\u274C Push failed: ${result.error}`);
2082
2212
  process.exit(1);
2083
2213
  }
2084
2214
  }
2085
2215
  try {
2086
- await fs8.remove(tempPath);
2216
+ await fs10.remove(tempDir);
2087
2217
  } catch {
2088
2218
  }
2089
2219
  } catch (error) {
@@ -2104,7 +2234,7 @@ async function pushCommand(options) {
2104
2234
  )
2105
2235
  );
2106
2236
  } else {
2107
- logger.error(`\u274C Push command failed: ${errorMessage}`);
2237
+ logger2.error(`\u274C Push command failed: ${errorMessage}`);
2108
2238
  }
2109
2239
  process.exit(1);
2110
2240
  }
@@ -2112,11 +2242,11 @@ async function pushCommand(options) {
2112
2242
  "push",
2113
2243
  dockerArgs,
2114
2244
  options,
2115
- logger,
2245
+ logger2,
2116
2246
  options.config
2117
2247
  );
2118
2248
  }
2119
- async function executeWebPush(bundlePath, event, logger) {
2249
+ async function executeWebPush(bundlePath, event, logger2) {
2120
2250
  const startTime = Date.now();
2121
2251
  try {
2122
2252
  const virtualConsole = new VirtualConsole2();
@@ -2127,10 +2257,10 @@ async function executeWebPush(bundlePath, event, logger) {
2127
2257
  virtualConsole
2128
2258
  });
2129
2259
  const { window } = dom;
2130
- logger.debug("Loading bundle...");
2131
- const bundleCode = await fs8.readFile(bundlePath, "utf8");
2260
+ logger2.debug("Loading bundle...");
2261
+ const bundleCode = await fs10.readFile(bundlePath, "utf8");
2132
2262
  window.eval(bundleCode);
2133
- logger.debug("Waiting for elb...");
2263
+ logger2.debug("Waiting for elb...");
2134
2264
  await waitForWindowProperty2(
2135
2265
  window,
2136
2266
  "elb",
@@ -2138,9 +2268,8 @@ async function executeWebPush(bundlePath, event, logger) {
2138
2268
  );
2139
2269
  const windowObj = window;
2140
2270
  const elb = windowObj.elb;
2141
- logger.info(`Pushing event: ${event.name}`);
2142
- const eventData = event.data || {};
2143
- const elbResult = await elb(event.name, eventData);
2271
+ logger2.info(`Pushing event: ${event.name}`);
2272
+ const elbResult = await elb(event.name, event.data);
2144
2273
  return {
2145
2274
  success: true,
2146
2275
  elbResult,
@@ -2154,7 +2283,7 @@ async function executeWebPush(bundlePath, event, logger) {
2154
2283
  };
2155
2284
  }
2156
2285
  }
2157
- async function executeServerPush(bundlePath, event, logger, timeout = 6e4) {
2286
+ async function executeServerPush(bundlePath, event, logger2, timeout = 6e4) {
2158
2287
  const startTime = Date.now();
2159
2288
  try {
2160
2289
  const timeoutPromise = new Promise((_, reject) => {
@@ -2164,12 +2293,12 @@ async function executeServerPush(bundlePath, event, logger, timeout = 6e4) {
2164
2293
  );
2165
2294
  });
2166
2295
  const executePromise = (async () => {
2167
- logger.debug("Importing bundle...");
2296
+ logger2.debug("Importing bundle...");
2168
2297
  const flowModule = await import(bundlePath);
2169
2298
  if (!flowModule.default || typeof flowModule.default !== "function") {
2170
2299
  throw new Error("Bundle does not export default factory function");
2171
2300
  }
2172
- logger.debug("Calling factory function...");
2301
+ logger2.debug("Calling factory function...");
2173
2302
  const result = await flowModule.default();
2174
2303
  if (!result || !result.elb || typeof result.elb !== "function") {
2175
2304
  throw new Error(
@@ -2177,9 +2306,8 @@ async function executeServerPush(bundlePath, event, logger, timeout = 6e4) {
2177
2306
  );
2178
2307
  }
2179
2308
  const { elb } = result;
2180
- logger.info(`Pushing event: ${event.name}`);
2181
- const eventData = event.data || {};
2182
- const elbResult = await elb(event.name, eventData);
2309
+ logger2.info(`Pushing event: ${event.name}`);
2310
+ const elbResult = await elb(event.name, event.data);
2183
2311
  return {
2184
2312
  success: true,
2185
2313
  elbResult,
@@ -2216,23 +2344,40 @@ function waitForWindowProperty2(window, prop, timeout = 5e3) {
2216
2344
  }
2217
2345
 
2218
2346
  // src/commands/run/index.ts
2219
- import path10 from "path";
2347
+ import path13 from "path";
2348
+
2349
+ // src/commands/run/validators.ts
2350
+ import { existsSync as existsSync2 } from "fs";
2351
+
2352
+ // src/schemas/primitives.ts
2353
+ import { z } from "@walkeros/core/dev";
2354
+ var RunModeSchema = z.enum(["collect", "serve"]).describe("CLI run mode: collect events or serve HTTP");
2355
+ var PortSchema = z.number().int("Port must be an integer").min(1, "Port must be at least 1").max(65535, "Port must be at most 65535").describe("HTTP server port number");
2356
+ var FilePathSchema = z.string().min(1, "File path cannot be empty").describe("Path to configuration file");
2357
+
2358
+ // src/schemas/run.ts
2359
+ import { z as z2 } from "@walkeros/core/dev";
2360
+ var RunOptionsSchema = z2.object({
2361
+ mode: RunModeSchema,
2362
+ flow: FilePathSchema,
2363
+ port: PortSchema.default(8080),
2364
+ flowName: z2.string().optional().describe("Specific flow name to run")
2365
+ });
2220
2366
 
2221
2367
  // src/commands/run/validators.ts
2222
- import { existsSync } from "fs";
2223
- var VALID_MODES = ["collect", "serve"];
2224
2368
  function validateMode(mode) {
2225
- if (!VALID_MODES.includes(mode)) {
2369
+ const result = RunModeSchema.safeParse(mode);
2370
+ if (!result.success) {
2226
2371
  throw new Error(
2227
2372
  `Invalid mode: "${mode}"
2228
- Valid modes: ${VALID_MODES.join(", ")}
2373
+ Valid modes: collect, serve
2229
2374
  Example: walkeros run collect ./flow.json`
2230
2375
  );
2231
2376
  }
2232
2377
  }
2233
2378
  function validateFlowFile(filePath) {
2234
2379
  const absolutePath = resolveAsset(filePath, "bundle");
2235
- if (!existsSync(absolutePath)) {
2380
+ if (!existsSync2(absolutePath)) {
2236
2381
  throw new Error(
2237
2382
  `Flow file not found: ${filePath}
2238
2383
  Resolved path: ${absolutePath}
@@ -2242,7 +2387,8 @@ function validateFlowFile(filePath) {
2242
2387
  return absolutePath;
2243
2388
  }
2244
2389
  function validatePort(port) {
2245
- if (!Number.isInteger(port) || port < 1 || port > 65535) {
2390
+ const result = PortSchema.safeParse(port);
2391
+ if (!result.success) {
2246
2392
  throw new Error(
2247
2393
  `Invalid port: ${port}
2248
2394
  Port must be an integer between 1 and 65535
@@ -2252,26 +2398,26 @@ function validatePort(port) {
2252
2398
  }
2253
2399
 
2254
2400
  // src/commands/run/utils.ts
2255
- import path9 from "path";
2256
- import os3 from "os";
2401
+ import path12 from "path";
2402
+ import fs11 from "fs-extra";
2257
2403
  async function prepareBundleForRun(configPath, options) {
2258
- const rawConfig = await loadJsonConfig(configPath);
2259
- const tempPath = path9.join(
2260
- os3.tmpdir(),
2261
- `walkeros-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.mjs`
2404
+ const configDir = path12.dirname(path12.resolve(configPath));
2405
+ const tempDir = path12.join(
2406
+ configDir,
2407
+ ".tmp",
2408
+ `run-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
2262
2409
  );
2263
- const existingBuild = typeof rawConfig === "object" && rawConfig !== null && "build" in rawConfig && typeof rawConfig.build === "object" ? rawConfig.build : {};
2264
- const configWithOutput = {
2265
- ...rawConfig,
2266
- build: {
2267
- ...existingBuild,
2268
- output: tempPath
2269
- }
2270
- };
2271
- await bundle(configWithOutput, {
2410
+ await fs11.ensureDir(tempDir);
2411
+ const tempPath = path12.join(tempDir, "bundle.mjs");
2412
+ await bundle(configPath, {
2272
2413
  cache: true,
2273
2414
  verbose: options.verbose,
2274
- silent: options.silent
2415
+ silent: options.silent,
2416
+ buildOverrides: {
2417
+ output: tempPath,
2418
+ format: "esm",
2419
+ platform: "node"
2420
+ }
2275
2421
  });
2276
2422
  return tempPath;
2277
2423
  }
@@ -2280,7 +2426,10 @@ function isPreBuiltConfig(configPath) {
2280
2426
  }
2281
2427
 
2282
2428
  // src/commands/run/execution.ts
2429
+ import { createLogger as createLogger2, Level } from "@walkeros/core";
2283
2430
  import { runFlow, runServeMode } from "@walkeros/docker";
2431
+ var logLevel = process.env.VERBOSE === "true" ? Level.DEBUG : Level.INFO;
2432
+ var logger = createLogger2({ level: logLevel });
2284
2433
  async function executeRunLocal(mode, flowPath, options) {
2285
2434
  switch (mode) {
2286
2435
  case "collect": {
@@ -2291,7 +2440,7 @@ async function executeRunLocal(mode, flowPath, options) {
2291
2440
  port: options.port,
2292
2441
  host: options.host
2293
2442
  };
2294
- await runFlow(flowPath, config);
2443
+ await runFlow(flowPath, config, logger.scope("runner"));
2295
2444
  break;
2296
2445
  }
2297
2446
  case "serve": {
@@ -2302,7 +2451,7 @@ async function executeRunLocal(mode, flowPath, options) {
2302
2451
  servePath: options.servePath,
2303
2452
  filePath: flowPath || void 0
2304
2453
  };
2305
- await runServeMode(config);
2454
+ await runServeMode(config, logger.scope("serve"));
2306
2455
  break;
2307
2456
  }
2308
2457
  default:
@@ -2314,7 +2463,7 @@ async function executeRunLocal(mode, flowPath, options) {
2314
2463
  async function runCommand(mode, options) {
2315
2464
  const timer = createTimer();
2316
2465
  timer.start();
2317
- const logger = createCommandLogger(options);
2466
+ const logger2 = createCommandLogger(options);
2318
2467
  try {
2319
2468
  validateMode(mode);
2320
2469
  const configPath = validateFlowFile(options.config);
@@ -2325,31 +2474,31 @@ async function runCommand(mode, options) {
2325
2474
  let flowPath = null;
2326
2475
  if (mode === "collect") {
2327
2476
  if (isPreBuilt) {
2328
- flowPath = path10.resolve(configPath);
2477
+ flowPath = path13.resolve(configPath);
2329
2478
  if (!options.json && !options.silent) {
2330
- logger.info(`\u{1F4E6} Using pre-built flow: ${path10.basename(flowPath)}`);
2479
+ logger2.info(`\u{1F4E6} Using pre-built flow: ${path13.basename(flowPath)}`);
2331
2480
  }
2332
2481
  } else {
2333
2482
  if (!options.json && !options.silent) {
2334
- logger.info("\u{1F528} Building flow bundle...");
2483
+ logger2.info("\u{1F528} Building flow bundle...");
2335
2484
  }
2336
2485
  flowPath = await prepareBundleForRun(configPath, {
2337
2486
  verbose: options.verbose,
2338
2487
  silent: options.json || options.silent
2339
2488
  });
2340
2489
  if (!options.json && !options.silent) {
2341
- logger.success("\u2705 Bundle ready");
2490
+ logger2.success("\u2705 Bundle ready");
2342
2491
  }
2343
2492
  }
2344
2493
  }
2345
2494
  const executionMode = getExecutionMode(options);
2346
2495
  if (options.dryRun) {
2347
2496
  if (executionMode === "docker") {
2348
- logger.info(
2497
+ logger2.info(
2349
2498
  `[DRY-RUN] Would execute in Docker: run ${mode} with runtime image`
2350
2499
  );
2351
2500
  } else {
2352
- logger.info(`[DRY-RUN] Would execute locally: run ${mode}`);
2501
+ logger2.info(`[DRY-RUN] Would execute locally: run ${mode}`);
2353
2502
  }
2354
2503
  return;
2355
2504
  }
@@ -2361,7 +2510,7 @@ async function runCommand(mode, options) {
2361
2510
  );
2362
2511
  }
2363
2512
  if (!options.json && !options.silent) {
2364
- logger.info("\u{1F433} Executing in production runtime container...");
2513
+ logger2.info("\u{1F433} Executing in production runtime container...");
2365
2514
  }
2366
2515
  await executeRunInDocker(mode, flowPath, {
2367
2516
  port: options.port,
@@ -2373,7 +2522,7 @@ async function runCommand(mode, options) {
2373
2522
  } else {
2374
2523
  if (!options.json && !options.silent) {
2375
2524
  const modeLabel = mode === "collect" ? "Collector" : "Server";
2376
- logger.info(`\u{1F5A5}\uFE0F Starting ${modeLabel} locally...`);
2525
+ logger2.info(`\u{1F5A5}\uFE0F Starting ${modeLabel} locally...`);
2377
2526
  }
2378
2527
  await executeRunLocal(mode, flowPath, {
2379
2528
  port: options.port,
@@ -2394,8 +2543,8 @@ async function runCommand(mode, options) {
2394
2543
  };
2395
2544
  console.log(JSON.stringify(output, null, 2));
2396
2545
  } else {
2397
- logger.error("\u274C Run failed:");
2398
- logger.error(errorMessage);
2546
+ logger2.error("\u274C Run failed:");
2547
+ logger2.error(errorMessage);
2399
2548
  }
2400
2549
  process.exit(1);
2401
2550
  }
@@ -2416,7 +2565,7 @@ async function run(mode, options) {
2416
2565
  const isPreBuilt = isPreBuiltConfig(flowFile);
2417
2566
  let flowPath;
2418
2567
  if (isPreBuilt) {
2419
- flowPath = path10.resolve(flowFile);
2568
+ flowPath = path13.resolve(flowFile);
2420
2569
  } else {
2421
2570
  flowPath = await prepareBundleForRun(flowFile, {
2422
2571
  verbose: options.verbose,
@@ -2444,22 +2593,60 @@ async function run(mode, options) {
2444
2593
  }
2445
2594
  }
2446
2595
 
2596
+ // src/commands/cache.ts
2597
+ import fs12 from "fs-extra";
2598
+ import path14 from "path";
2599
+ var CACHE_DIR = path14.join(".tmp", "cache");
2600
+ function registerCacheCommand(program2) {
2601
+ const cache = program2.command("cache").description("Manage the CLI cache");
2602
+ 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) => {
2603
+ if (options.packages) {
2604
+ await fs12.remove(path14.join(CACHE_DIR, "packages"));
2605
+ console.log("Package cache cleared");
2606
+ } else if (options.builds) {
2607
+ await fs12.remove(path14.join(CACHE_DIR, "builds"));
2608
+ console.log("Build cache cleared");
2609
+ } else {
2610
+ await fs12.remove(CACHE_DIR);
2611
+ console.log("All caches cleared");
2612
+ }
2613
+ });
2614
+ cache.command("info").description("Show cache statistics").action(async () => {
2615
+ const packagesDir = path14.join(CACHE_DIR, "packages");
2616
+ const buildsDir = path14.join(CACHE_DIR, "builds");
2617
+ const packageCount = await countEntries(packagesDir);
2618
+ const buildCount = await countEntries(buildsDir);
2619
+ console.log(`Cache directory: ${CACHE_DIR}`);
2620
+ console.log(`Cached packages: ${packageCount}`);
2621
+ console.log(`Cached builds: ${buildCount}`);
2622
+ });
2623
+ }
2624
+ async function countEntries(dir) {
2625
+ if (!await fs12.pathExists(dir)) return 0;
2626
+ const entries = await fs12.readdir(dir);
2627
+ return entries.length;
2628
+ }
2629
+
2447
2630
  // src/index.ts
2448
- var __filename = fileURLToPath3(import.meta.url);
2631
+ var __filename = fileURLToPath2(import.meta.url);
2449
2632
  var __dirname = dirname(__filename);
2450
2633
  var packageJson = JSON.parse(
2451
- readFileSync2(join(__dirname, "../package.json"), "utf-8")
2634
+ readFileSync(join(__dirname, "../package.json"), "utf-8")
2452
2635
  );
2453
2636
  var VERSION = packageJson.version;
2454
2637
  var program = new Command();
2455
2638
  program.name("walkeros").description("walkerOS CLI - Bundle and deploy walkerOS components").version(VERSION);
2456
- program.command("bundle [file]").description("Bundle NPM packages with custom code").option(
2457
- "-e, --env <name>",
2458
- "environment to build (for multi-environment configs)"
2459
- ).option("--all", "build all environments (for multi-environment 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) => {
2639
+ program.hook("preAction", (thisCommand, actionCommand) => {
2640
+ const options = actionCommand.opts();
2641
+ if (!options.silent && !options.json) {
2642
+ console.log(`\u{1F680} walkerOS CLI v${VERSION}`);
2643
+ console.log(`\u{1F433} Using Docker runtime: walkeros/docker:${DOCKER_VERSION2}`);
2644
+ }
2645
+ });
2646
+ 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) => {
2460
2647
  await bundleCommand({
2461
2648
  config: file || "bundle.config.json",
2462
- env: options.env,
2649
+ flow: options.flow,
2463
2650
  all: options.all,
2464
2651
  stats: options.stats,
2465
2652
  json: options.json,
@@ -2487,11 +2674,11 @@ program.command("simulate [file]").description("Simulate event processing and ca
2487
2674
  program.command("push [file]").description("Push an event through the flow with real API execution").requiredOption(
2488
2675
  "-e, --event <source>",
2489
2676
  "Event to push (JSON string, file path, or URL)"
2490
- ).option("--env <name>", "Environment name (for multi-environment 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) => {
2677
+ ).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) => {
2491
2678
  await pushCommand({
2492
2679
  config: file || "bundle.config.json",
2493
2680
  event: options.event,
2494
- env: options.env,
2681
+ flow: options.flow,
2495
2682
  json: options.json,
2496
2683
  verbose: options.verbose,
2497
2684
  silent: options.silent,
@@ -2529,6 +2716,7 @@ runCmd.command("serve [file]").description(
2529
2716
  silent: options.silent
2530
2717
  });
2531
2718
  });
2719
+ registerCacheCommand(program);
2532
2720
  program.parse();
2533
2721
  export {
2534
2722
  bundle,