@walkeros/cli 0.4.1 → 0.4.2

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 (194) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +112 -42
  3. package/dist/__tests__/bundle/bundler.test.js +174 -164
  4. package/dist/__tests__/bundle/bundler.test.js.map +1 -1
  5. package/dist/__tests__/bundle/programmatic.test.js +76 -53
  6. package/dist/__tests__/bundle/programmatic.test.js.map +1 -1
  7. package/dist/__tests__/cli.test.js +58 -46
  8. package/dist/__tests__/cli.test.js.map +1 -1
  9. package/dist/__tests__/config-loader.test.d.ts +1 -1
  10. package/dist/__tests__/config-loader.test.js +231 -212
  11. package/dist/__tests__/config-loader.test.js.map +1 -1
  12. package/dist/__tests__/core/build-cache.test.d.ts +2 -0
  13. package/dist/__tests__/core/build-cache.test.d.ts.map +1 -0
  14. package/dist/__tests__/core/build-cache.test.js +55 -0
  15. package/dist/__tests__/core/build-cache.test.js.map +1 -0
  16. package/dist/__tests__/core/cache-utils.test.d.ts +2 -0
  17. package/dist/__tests__/core/cache-utils.test.d.ts.map +1 -0
  18. package/dist/__tests__/core/cache-utils.test.js +70 -0
  19. package/dist/__tests__/core/cache-utils.test.js.map +1 -0
  20. package/dist/__tests__/integration/bundle-run.integration.test.js +8 -4
  21. package/dist/__tests__/integration/bundle-run.integration.test.js.map +1 -1
  22. package/dist/__tests__/simulate/node-executor.test.d.ts +5 -0
  23. package/dist/__tests__/simulate/node-executor.test.d.ts.map +1 -0
  24. package/dist/__tests__/simulate/node-executor.test.js +25 -0
  25. package/dist/__tests__/simulate/node-executor.test.js.map +1 -0
  26. package/dist/__tests__/simulate/server-simulate.integration.test.d.ts +5 -0
  27. package/dist/__tests__/simulate/server-simulate.integration.test.d.ts.map +1 -0
  28. package/dist/__tests__/simulate/server-simulate.integration.test.js +59 -0
  29. package/dist/__tests__/simulate/server-simulate.integration.test.js.map +1 -0
  30. package/dist/__tests__/smoke/production.smoke.test.js +9 -2
  31. package/dist/__tests__/smoke/production.smoke.test.js.map +1 -1
  32. package/dist/commands/bundle/bundler.d.ts.map +1 -1
  33. package/dist/commands/bundle/bundler.js +93 -3
  34. package/dist/commands/bundle/bundler.js.map +1 -1
  35. package/dist/commands/bundle/index.d.ts +16 -10
  36. package/dist/commands/bundle/index.d.ts.map +1 -1
  37. package/dist/commands/bundle/index.js +44 -32
  38. package/dist/commands/bundle/index.js.map +1 -1
  39. package/dist/commands/bundle/package-manager.d.ts +2 -1
  40. package/dist/commands/bundle/package-manager.d.ts.map +1 -1
  41. package/dist/commands/bundle/package-manager.js +34 -7
  42. package/dist/commands/bundle/package-manager.js.map +1 -1
  43. package/dist/commands/cache.d.ts +3 -0
  44. package/dist/commands/cache.d.ts.map +1 -0
  45. package/dist/commands/cache.js +44 -0
  46. package/dist/commands/cache.js.map +1 -0
  47. package/dist/commands/push/index.d.ts.map +1 -1
  48. package/dist/commands/push/index.js +49 -44
  49. package/dist/commands/push/index.js.map +1 -1
  50. package/dist/commands/push/types.d.ts +1 -1
  51. package/dist/commands/push/types.d.ts.map +1 -1
  52. package/dist/commands/run/__tests__/run.integration.test.js +14 -15
  53. package/dist/commands/run/__tests__/run.integration.test.js.map +1 -1
  54. package/dist/commands/run/utils.d.ts +4 -1
  55. package/dist/commands/run/utils.d.ts.map +1 -1
  56. package/dist/commands/run/utils.js +18 -24
  57. package/dist/commands/run/utils.js.map +1 -1
  58. package/dist/commands/run/validators.d.ts +9 -5
  59. package/dist/commands/run/validators.d.ts.map +1 -1
  60. package/dist/commands/run/validators.js +14 -11
  61. package/dist/commands/run/validators.js.map +1 -1
  62. package/dist/commands/simulate/index.d.ts +1 -0
  63. package/dist/commands/simulate/index.d.ts.map +1 -1
  64. package/dist/commands/simulate/index.js +1 -0
  65. package/dist/commands/simulate/index.js.map +1 -1
  66. package/dist/commands/simulate/node-executor.d.ts +28 -0
  67. package/dist/commands/simulate/node-executor.d.ts.map +1 -0
  68. package/dist/commands/simulate/node-executor.js +94 -0
  69. package/dist/commands/simulate/node-executor.js.map +1 -0
  70. package/dist/commands/simulate/simulator.d.ts.map +1 -1
  71. package/dist/commands/simulate/simulator.js +36 -32
  72. package/dist/commands/simulate/simulator.js.map +1 -1
  73. package/dist/config/build-defaults.d.ts +49 -0
  74. package/dist/config/build-defaults.d.ts.map +1 -0
  75. package/dist/config/build-defaults.js +72 -0
  76. package/dist/config/build-defaults.js.map +1 -0
  77. package/dist/config/index.d.ts +6 -7
  78. package/dist/config/index.d.ts.map +1 -1
  79. package/dist/config/index.js +6 -7
  80. package/dist/config/index.js.map +1 -1
  81. package/dist/config/loader.d.ts +34 -27
  82. package/dist/config/loader.d.ts.map +1 -1
  83. package/dist/config/loader.js +107 -92
  84. package/dist/config/loader.js.map +1 -1
  85. package/dist/config/validators.d.ts +34 -8
  86. package/dist/config/validators.d.ts.map +1 -1
  87. package/dist/config/validators.js +59 -21
  88. package/dist/config/validators.js.map +1 -1
  89. package/dist/core/asset-resolver.d.ts +8 -15
  90. package/dist/core/asset-resolver.d.ts.map +1 -1
  91. package/dist/core/asset-resolver.js +30 -37
  92. package/dist/core/asset-resolver.js.map +1 -1
  93. package/dist/core/build-cache.d.ts +23 -0
  94. package/dist/core/build-cache.d.ts.map +1 -0
  95. package/dist/core/build-cache.js +43 -0
  96. package/dist/core/build-cache.js.map +1 -0
  97. package/dist/core/cache-utils.d.ts +27 -0
  98. package/dist/core/cache-utils.d.ts.map +1 -0
  99. package/dist/core/cache-utils.js +60 -0
  100. package/dist/core/cache-utils.js.map +1 -0
  101. package/dist/core/docker.d.ts.map +1 -1
  102. package/dist/core/docker.js +8 -25
  103. package/dist/core/docker.js.map +1 -1
  104. package/dist/core/index.d.ts +1 -0
  105. package/dist/core/index.d.ts.map +1 -1
  106. package/dist/core/index.js +1 -0
  107. package/dist/core/index.js.map +1 -1
  108. package/dist/core/local-packages.d.ts +19 -0
  109. package/dist/core/local-packages.d.ts.map +1 -0
  110. package/dist/core/local-packages.js +60 -0
  111. package/dist/core/local-packages.js.map +1 -0
  112. package/dist/examples/.npm-cache/content-v2/sha512/0d/2d/7581c288670eaf8538ddd9df145b78756ce3be0791c6e0b9cd33429b3bae894525b9bda287a3cedffbcdd2c7b3107bafc03f2b0367eea489eee1cc042abb +1 -0
  113. package/dist/examples/.npm-cache/content-v2/sha512/12/20/bc4f5acca143809f7e07da1fdafb38137d93243de4d5b403e6e10b92d0d3a6e51eab24fe9dbc9d3ed1cd72e8f7a406085e99c422bb2c7d1166cf9f1f564e +0 -0
  114. package/dist/examples/.npm-cache/content-v2/sha512/22/ee/fb2695b01871c1d36946bdcfb49f1b520a57200d0a0b221b1e7d5f047ab38a8b2ab0e5f0e25a00acde1f3f2f9d24430a18f1092d438bc1a9e9891cc45f75 +0 -0
  115. package/dist/examples/.npm-cache/content-v2/sha512/24/89/da1ce6a61bca6de7e132f241a675c01c83738bf6b78af25b5cce01d3030361332b3fe938571e2b721f1555da9ddf930fdcf8c02f0471556071590e68cc09 +0 -0
  116. package/dist/examples/.npm-cache/content-v2/sha512/47/fd/c6be997da99228c3e279b95d4a46d6913947078a178f54ac71795a159f3513b1483232f4c2d0a1f403178bf9f96bb19615de32a9e2133e949880c6bc15e2 +0 -0
  117. package/dist/examples/.npm-cache/content-v2/sha512/4b/1c/c1cb7f8b32102071a89fef97158daa32080ebaedfbbd596880d2213d84e305abc76d2a95a412ded55c1c3d487adcb1ceff87fc2c85d7e2856ebd9d3f16f3 +0 -0
  118. package/dist/examples/.npm-cache/content-v2/sha512/6e/53/ff864769671f44f39d8a3bf904cd646535b745cc4824a8bb3189193b474678049f43b5178ba15cad7f0289046105e70f1565afc84e907120b35a466690fd +1 -0
  119. package/dist/examples/.npm-cache/content-v2/sha512/70/4c/4c8837d446965c5551b4ea527e95fa011744fb727581d82cf35bb5599ea0b57d18baa490f7af93ef9a16e8e45e5c0802737da20575f4056a4a5c9a3cd288 +0 -0
  120. package/dist/examples/.npm-cache/content-v2/sha512/96/ad/05de3bbb12d7de8ea353f962bdaea7d2eb44f707f2973462a6635daf537c67b46cca7764fed7d464fe62152c3f783a07aba1ceb35e09ad446bff05a4b466 +1 -0
  121. package/dist/examples/.npm-cache/content-v2/sha512/b5/20/52dde94e6cef7170f6089c64a4843e57be18be450d956f4e455905aed047ae6a368451c93035e6ac3ee59576b600f03f815afba0836b3a16e10a9aaca4ba +1 -0
  122. package/dist/examples/.npm-cache/content-v2/sha512/c7/a9/d166a1c39f97df312c59261319ba1cf9aac178bda0a0cb697d5ddd78bd8dd38ef1bf40017bcc8633c2049896c2d70696d9bff9280851f270792ff38bb3a0 +1 -0
  123. package/dist/examples/.npm-cache/content-v2/sha512/e0/d0/8c14083b633e6adbd3c6a93da5fc0f6bbd456c5512ef276920bedd8d85d551052adff992de977aff326616a211aaa2d6ddcc801149e9b7f914f566359b6a +1 -0
  124. package/dist/examples/.npm-cache/content-v2/sha512/e7/c5/06ad3fd79ac4f1031fe0b16ea5e54e232ca397bbcd7592c679021cbfb027276099f8c848f3f7a7691f0102ad53aa64f9141e61d729b037a678bd60440d17 +1 -0
  125. package/dist/examples/.npm-cache/content-v2/sha512/f3/28/d5d32329604ed7d471a4949105daa2cc98858cf24f45b0b97c41d0eb0d5a9fe7bf1f69c792161cc6693e4fc1b52e886ac41875ebfb8fe47fafe417ca3e6e +0 -0
  126. package/dist/examples/.npm-cache/index-v5/04/5a/2b5d7a7c407d85d746baa0f5c9388a333e35a717a8a0a81943daa6cb1364 +3 -0
  127. package/dist/examples/.npm-cache/index-v5/12/9a/eba560cbace295d8ee04cf283015377bd77b379e70968fb6bc407c7fc410 +15 -0
  128. package/dist/examples/.npm-cache/index-v5/2f/a2/7b047564b0ee21ac835ec609e89153dd6549be554d098584d5bfd19fe043 +15 -0
  129. package/dist/examples/.npm-cache/index-v5/32/8e/322d58dd8d1e000be248ada51385bf96288e56039de9feec1a4c6a467653 +3 -0
  130. package/dist/examples/.npm-cache/index-v5/57/93/d1d7cd1402e3e26468db03f2870822bb2c9018a506cdfb3b405f38cd3e1c +3 -0
  131. package/dist/examples/.npm-cache/index-v5/5d/f8/0a1f4fa7149e4ff33e09eb6aea41ac8d1730c868a5d3ace91f762698acff +3 -0
  132. package/dist/examples/.npm-cache/index-v5/69/a4/a92c72d838259b051cdf8e0acfb2bc680b6d4cfc642314a7836c3f7b2c50 +15 -0
  133. package/dist/examples/.npm-cache/index-v5/71/31/6da3423bb203f3de5eb16c942431073f89be2cfcb40058ec91dcb5ce0abc +15 -0
  134. package/dist/examples/.npm-cache/index-v5/7b/94/72b6bffa050d9ef52a558dd220663695bc606f756be0dfa196ef4f3913ba +3 -0
  135. package/dist/examples/.npm-cache/index-v5/85/9e/99e97fdd562517e56285337db91d1a8f2f416b8d631cf4d7d754fa671299 +15 -0
  136. package/dist/examples/.npm-cache/index-v5/92/4c/9416ada81a9b3c679539fd1ab53f8de3d41ff268f35eba7a194389a85b06 +3 -0
  137. package/dist/examples/.npm-cache/index-v5/c1/5a/13df76b218deed8a6ef12961116af5183db98c53fad1b922fd9edc075247 +3 -0
  138. package/dist/examples/.npm-cache/index-v5/cb/11/253c55410a8ab7c4a9ea9d6e1bf8ef1450a581da64c478074dfd82c8bff6 +3 -0
  139. package/dist/examples/.npm-cache/index-v5/d5/ae/b57fad3a62b5ba2dbdf24b042a9e7b70820f3db00e5a630f02e1fea020dc +3 -0
  140. package/dist/examples/.npm-cache/index-v5/d6/32/2f620f83c7d14451de98de8298c2408e05a16cc0829bd16c891ac19d7a67 +3 -0
  141. package/dist/examples/.npm-cache/index-v5/dd/b5/01dc7a3cd8b6a03a69aee9af500d51ae19cb0aa12631a4aafd152148b8e5 +15 -0
  142. package/dist/examples/.npm-cache/index-v5/e0/cf/6b862c15d74630d3871cd813d305210ab741311deb10baf8813014e0bc30 +3 -0
  143. package/dist/examples/.npm-cache/index-v5/e2/be/e880ccd35950a814d3c1dded34d3938ac61b15a195321dc51357f801aad4 +15 -0
  144. package/dist/examples/.npm-cache/index-v5/e5/1f/f4affe0b392cd03288f23cc03abcb274ff11a2c8f8965299de681914abb2 +3 -0
  145. package/dist/examples/.npm-cache/index-v5/f3/5b/9ebe450958ff0d7cc44ab0a00080cb8a3ff1389744b5eab5f97b68a6a6af +3 -0
  146. package/dist/examples/.npm-cache/index-v5/fb/c1/0de405e902866d53e7c30cf36a97dc2578838622b261816f44dc377c9a80 +3 -0
  147. package/dist/examples/README.md +343 -0
  148. package/dist/examples/event.json +53 -0
  149. package/dist/examples/flow-order-complete.json +68 -0
  150. package/dist/examples/flow-simple.json +32 -0
  151. package/dist/examples/flow.json +82 -0
  152. package/dist/examples/server-collect.json +60 -0
  153. package/dist/examples/server-collect.mjs +13540 -0
  154. package/dist/examples/test.html +43 -0
  155. package/dist/examples/web-serve.js +25503 -0
  156. package/dist/examples/web-serve.json +74 -0
  157. package/dist/index.d.ts +84 -201
  158. package/dist/index.d.ts.map +1 -1
  159. package/dist/index.js +675 -422
  160. package/dist/index.js.map +1 -1
  161. package/dist/schemas/index.d.ts +9 -0
  162. package/dist/schemas/index.d.ts.map +1 -0
  163. package/dist/schemas/index.js +9 -0
  164. package/dist/schemas/index.js.map +1 -0
  165. package/dist/schemas/primitives.d.ts +37 -0
  166. package/dist/schemas/primitives.d.ts.map +1 -0
  167. package/dist/schemas/primitives.js +43 -0
  168. package/dist/schemas/primitives.js.map +1 -0
  169. package/dist/schemas/run.d.ts +23 -0
  170. package/dist/schemas/run.d.ts.map +1 -0
  171. package/dist/schemas/run.js +20 -0
  172. package/dist/schemas/run.js.map +1 -0
  173. package/dist/templates/server.hbs +29 -0
  174. package/dist/templates/web.hbs +45 -0
  175. package/dist/types/bundle.d.ts +68 -190
  176. package/dist/types/bundle.d.ts.map +1 -1
  177. package/dist/types/bundle.js +2 -2
  178. package/dist/walker.js +1 -0
  179. package/examples/README.md +42 -29
  180. package/examples/flow-order-complete.json +57 -57
  181. package/examples/flow-simple.json +25 -25
  182. package/examples/flow.json +69 -69
  183. package/examples/server-collect.json +51 -44
  184. package/examples/server-collect.mjs +1 -1
  185. package/examples/web-serve.json +62 -63
  186. package/package.json +2 -2
  187. package/dist/config/defaults.d.ts +0 -33
  188. package/dist/config/defaults.d.ts.map +0 -1
  189. package/dist/config/defaults.js +0 -69
  190. package/dist/config/defaults.js.map +0 -1
  191. package/dist/config/parser.d.ts +0 -128
  192. package/dist/config/parser.d.ts.map +0 -1
  193. package/dist/config/parser.js +0 -256
  194. package/dist/config/parser.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @walkeros/cli
2
2
 
3
+ ## 0.4.2
4
+
5
+ ### Patch Changes
6
+
7
+ - simulate server and local packages
8
+ - cli cache
9
+ - Updated dependencies
10
+ - Updated dependencies
11
+ - Updated dependencies
12
+ - @walkeros/core@0.4.2
13
+ - @walkeros/docker@0.2.2
14
+ - @walkeros/server-core@0.4.2
15
+
3
16
  ## 0.4.1
4
17
 
5
18
  ### Patch Changes
package/README.md CHANGED
@@ -43,8 +43,8 @@ walkeros bundle https://example.com/config.json # Remote URL
43
43
 
44
44
  **Options:**
45
45
 
46
- - `-e, --env <name>` - Build specific environment (multi-env configs)
47
- - `--all` - Build all environments
46
+ - `-f, --flow <name>` - Build specific flow (multi-flow configs)
47
+ - `--all` - Build all flows
48
48
  - `-s, --stats` - Show bundle statistics
49
49
  - `--json` - Output stats as JSON
50
50
  - `--no-cache` - Disable package caching
@@ -58,7 +58,8 @@ walkeros bundle https://example.com/config.json # Remote URL
58
58
  walkeros bundle examples/server-collect.json --stats
59
59
  ```
60
60
 
61
- The output path is specified in the config's `build.output` field.
61
+ The output path uses convention-based defaults: `./dist/bundle.mjs` for server,
62
+ `./dist/walker.js` for web.
62
63
 
63
64
  ### simulate
64
65
 
@@ -128,61 +129,130 @@ walkeros run serve flow.json --port 8080 --static-dir ./dist
128
129
  3. Runs in current Node.js process (no containers)
129
130
  4. Press Ctrl+C for graceful shutdown
130
131
 
132
+ ## Caching
133
+
134
+ The CLI implements intelligent caching for faster builds:
135
+
136
+ ### Package Cache
137
+
138
+ - NPM packages are cached in `.tmp/cache/packages/`
139
+ - Mutable versions (`latest`, `^`, `~`) are re-checked daily
140
+ - Exact versions (`0.4.1`) are cached indefinitely
141
+
142
+ ### Build Cache
143
+
144
+ - Compiled bundles are cached in `.tmp/cache/builds/`
145
+ - Cache key based on flow.json content + current date
146
+ - Identical configs reuse cached build within the same day
147
+
148
+ ### Cache Management
149
+
150
+ ```bash
151
+ # View cache info
152
+ walkeros cache info
153
+
154
+ # Clear all caches
155
+ walkeros cache clear
156
+
157
+ # Clear only package cache
158
+ walkeros cache clear --packages
159
+
160
+ # Clear only build cache
161
+ walkeros cache clear --builds
162
+
163
+ # Disable caching for a single build
164
+ walkeros bundle flow.json --no-cache
165
+ ```
166
+
131
167
  ## Flow Configuration
132
168
 
133
- Minimal example:
169
+ Flow configs use the `Flow.Setup` format with `version` and `flows`:
134
170
 
135
171
  ```json
136
172
  {
137
- "flow": {
138
- "platform": "server",
139
- "sources": {
140
- "http": {
141
- "code": "sourceExpress",
142
- "config": {
143
- "settings": {
144
- "path": "/collect",
145
- "port": 8080
173
+ "version": 1,
174
+ "flows": {
175
+ "default": {
176
+ "server": {},
177
+ "packages": {
178
+ "@walkeros/collector": { "imports": ["startFlow"] },
179
+ "@walkeros/server-source-express": { "imports": ["sourceExpress"] },
180
+ "@walkeros/destination-demo": { "imports": ["destinationDemo"] }
181
+ },
182
+ "sources": {
183
+ "http": {
184
+ "code": "sourceExpress",
185
+ "config": {
186
+ "settings": { "path": "/collect", "port": 8080 }
146
187
  }
147
188
  }
148
- }
149
- },
150
- "destinations": {
151
- "demo": {
152
- "code": "destinationDemo",
153
- "config": {
154
- "settings": {
155
- "name": "Demo"
189
+ },
190
+ "destinations": {
191
+ "demo": {
192
+ "code": "destinationDemo",
193
+ "config": {
194
+ "settings": { "name": "Demo" }
156
195
  }
157
196
  }
158
- }
197
+ },
198
+ "collector": { "run": true }
199
+ }
200
+ }
201
+ }
202
+ ```
203
+
204
+ Platform is determined by the `web: {}` or `server: {}` key presence.
205
+
206
+ ### Local Packages
207
+
208
+ Use local packages instead of npm for development or testing unpublished
209
+ packages:
210
+
211
+ ```json
212
+ {
213
+ "packages": {
214
+ "@walkeros/collector": {
215
+ "path": "../packages/collector",
216
+ "imports": ["startFlow"]
159
217
  },
160
- "collector": {
161
- "run": true
218
+ "@my/custom-destination": {
219
+ "path": "./my-destination",
220
+ "imports": ["myDestination"]
162
221
  }
163
- },
164
- "build": {
165
- "packages": {
166
- "@walkeros/collector": {
167
- "version": "latest",
168
- "imports": ["startFlow"]
169
- },
170
- "@walkeros/server-source-express": {
171
- "version": "latest",
172
- "imports": ["sourceExpress"]
173
- },
174
- "@walkeros/destination-demo": {
175
- "version": "latest",
176
- "imports": ["destinationDemo"]
177
- }
222
+ }
223
+ }
224
+ ```
225
+
226
+ **Resolution rules:**
227
+
228
+ - `path` takes precedence over `version`
229
+ - Relative paths are resolved from the config file's directory
230
+ - If `dist/` folder exists, it's used; otherwise package root is used
231
+
232
+ **Dependency resolution:**
233
+
234
+ When a local package has dependencies on other packages that are also specified
235
+ with local paths, the CLI will use the local versions for those dependencies
236
+ too. This prevents npm versions from overwriting your local packages.
237
+
238
+ ```json
239
+ {
240
+ "packages": {
241
+ "@walkeros/core": {
242
+ "path": "../packages/core",
243
+ "imports": []
178
244
  },
179
- "code": "// Custom code here\n",
180
- "output": "bundle.mjs",
181
- "template": "./templates/base.hbs"
245
+ "@walkeros/collector": {
246
+ "path": "../packages/collector",
247
+ "imports": ["startFlow"]
248
+ }
182
249
  }
183
250
  }
184
251
  ```
185
252
 
253
+ In this example, even though `@walkeros/collector` depends on `@walkeros/core`,
254
+ the local version of core will be used (not downloaded from npm).
255
+
186
256
  See [examples/](./examples/) for complete working configurations.
187
257
 
188
258
  ## Programmatic API
@@ -1,16 +1,50 @@
1
1
  import fs from 'fs-extra';
2
2
  import path from 'path';
3
3
  import { bundleCore as bundle } from '../../commands/bundle/bundler.js';
4
- import { parseBundleConfig } from '../../config/index.js';
4
+ import { loadBundleConfig } from '../../config/index.js';
5
5
  import { createLogger } from '../../core/index.js';
6
6
  import { getId } from '@walkeros/core';
7
7
  // No mocks - test with real package downloads and bundling
8
+ /**
9
+ * Helper to create a Flow.Setup config for testing.
10
+ */
11
+ function createFlowSetup(platform, packages) {
12
+ return {
13
+ version: 1,
14
+ flows: {
15
+ default: {
16
+ ...(platform === 'web' ? { web: {} } : { server: {} }),
17
+ packages,
18
+ },
19
+ },
20
+ };
21
+ }
22
+ /**
23
+ * Helper to create build options for testing.
24
+ * Uses minimal defaults with test-specific overrides.
25
+ */
26
+ function createBuildOptions(overrides) {
27
+ return {
28
+ format: 'esm',
29
+ platform: 'browser',
30
+ target: 'es2020',
31
+ minify: false,
32
+ sourcemap: false,
33
+ cache: true,
34
+ tempDir: '.tmp',
35
+ packages: {},
36
+ code: '',
37
+ ...overrides,
38
+ };
39
+ }
8
40
  describe('Bundler', () => {
9
41
  const testOutputDir = path.resolve('.tmp', `bundler-${Date.now()}-${getId()}`);
10
42
  let logger;
11
43
  beforeEach(async () => {
12
44
  // Ensure test output directory exists
13
45
  await fs.ensureDir(testOutputDir);
46
+ // Clean build cache to ensure each test starts fresh
47
+ await fs.remove(path.join('.tmp', 'cache', 'builds'));
14
48
  // Create a silent logger for tests
15
49
  logger = createLogger({ silent: true });
16
50
  // Mock console.log to suppress output during tests
@@ -32,96 +66,82 @@ describe('Bundler', () => {
32
66
  jest.restoreAllMocks();
33
67
  });
34
68
  it('should bundle minimal config successfully', async () => {
35
- // Inline minimal configuration to avoid path dependencies
36
- const rawConfig = {
37
- flow: {
38
- platform: 'web',
39
- },
40
- build: {
41
- packages: {
42
- '@walkeros/core': {
43
- imports: ['getId'],
44
- },
69
+ const flowConfig = {
70
+ web: {},
71
+ packages: {
72
+ '@walkeros/core': {
73
+ imports: ['getId'],
45
74
  },
46
- code: 'export const test = getId(8);',
47
- template: '', // Explicitly disable template for raw code bundling
48
- platform: 'browser',
49
- format: 'esm',
50
- output: path.join(testOutputDir, 'minimal.js'),
51
75
  },
52
76
  };
53
- const { flowConfig, buildOptions } = parseBundleConfig(rawConfig);
54
- // Run bundler with real dependencies
77
+ const buildOptions = createBuildOptions({
78
+ packages: flowConfig.packages || {},
79
+ code: 'export const test = getId(8);',
80
+ template: '',
81
+ platform: 'browser',
82
+ format: 'esm',
83
+ output: path.join(testOutputDir, 'minimal.js'),
84
+ });
55
85
  await expect(bundle(flowConfig, buildOptions, logger)).resolves.not.toThrow();
56
86
  });
57
87
  it('should bundle server config with ESM format', async () => {
58
- // Inline server configuration
59
- const rawConfig = {
60
- flow: {
61
- platform: 'server',
62
- },
63
- build: {
64
- packages: {
65
- '@walkeros/core': {
66
- imports: ['trim', 'isString'],
67
- },
88
+ const flowConfig = {
89
+ server: {},
90
+ packages: {
91
+ '@walkeros/core': {
92
+ imports: ['trim', 'isString'],
68
93
  },
69
- code: 'export default { processText: (text) => trim(text) };',
70
- template: '', // Explicitly disable template for raw code bundling
71
- platform: 'node',
72
- format: 'esm',
73
- output: path.join(testOutputDir, 'server-bundle.mjs'),
74
94
  },
75
95
  };
76
- const { flowConfig, buildOptions } = parseBundleConfig(rawConfig);
77
- // Run bundler with real dependencies
96
+ const buildOptions = createBuildOptions({
97
+ packages: flowConfig.packages || {},
98
+ code: 'export default { processText: (text) => trim(text) };',
99
+ template: '',
100
+ platform: 'node',
101
+ format: 'esm',
102
+ output: path.join(testOutputDir, 'server-bundle.mjs'),
103
+ });
78
104
  await expect(bundle(flowConfig, buildOptions, logger)).resolves.not.toThrow();
79
105
  });
80
106
  it('should bundle advanced config with minification', async () => {
81
- // Inline advanced configuration
82
- const rawConfig = {
83
- flow: {
84
- platform: 'web',
85
- },
86
- build: {
87
- packages: {
88
- '@walkeros/core': {
89
- imports: ['getId', 'getByPath', 'clone', 'trim', 'isObject'],
90
- },
107
+ const flowConfig = {
108
+ web: {},
109
+ packages: {
110
+ '@walkeros/core': {
111
+ imports: ['getId', 'getByPath', 'clone', 'trim', 'isObject'],
91
112
  },
92
- code: "export function processData(data) {\n return data.map(item => ({\n ...item,\n id: getId(8),\n timestamp: new Date().toISOString().split('T')[0],\n processed: true\n }));\n}\n\nexport function extractNestedValues(data, path) {\n return data.map(item => getByPath(item, path, null)).filter(val => val !== null);\n}\n\nexport function deepCloneData(data) {\n return clone(data);\n}\n\nexport function cleanStringData(data) {\n return data.map(item => ({\n ...item,\n name: typeof item.name === 'string' ? trim(item.name) : item.name\n }));\n}\n\n// Re-export walkerOS utilities\nexport { getId, getByPath, clone, trim, isObject };",
93
- template: '', // Explicitly disable template for raw code bundling
94
- platform: 'browser',
95
- format: 'esm',
96
- target: 'es2020',
97
- minify: true,
98
- sourcemap: true,
99
- output: path.join(testOutputDir, 'advanced-bundle.js'),
100
113
  },
101
114
  };
102
- const { flowConfig, buildOptions } = parseBundleConfig(rawConfig);
103
- // Run bundler with real dependencies
115
+ const buildOptions = createBuildOptions({
116
+ packages: flowConfig.packages || {},
117
+ code: "export function processData(data) {\n return data.map(item => ({\n ...item,\n id: getId(8),\n timestamp: new Date().toISOString().split('T')[0],\n processed: true\n }));\n}\n\nexport function extractNestedValues(data, path) {\n return data.map(item => getByPath(item, path, null)).filter(val => val !== null);\n}\n\nexport function deepCloneData(data) {\n return clone(data);\n}\n\nexport function cleanStringData(data) {\n return data.map(item => ({\n ...item,\n name: typeof item.name === 'string' ? trim(item.name) : item.name\n }));\n}\n\n// Re-export walkerOS utilities\nexport { getId, getByPath, clone, trim, isObject };",
118
+ template: '',
119
+ platform: 'browser',
120
+ format: 'esm',
121
+ target: 'es2020',
122
+ minify: true,
123
+ sourcemap: true,
124
+ output: path.join(testOutputDir, 'advanced-bundle.js'),
125
+ });
104
126
  await expect(bundle(flowConfig, buildOptions, logger)).resolves.not.toThrow();
105
127
  });
106
128
  describe('Stats Collection', () => {
107
129
  it('should collect bundle stats when requested', async () => {
108
- const rawConfig = {
109
- flow: {
110
- platform: 'web',
111
- },
112
- build: {
113
- packages: {
114
- '@walkeros/core': {
115
- imports: ['getId'],
116
- },
130
+ const flowConfig = {
131
+ web: {},
132
+ packages: {
133
+ '@walkeros/core': {
134
+ imports: ['getId'],
117
135
  },
118
- code: 'export const test = getId(8);',
119
- template: '', // Explicitly disable template for raw code bundling
120
- format: 'esm',
121
- output: path.join(testOutputDir, 'stats-test.js'),
122
136
  },
123
137
  };
124
- const { flowConfig, buildOptions } = parseBundleConfig(rawConfig);
138
+ const buildOptions = createBuildOptions({
139
+ packages: flowConfig.packages || {},
140
+ code: 'export const test = getId(8);',
141
+ template: '',
142
+ format: 'esm',
143
+ output: path.join(testOutputDir, 'stats-test.js'),
144
+ });
125
145
  const stats = await bundle(flowConfig, buildOptions, logger, true);
126
146
  expect(stats).toBeDefined();
127
147
  expect(stats.totalSize).toBe(1024); // From mocked fs.stat
@@ -131,39 +151,36 @@ describe('Bundler', () => {
131
151
  expect(stats.packages[0].name).toBe('@walkeros/core@latest');
132
152
  });
133
153
  it('should detect ineffective tree-shaking with wildcard imports', async () => {
134
- const { flowConfig, buildOptions } = parseBundleConfig({
135
- flow: {
136
- platform: 'web',
137
- },
138
- build: {
139
- packages: { '@walkeros/core': {} },
140
- code: 'import * as walkerCore from "@walkeros/core";\nexport const test = walkerCore.getId;',
141
- template: '', // Explicitly disable template for raw code bundling
142
- format: 'esm',
143
- output: path.join(testOutputDir, 'test.js'),
144
- },
154
+ const flowConfig = {
155
+ web: {},
156
+ packages: { '@walkeros/core': {} },
157
+ };
158
+ const buildOptions = createBuildOptions({
159
+ packages: flowConfig.packages || {},
160
+ code: 'import * as walkerCore from "@walkeros/core";\nexport const test = walkerCore.getId;',
161
+ template: '',
162
+ format: 'esm',
163
+ output: path.join(testOutputDir, 'test.js'),
145
164
  });
146
165
  const stats = await bundle(flowConfig, buildOptions, logger, true);
147
166
  expect(stats.treeshakingEffective).toBe(false);
148
167
  });
149
168
  it('should return undefined when stats not requested', async () => {
150
- const rawConfig = {
151
- flow: {
152
- platform: 'web',
153
- },
154
- build: {
155
- packages: {
156
- '@walkeros/core': {
157
- imports: ['getId'],
158
- },
169
+ const flowConfig = {
170
+ web: {},
171
+ packages: {
172
+ '@walkeros/core': {
173
+ imports: ['getId'],
159
174
  },
160
- code: 'export const test = getId(8);',
161
- template: '', // Explicitly disable template for raw code bundling
162
- format: 'esm',
163
- output: path.join(testOutputDir, 'no-stats.js'),
164
175
  },
165
176
  };
166
- const { flowConfig, buildOptions } = parseBundleConfig(rawConfig);
177
+ const buildOptions = createBuildOptions({
178
+ packages: flowConfig.packages || {},
179
+ code: 'export const test = getId(8);',
180
+ template: '',
181
+ format: 'esm',
182
+ output: path.join(testOutputDir, 'no-stats.js'),
183
+ });
167
184
  const result = await bundle(flowConfig, buildOptions, logger, false);
168
185
  expect(result).toBeUndefined();
169
186
  });
@@ -173,110 +190,103 @@ describe('Bundler', () => {
173
190
  // Create a test template file
174
191
  const templatePath = path.join(testOutputDir, 'test.hbs');
175
192
  await fs.writeFile(templatePath, '{{{CODE}}}\n// Template footer');
176
- const { flowConfig, buildOptions } = parseBundleConfig({
177
- flow: {
178
- platform: 'web',
179
- },
180
- build: {
181
- packages: {
182
- '@walkeros/core': { imports: ['getId'] },
183
- },
184
- code: 'export const generateId = () => getId(8);',
185
- template: templatePath,
186
- output: path.join(testOutputDir, 'template-test.js'),
193
+ const flowConfig = {
194
+ web: {},
195
+ packages: {
196
+ '@walkeros/core': { imports: ['getId'] },
187
197
  },
198
+ };
199
+ const buildOptions = createBuildOptions({
200
+ packages: flowConfig.packages || {},
201
+ code: 'export const generateId = () => getId(8);',
202
+ template: templatePath,
203
+ output: path.join(testOutputDir, 'template-test.js'),
188
204
  });
189
205
  await expect(bundle(flowConfig, buildOptions, logger)).resolves.not.toThrow();
190
206
  });
191
207
  it('should handle missing template variables gracefully', async () => {
192
- const { flowConfig, buildOptions } = parseBundleConfig({
193
- flow: {
194
- platform: 'web',
195
- },
196
- build: {
197
- packages: {
198
- '@walkeros/core': { imports: ['trim'] },
199
- },
200
- code: 'export const test = trim("hello");',
201
- template: '', // Explicitly disable template for raw code bundling
202
- format: 'esm',
203
- output: path.join(testOutputDir, 'missing-vars.js'),
208
+ const flowConfig = {
209
+ web: {},
210
+ packages: {
211
+ '@walkeros/core': { imports: ['trim'] },
204
212
  },
213
+ };
214
+ const buildOptions = createBuildOptions({
215
+ packages: flowConfig.packages || {},
216
+ code: 'export const test = trim("hello");',
217
+ template: '',
218
+ format: 'esm',
219
+ output: path.join(testOutputDir, 'missing-vars.js'),
205
220
  });
206
221
  await expect(bundle(flowConfig, buildOptions, logger)).resolves.not.toThrow();
207
222
  });
208
223
  it('should append bundle code when placeholder not found', async () => {
209
- const { flowConfig, buildOptions } = parseBundleConfig({
210
- flow: {
211
- platform: 'web',
212
- },
213
- build: {
214
- packages: {
215
- '@walkeros/core': { imports: ['getId'] },
216
- },
217
- code: 'export const test = getId(6);',
218
- template: '', // Explicitly disable template for raw code bundling
219
- format: 'esm',
220
- output: path.join(testOutputDir, 'append-test.js'),
224
+ const flowConfig = {
225
+ web: {},
226
+ packages: {
227
+ '@walkeros/core': { imports: ['getId'] },
221
228
  },
229
+ };
230
+ const buildOptions = createBuildOptions({
231
+ packages: flowConfig.packages || {},
232
+ code: 'export const test = getId(6);',
233
+ template: '',
234
+ format: 'esm',
235
+ output: path.join(testOutputDir, 'append-test.js'),
222
236
  });
223
237
  await expect(bundle(flowConfig, buildOptions, logger)).resolves.not.toThrow();
224
238
  });
225
239
  });
226
240
  describe('Configuration Scenarios', () => {
227
241
  it('should handle custom temp directory configuration', async () => {
228
- const { flowConfig, buildOptions } = parseBundleConfig({
229
- flow: {
230
- platform: 'web',
231
- },
232
- build: {
233
- packages: {
234
- '@walkeros/core': { imports: ['getId'] },
235
- },
236
- code: 'export const test = getId();',
237
- template: '', // Explicitly disable template for raw code bundling
238
- format: 'esm',
239
- tempDir: '/tmp/my-custom-bundler-temp',
240
- output: path.join(testOutputDir, 'custom-temp-example.js'),
242
+ const flowConfig = {
243
+ web: {},
244
+ packages: {
245
+ '@walkeros/core': { imports: ['getId'] },
241
246
  },
247
+ };
248
+ const buildOptions = createBuildOptions({
249
+ packages: flowConfig.packages || {},
250
+ code: 'export const test = getId();',
251
+ template: '',
252
+ format: 'esm',
253
+ tempDir: '/tmp/my-custom-bundler-temp',
254
+ output: path.join(testOutputDir, 'custom-temp-example.js'),
242
255
  });
243
256
  await expect(bundle(flowConfig, buildOptions, logger)).resolves.not.toThrow();
244
257
  });
245
258
  it('should handle version pinning correctly', async () => {
246
- const { flowConfig, buildOptions } = parseBundleConfig({
247
- flow: {
248
- platform: 'web',
249
- },
250
- build: {
251
- packages: {
252
- '@walkeros/core': { version: '0.0.7', imports: ['getId'] },
253
- },
254
- code: '// Test version pinning\nexport const test = getId();',
255
- template: '', // Explicitly disable template for raw code bundling
256
- platform: 'browser',
257
- format: 'esm',
258
- target: 'es2020',
259
- output: path.join(testOutputDir, 'version-test.js'),
259
+ const flowConfig = {
260
+ web: {},
261
+ packages: {
262
+ '@walkeros/core': { version: '0.0.7', imports: ['getId'] },
260
263
  },
264
+ };
265
+ const buildOptions = createBuildOptions({
266
+ packages: flowConfig.packages || {},
267
+ code: '// Test version pinning\nexport const test = getId();',
268
+ template: '',
269
+ platform: 'browser',
270
+ format: 'esm',
271
+ target: 'es2020',
272
+ output: path.join(testOutputDir, 'version-test.js'),
261
273
  });
262
274
  await expect(bundle(flowConfig, buildOptions, logger)).resolves.not.toThrow();
263
275
  });
264
276
  });
265
277
  describe('Error Handling', () => {
266
- it('should validate configuration properly', async () => {
267
- // Test configuration validation instead of runtime errors
278
+ it('should reject invalid config structure', async () => {
279
+ // Test that loader rejects invalid config structure
268
280
  expect(() => {
269
- parseBundleConfig({
281
+ loadBundleConfig({
270
282
  flow: {
271
283
  platform: 'web',
272
284
  },
273
285
  build: {
274
- packages: 'invalid', // should be object
275
- code: 'test',
276
- output: path.join(testOutputDir, 'test.js'),
286
+ packages: {},
277
287
  },
278
- });
279
- }).toThrow();
288
+ }, { configPath: '/test/config.json' });
289
+ }).toThrow(/Invalid configuration/);
280
290
  });
281
291
  });
282
292
  });