@ecopages/core 0.2.0-alpha.5 → 0.2.0-alpha.7

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 (418) hide show
  1. package/README.md +213 -12
  2. package/package.json +100 -188
  3. package/src/adapters/README.md +39 -0
  4. package/src/adapters/bun/hmr-manager.test.ts +267 -0
  5. package/src/adapters/bun/hmr-manager.ts +180 -47
  6. package/src/adapters/bun/index.ts +1 -2
  7. package/src/adapters/bun/server-adapter.ts +41 -34
  8. package/src/adapters/bun/server-lifecycle.ts +40 -70
  9. package/src/adapters/index.ts +1 -1
  10. package/src/adapters/node/bootstrap-dependency-resolver.test.ts +282 -0
  11. package/src/adapters/node/bootstrap-dependency-resolver.ts +301 -0
  12. package/src/adapters/node/index.ts +7 -0
  13. package/src/adapters/node/node-client-bridge.test.ts +198 -0
  14. package/src/adapters/node/node-hmr-manager.test.ts +322 -0
  15. package/src/adapters/node/node-hmr-manager.ts +207 -97
  16. package/src/adapters/node/runtime-adapter.test.ts +868 -0
  17. package/src/adapters/node/runtime-adapter.ts +439 -0
  18. package/src/adapters/node/server-adapter.ts +31 -104
  19. package/src/adapters/node/static-content-server.test.ts +60 -0
  20. package/src/adapters/node/static-content-server.ts +36 -0
  21. package/src/adapters/node/write-runtime-manifest.ts +38 -0
  22. package/src/adapters/shared/api-response.test.ts +97 -0
  23. package/src/{define-api-handler.ts → adapters/shared/define-api-handler.ts} +1 -1
  24. package/src/adapters/shared/explicit-static-route-matcher.test.ts +381 -0
  25. package/src/adapters/shared/explicit-static-route-matcher.ts +7 -1
  26. package/src/adapters/shared/file-route-middleware-pipeline.test.ts +90 -0
  27. package/src/adapters/shared/file-route-middleware-pipeline.ts +6 -2
  28. package/src/adapters/shared/fs-server-response-factory.test.ts +187 -0
  29. package/src/adapters/shared/fs-server-response-matcher.test.ts +286 -0
  30. package/src/adapters/shared/fs-server-response-matcher.ts +17 -10
  31. package/src/adapters/shared/hmr-entrypoint-registrar.ts +149 -0
  32. package/src/adapters/shared/hmr-html-response.ts +52 -0
  33. package/src/adapters/shared/hmr-manager.contract.test.ts +196 -0
  34. package/src/adapters/shared/hmr-manager.dispatch.test.ts +220 -0
  35. package/src/adapters/shared/render-context.test.ts +146 -0
  36. package/src/adapters/shared/render-context.ts +21 -6
  37. package/src/adapters/shared/runtime-bootstrap.ts +79 -0
  38. package/src/adapters/shared/server-adapter.test.ts +77 -0
  39. package/src/adapters/shared/server-adapter.ts +51 -4
  40. package/src/adapters/shared/server-route-handler.test.ts +110 -0
  41. package/src/adapters/shared/server-route-handler.ts +5 -18
  42. package/src/adapters/shared/server-static-builder.test.ts +316 -0
  43. package/src/adapters/shared/server-static-builder.ts +92 -8
  44. package/src/build/README.md +101 -0
  45. package/src/build/build-adapter-serialization.test.ts +268 -0
  46. package/src/build/build-adapter.test.ts +815 -0
  47. package/src/build/build-adapter.ts +234 -6
  48. package/src/build/build-manifest.ts +54 -0
  49. package/src/build/dev-build-coordinator.ts +221 -0
  50. package/src/build/esbuild-build-adapter.ts +132 -84
  51. package/src/build/runtime-build-executor.ts +34 -0
  52. package/src/build/runtime-specifier-alias-plugin.test.ts +43 -0
  53. package/src/build/runtime-specifier-alias-plugin.ts +58 -0
  54. package/src/config/README.md +33 -0
  55. package/src/config/config-builder.test.ts +410 -0
  56. package/src/config/config-builder.ts +281 -49
  57. package/src/constants.ts +15 -0
  58. package/src/declarations.d.ts +18 -13
  59. package/src/eco/README.md +70 -16
  60. package/src/eco/component-render-context.ts +39 -17
  61. package/src/eco/eco.test.ts +678 -0
  62. package/src/eco/eco.ts +29 -8
  63. package/src/eco/eco.types.ts +20 -1
  64. package/src/eco/eco.utils.test.ts +124 -0
  65. package/src/eco/global-injector-map.test.ts +42 -0
  66. package/src/eco/lazy-injector-map.test.ts +66 -0
  67. package/src/eco/module-dependencies.test.ts +30 -0
  68. package/src/errors/http-error.test.ts +134 -0
  69. package/src/global/utils.test.ts +12 -0
  70. package/src/hmr/README.md +26 -0
  71. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-have-HMR-script-injected-in-page-1.png +0 -0
  72. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-load-fixture-app-page-1.png +0 -0
  73. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-WebSocket-Connection-should-connect-to-correct-HMR-endpoint-1.png +0 -0
  74. package/src/hmr/client/hmr-runtime.ts +38 -7
  75. package/src/hmr/hmr-strategy.test.ts +124 -0
  76. package/src/hmr/hmr.postcss.test.e2e.ts +41 -0
  77. package/src/hmr/hmr.test.e2e.ts +29 -38
  78. package/src/hmr/strategies/js-hmr-strategy.test.ts +335 -0
  79. package/src/hmr/strategies/js-hmr-strategy.ts +71 -78
  80. package/src/index.ts +1 -1
  81. package/src/integrations/ghtml/ghtml-renderer.test.ts +63 -0
  82. package/src/integrations/ghtml/ghtml-renderer.ts +4 -1
  83. package/src/internal-types.ts +39 -19
  84. package/src/plugins/README.md +34 -0
  85. package/src/plugins/alias-resolver-plugin.test.ts +41 -0
  86. package/src/plugins/alias-resolver-plugin.ts +21 -3
  87. package/src/plugins/eco-component-meta-plugin.test.ts +380 -0
  88. package/src/plugins/eco-component-meta-plugin.ts +10 -3
  89. package/src/plugins/integration-plugin.test.ts +111 -0
  90. package/src/plugins/integration-plugin.ts +45 -3
  91. package/src/plugins/processor.test.ts +148 -0
  92. package/src/plugins/processor.ts +22 -2
  93. package/src/plugins/runtime-capability.ts +14 -0
  94. package/src/public-types.ts +73 -11
  95. package/src/route-renderer/GRAPH.md +16 -20
  96. package/src/route-renderer/README.md +8 -21
  97. package/src/route-renderer/component-graph/component-graph-executor.test.ts +41 -0
  98. package/src/route-renderer/component-graph/component-graph.test.ts +63 -0
  99. package/src/route-renderer/component-graph/component-marker.test.ts +73 -0
  100. package/src/route-renderer/component-graph/component-reference.ts +29 -0
  101. package/src/route-renderer/component-graph/marker-graph-resolver.test.ts +135 -0
  102. package/src/route-renderer/{marker-graph-resolver.ts → component-graph/marker-graph-resolver.ts} +11 -9
  103. package/src/route-renderer/orchestration/integration-renderer.test.ts +936 -0
  104. package/src/route-renderer/{integration-renderer.ts → orchestration/integration-renderer.ts} +113 -19
  105. package/src/route-renderer/orchestration/render-execution.service.test.ts +97 -0
  106. package/src/route-renderer/{render-execution.service.ts → orchestration/render-execution.service.ts} +109 -37
  107. package/src/route-renderer/orchestration/render-preparation.service.test.ts +235 -0
  108. package/src/route-renderer/{render-preparation.service.ts → orchestration/render-preparation.service.ts} +127 -9
  109. package/src/route-renderer/page-loading/dependency-resolver.test.ts +345 -0
  110. package/src/route-renderer/{dependency-resolver.ts → page-loading/dependency-resolver.ts} +28 -12
  111. package/src/route-renderer/page-loading/page-module-loader.test.ts +96 -0
  112. package/src/route-renderer/{page-module-loader.ts → page-loading/page-module-loader.ts} +49 -21
  113. package/src/route-renderer/route-renderer.ts +36 -1
  114. package/src/router/README.md +26 -0
  115. package/src/router/client/link-intent.d.ts +53 -0
  116. package/src/router/client/link-intent.test.browser.ts +51 -0
  117. package/src/router/client/link-intent.ts +92 -0
  118. package/src/router/client/navigation-coordinator.test.ts +237 -0
  119. package/src/router/client/navigation-coordinator.ts +433 -0
  120. package/src/router/server/fs-router-scanner.test.ts +83 -0
  121. package/src/router/{fs-router-scanner.ts → server/fs-router-scanner.ts} +12 -10
  122. package/src/router/server/fs-router.test.ts +214 -0
  123. package/src/router/{fs-router.ts → server/fs-router.ts} +2 -2
  124. package/src/services/README.md +29 -0
  125. package/src/services/assets/asset-processing-service/asset-processing.service.test.ts +385 -0
  126. package/src/services/{asset-processing-service → assets/asset-processing-service}/asset-processing.service.ts +101 -6
  127. package/src/services/assets/asset-processing-service/asset.factory.test.ts +63 -0
  128. package/src/services/{asset-processing-service → assets/asset-processing-service}/asset.factory.ts +2 -2
  129. package/src/services/{asset-processing-service → assets/asset-processing-service}/assets.types.ts +2 -1
  130. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.test.ts +72 -0
  131. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.ts +95 -0
  132. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.test.ts +67 -0
  133. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.ts +78 -0
  134. package/src/services/{asset-processing-service → assets/asset-processing-service}/index.ts +2 -0
  135. package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.interface.ts +1 -1
  136. package/src/services/assets/asset-processing-service/processors/base/base-processor.test.ts +59 -0
  137. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-processor.ts +11 -5
  138. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-script-processor.ts +17 -27
  139. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.test.ts +286 -0
  140. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/file-script.processor.ts +3 -3
  141. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.test.ts +227 -0
  142. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/node-module-script.processor.ts +5 -4
  143. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.test.ts +199 -0
  144. package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/file-stylesheet.processor.ts +4 -1
  145. package/src/services/assets/browser-bundle.service.test.ts +36 -0
  146. package/src/services/assets/browser-bundle.service.ts +53 -0
  147. package/src/services/cache/index.ts +3 -3
  148. package/src/services/cache/memory-cache-store.test.ts +225 -0
  149. package/src/services/cache/memory-cache-store.ts +1 -1
  150. package/src/services/cache/page-cache-service.test.ts +175 -0
  151. package/src/services/cache/page-cache-service.ts +3 -3
  152. package/src/services/cache/page-request-cache-coordinator.service.test.ts +79 -0
  153. package/src/services/{page-request-cache-coordinator.service.ts → cache/page-request-cache-coordinator.service.ts} +9 -6
  154. package/src/services/html/html-rewriter-provider.service.test.ts +183 -0
  155. package/src/services/html/html-rewriter-provider.service.ts +103 -0
  156. package/src/services/html/html-transformer.service.test.ts +378 -0
  157. package/src/services/html/html-transformer.service.ts +279 -0
  158. package/src/services/invalidation/development-invalidation.service.test.ts +77 -0
  159. package/src/services/invalidation/development-invalidation.service.ts +261 -0
  160. package/src/services/module-loading/app-server-module-transpiler.service.ts +52 -0
  161. package/src/services/module-loading/page-module-import.service.test.ts +253 -0
  162. package/src/services/module-loading/page-module-import.service.ts +200 -0
  163. package/src/services/module-loading/server-loader.service.test.ts +161 -0
  164. package/src/services/module-loading/server-loader.service.ts +130 -0
  165. package/src/services/module-loading/server-module-transpiler.service.test.ts +115 -0
  166. package/src/services/module-loading/server-module-transpiler.service.ts +105 -0
  167. package/src/services/runtime-manifest/node-runtime-manifest.service.test.ts +95 -0
  168. package/src/services/runtime-manifest/node-runtime-manifest.service.ts +101 -0
  169. package/src/services/runtime-state/dev-graph.service.ts +217 -0
  170. package/src/services/runtime-state/entrypoint-dependency-graph.service.ts +136 -0
  171. package/src/services/runtime-state/runtime-specifier-registry.service.ts +96 -0
  172. package/src/services/runtime-state/server-invalidation-state.service.ts +68 -0
  173. package/src/services/validation/schema-validation-service.test.ts +223 -0
  174. package/src/services/{schema-validation-service.ts → validation/schema-validation-service.ts} +1 -1
  175. package/src/static-site-generator/README.md +26 -0
  176. package/src/static-site-generator/static-site-generator.test.ts +307 -0
  177. package/src/static-site-generator/static-site-generator.ts +109 -6
  178. package/src/utils/deep-merge.test.ts +114 -0
  179. package/src/utils/invariant.test.ts +22 -0
  180. package/src/utils/path-utils.test.ts +15 -0
  181. package/src/utils/resolve-work-dir.ts +45 -0
  182. package/src/utils/server-utils.test.ts +38 -0
  183. package/src/watchers/project-watcher.integration.test.ts +337 -0
  184. package/src/watchers/project-watcher.test-helpers.ts +1 -0
  185. package/src/watchers/project-watcher.test.ts +678 -0
  186. package/src/watchers/project-watcher.ts +49 -50
  187. package/CHANGELOG.md +0 -94
  188. package/src/adapters/abstract/application-adapter.d.ts +0 -168
  189. package/src/adapters/abstract/application-adapter.js +0 -109
  190. package/src/adapters/abstract/router-adapter.d.ts +0 -26
  191. package/src/adapters/abstract/router-adapter.js +0 -5
  192. package/src/adapters/abstract/server-adapter.d.ts +0 -69
  193. package/src/adapters/abstract/server-adapter.js +0 -15
  194. package/src/adapters/bun/client-bridge.d.ts +0 -34
  195. package/src/adapters/bun/client-bridge.js +0 -48
  196. package/src/adapters/bun/create-app.d.ts +0 -60
  197. package/src/adapters/bun/create-app.js +0 -117
  198. package/src/adapters/bun/define-api-handler.d.ts +0 -61
  199. package/src/adapters/bun/define-api-handler.js +0 -15
  200. package/src/adapters/bun/define-api-handler.ts +0 -114
  201. package/src/adapters/bun/hmr-manager.d.ts +0 -79
  202. package/src/adapters/bun/hmr-manager.js +0 -222
  203. package/src/adapters/bun/index.d.ts +0 -3
  204. package/src/adapters/bun/index.js +0 -8
  205. package/src/adapters/bun/server-adapter.d.ts +0 -155
  206. package/src/adapters/bun/server-adapter.js +0 -368
  207. package/src/adapters/bun/server-lifecycle.d.ts +0 -52
  208. package/src/adapters/bun/server-lifecycle.js +0 -120
  209. package/src/adapters/index.d.ts +0 -6
  210. package/src/adapters/index.js +0 -14
  211. package/src/adapters/node/create-app.d.ts +0 -21
  212. package/src/adapters/node/create-app.js +0 -143
  213. package/src/adapters/node/index.d.ts +0 -4
  214. package/src/adapters/node/index.js +0 -8
  215. package/src/adapters/node/node-client-bridge.d.ts +0 -26
  216. package/src/adapters/node/node-client-bridge.js +0 -66
  217. package/src/adapters/node/node-hmr-manager.d.ts +0 -62
  218. package/src/adapters/node/node-hmr-manager.js +0 -221
  219. package/src/adapters/node/server-adapter.d.ts +0 -190
  220. package/src/adapters/node/server-adapter.js +0 -420
  221. package/src/adapters/node/static-content-server.d.ts +0 -24
  222. package/src/adapters/node/static-content-server.js +0 -166
  223. package/src/adapters/shared/api-response.d.ts +0 -52
  224. package/src/adapters/shared/api-response.js +0 -96
  225. package/src/adapters/shared/application-adapter.d.ts +0 -18
  226. package/src/adapters/shared/application-adapter.js +0 -90
  227. package/src/adapters/shared/explicit-static-route-matcher.d.ts +0 -38
  228. package/src/adapters/shared/explicit-static-route-matcher.js +0 -100
  229. package/src/adapters/shared/file-route-middleware-pipeline.d.ts +0 -65
  230. package/src/adapters/shared/file-route-middleware-pipeline.js +0 -98
  231. package/src/adapters/shared/fs-server-response-factory.d.ts +0 -19
  232. package/src/adapters/shared/fs-server-response-factory.js +0 -97
  233. package/src/adapters/shared/fs-server-response-matcher.d.ts +0 -71
  234. package/src/adapters/shared/fs-server-response-matcher.js +0 -155
  235. package/src/adapters/shared/render-context.d.ts +0 -14
  236. package/src/adapters/shared/render-context.js +0 -69
  237. package/src/adapters/shared/server-adapter.d.ts +0 -87
  238. package/src/adapters/shared/server-adapter.js +0 -353
  239. package/src/adapters/shared/server-route-handler.d.ts +0 -89
  240. package/src/adapters/shared/server-route-handler.js +0 -120
  241. package/src/adapters/shared/server-static-builder.d.ts +0 -38
  242. package/src/adapters/shared/server-static-builder.js +0 -46
  243. package/src/build/build-adapter.d.ts +0 -75
  244. package/src/build/build-adapter.js +0 -54
  245. package/src/build/build-types.d.ts +0 -57
  246. package/src/build/build-types.js +0 -0
  247. package/src/build/esbuild-build-adapter.d.ts +0 -69
  248. package/src/build/esbuild-build-adapter.js +0 -391
  249. package/src/config/config-builder.d.ts +0 -227
  250. package/src/config/config-builder.js +0 -392
  251. package/src/constants.d.ts +0 -32
  252. package/src/constants.js +0 -21
  253. package/src/create-app.d.ts +0 -17
  254. package/src/create-app.js +0 -66
  255. package/src/define-api-handler.d.ts +0 -25
  256. package/src/define-api-handler.js +0 -15
  257. package/src/dev/sc-server.d.ts +0 -30
  258. package/src/dev/sc-server.js +0 -111
  259. package/src/eco/component-render-context.d.ts +0 -105
  260. package/src/eco/component-render-context.js +0 -77
  261. package/src/eco/eco.d.ts +0 -9
  262. package/src/eco/eco.js +0 -110
  263. package/src/eco/eco.types.d.ts +0 -170
  264. package/src/eco/eco.types.js +0 -0
  265. package/src/eco/eco.utils.d.ts +0 -40
  266. package/src/eco/eco.utils.js +0 -40
  267. package/src/eco/global-injector-map.d.ts +0 -16
  268. package/src/eco/global-injector-map.js +0 -80
  269. package/src/eco/lazy-injector-map.d.ts +0 -8
  270. package/src/eco/lazy-injector-map.js +0 -70
  271. package/src/eco/module-dependencies.d.ts +0 -18
  272. package/src/eco/module-dependencies.js +0 -49
  273. package/src/errors/http-error.d.ts +0 -31
  274. package/src/errors/http-error.js +0 -50
  275. package/src/errors/index.d.ts +0 -2
  276. package/src/errors/index.js +0 -4
  277. package/src/errors/locals-access-error.d.ts +0 -4
  278. package/src/errors/locals-access-error.js +0 -9
  279. package/src/global/app-logger.d.ts +0 -2
  280. package/src/global/app-logger.js +0 -6
  281. package/src/hmr/client/hmr-runtime.d.ts +0 -10
  282. package/src/hmr/client/hmr-runtime.js +0 -86
  283. package/src/hmr/hmr-strategy.d.ts +0 -159
  284. package/src/hmr/hmr-strategy.js +0 -29
  285. package/src/hmr/hmr.test.e2e.d.ts +0 -1
  286. package/src/hmr/hmr.test.e2e.js +0 -50
  287. package/src/hmr/strategies/default-hmr-strategy.d.ts +0 -43
  288. package/src/hmr/strategies/default-hmr-strategy.js +0 -34
  289. package/src/hmr/strategies/js-hmr-strategy.d.ts +0 -136
  290. package/src/hmr/strategies/js-hmr-strategy.js +0 -192
  291. package/src/index.browser.d.ts +0 -3
  292. package/src/index.browser.js +0 -4
  293. package/src/index.d.ts +0 -5
  294. package/src/index.js +0 -10
  295. package/src/integrations/ghtml/ghtml-renderer.d.ts +0 -15
  296. package/src/integrations/ghtml/ghtml-renderer.js +0 -60
  297. package/src/integrations/ghtml/ghtml.plugin.d.ts +0 -20
  298. package/src/integrations/ghtml/ghtml.plugin.js +0 -21
  299. package/src/internal-types.d.ts +0 -200
  300. package/src/internal-types.js +0 -0
  301. package/src/plugins/alias-resolver-plugin.d.ts +0 -2
  302. package/src/plugins/alias-resolver-plugin.js +0 -39
  303. package/src/plugins/eco-component-meta-plugin.d.ts +0 -95
  304. package/src/plugins/eco-component-meta-plugin.js +0 -157
  305. package/src/plugins/integration-plugin.d.ts +0 -102
  306. package/src/plugins/integration-plugin.js +0 -100
  307. package/src/plugins/processor.d.ts +0 -82
  308. package/src/plugins/processor.js +0 -122
  309. package/src/public-types.d.ts +0 -1094
  310. package/src/public-types.js +0 -0
  311. package/src/route-renderer/component-graph-executor.d.ts +0 -32
  312. package/src/route-renderer/component-graph-executor.js +0 -31
  313. package/src/route-renderer/component-graph.d.ts +0 -42
  314. package/src/route-renderer/component-graph.js +0 -72
  315. package/src/route-renderer/component-marker.d.ts +0 -52
  316. package/src/route-renderer/component-marker.js +0 -46
  317. package/src/route-renderer/dependency-resolver.d.ts +0 -24
  318. package/src/route-renderer/dependency-resolver.js +0 -428
  319. package/src/route-renderer/html-post-processing.service.d.ts +0 -40
  320. package/src/route-renderer/html-post-processing.service.js +0 -86
  321. package/src/route-renderer/html-post-processing.service.ts +0 -103
  322. package/src/route-renderer/integration-renderer.d.ts +0 -339
  323. package/src/route-renderer/integration-renderer.js +0 -526
  324. package/src/route-renderer/marker-graph-resolver.d.ts +0 -76
  325. package/src/route-renderer/marker-graph-resolver.js +0 -93
  326. package/src/route-renderer/page-module-loader.d.ts +0 -61
  327. package/src/route-renderer/page-module-loader.js +0 -102
  328. package/src/route-renderer/render-execution.service.d.ts +0 -69
  329. package/src/route-renderer/render-execution.service.js +0 -91
  330. package/src/route-renderer/render-preparation.service.d.ts +0 -112
  331. package/src/route-renderer/render-preparation.service.js +0 -243
  332. package/src/route-renderer/route-renderer.d.ts +0 -26
  333. package/src/route-renderer/route-renderer.js +0 -68
  334. package/src/router/fs-router-scanner.d.ts +0 -41
  335. package/src/router/fs-router-scanner.js +0 -155
  336. package/src/router/fs-router.d.ts +0 -26
  337. package/src/router/fs-router.js +0 -100
  338. package/src/services/asset-processing-service/asset-processing.service.d.ts +0 -41
  339. package/src/services/asset-processing-service/asset-processing.service.js +0 -250
  340. package/src/services/asset-processing-service/asset.factory.d.ts +0 -17
  341. package/src/services/asset-processing-service/asset.factory.js +0 -82
  342. package/src/services/asset-processing-service/assets.types.d.ts +0 -88
  343. package/src/services/asset-processing-service/assets.types.js +0 -0
  344. package/src/services/asset-processing-service/index.d.ts +0 -3
  345. package/src/services/asset-processing-service/index.js +0 -3
  346. package/src/services/asset-processing-service/processor.interface.d.ts +0 -22
  347. package/src/services/asset-processing-service/processor.interface.js +0 -6
  348. package/src/services/asset-processing-service/processor.registry.d.ts +0 -8
  349. package/src/services/asset-processing-service/processor.registry.js +0 -15
  350. package/src/services/asset-processing-service/processors/base/base-processor.d.ts +0 -24
  351. package/src/services/asset-processing-service/processors/base/base-processor.js +0 -59
  352. package/src/services/asset-processing-service/processors/base/base-script-processor.d.ts +0 -16
  353. package/src/services/asset-processing-service/processors/base/base-script-processor.js +0 -80
  354. package/src/services/asset-processing-service/processors/index.d.ts +0 -5
  355. package/src/services/asset-processing-service/processors/index.js +0 -5
  356. package/src/services/asset-processing-service/processors/script/content-script.processor.d.ts +0 -5
  357. package/src/services/asset-processing-service/processors/script/content-script.processor.js +0 -57
  358. package/src/services/asset-processing-service/processors/script/file-script.processor.d.ts +0 -8
  359. package/src/services/asset-processing-service/processors/script/file-script.processor.js +0 -76
  360. package/src/services/asset-processing-service/processors/script/node-module-script.processor.d.ts +0 -7
  361. package/src/services/asset-processing-service/processors/script/node-module-script.processor.js +0 -74
  362. package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -5
  363. package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +0 -25
  364. package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -9
  365. package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +0 -63
  366. package/src/services/cache/cache.types.d.ts +0 -107
  367. package/src/services/cache/cache.types.js +0 -0
  368. package/src/services/cache/index.d.ts +0 -7
  369. package/src/services/cache/index.js +0 -7
  370. package/src/services/cache/memory-cache-store.d.ts +0 -42
  371. package/src/services/cache/memory-cache-store.js +0 -98
  372. package/src/services/cache/page-cache-service.d.ts +0 -70
  373. package/src/services/cache/page-cache-service.js +0 -152
  374. package/src/services/html-transformer.service.d.ts +0 -50
  375. package/src/services/html-transformer.service.js +0 -163
  376. package/src/services/html-transformer.service.ts +0 -217
  377. package/src/services/page-module-import.service.d.ts +0 -37
  378. package/src/services/page-module-import.service.js +0 -88
  379. package/src/services/page-module-import.service.ts +0 -129
  380. package/src/services/page-request-cache-coordinator.service.d.ts +0 -75
  381. package/src/services/page-request-cache-coordinator.service.js +0 -107
  382. package/src/services/schema-validation-service.d.ts +0 -122
  383. package/src/services/schema-validation-service.js +0 -101
  384. package/src/services/validation/standard-schema.types.d.ts +0 -65
  385. package/src/services/validation/standard-schema.types.js +0 -0
  386. package/src/static-site-generator/static-site-generator.d.ts +0 -57
  387. package/src/static-site-generator/static-site-generator.js +0 -272
  388. package/src/utils/css.d.ts +0 -1
  389. package/src/utils/css.js +0 -7
  390. package/src/utils/deep-merge.d.ts +0 -14
  391. package/src/utils/deep-merge.js +0 -32
  392. package/src/utils/hash.d.ts +0 -1
  393. package/src/utils/hash.js +0 -7
  394. package/src/utils/html.d.ts +0 -1
  395. package/src/utils/html.js +0 -4
  396. package/src/utils/invariant.d.ts +0 -5
  397. package/src/utils/invariant.js +0 -11
  398. package/src/utils/locals-utils.d.ts +0 -15
  399. package/src/utils/locals-utils.js +0 -24
  400. package/src/utils/parse-cli-args.d.ts +0 -24
  401. package/src/utils/parse-cli-args.js +0 -47
  402. package/src/utils/path-utils.module.d.ts +0 -5
  403. package/src/utils/path-utils.module.js +0 -14
  404. package/src/utils/runtime.d.ts +0 -11
  405. package/src/utils/runtime.js +0 -40
  406. package/src/utils/server-utils.module.d.ts +0 -19
  407. package/src/utils/server-utils.module.js +0 -56
  408. package/src/watchers/project-watcher.d.ts +0 -132
  409. package/src/watchers/project-watcher.js +0 -281
  410. package/src/watchers/project-watcher.test-helpers.d.ts +0 -4
  411. package/src/watchers/project-watcher.test-helpers.js +0 -51
  412. /package/src/route-renderer/{component-graph-executor.ts → component-graph/component-graph-executor.ts} +0 -0
  413. /package/src/route-renderer/{component-graph.ts → component-graph/component-graph.ts} +0 -0
  414. /package/src/route-renderer/{component-marker.ts → component-graph/component-marker.ts} +0 -0
  415. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.registry.ts +0 -0
  416. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/index.ts +0 -0
  417. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/content-script.processor.ts +0 -0
  418. /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/content-stylesheet.processor.ts +0 -0
@@ -0,0 +1,223 @@
1
+ import { describe, test, expect } from 'vitest';
2
+ import { z } from 'zod';
3
+ import * as v from 'valibot';
4
+ import { type } from 'arktype';
5
+ import { SchemaValidationService } from './schema-validation-service.ts';
6
+
7
+ describe('SchemaValidationService', () => {
8
+ const service = new SchemaValidationService();
9
+
10
+ describe('Zod validation', () => {
11
+ test('validates body with Zod schema', async () => {
12
+ const schema = z.object({
13
+ title: z.string().min(1),
14
+ count: z.number(),
15
+ });
16
+
17
+ const result = await service.validateRequest(
18
+ { body: { title: 'Hello', count: 42 } },
19
+ { body: schema as unknown as Parameters<typeof service.validateRequest>[1]['body'] },
20
+ );
21
+
22
+ expect(result.success).toBe(true);
23
+ expect(result.data?.body).toEqual({ title: 'Hello', count: 42 });
24
+ });
25
+
26
+ test('rejects invalid body with Zod schema', async () => {
27
+ const schema = z.object({
28
+ title: z.string().min(1),
29
+ count: z.number(),
30
+ });
31
+
32
+ const result = await service.validateRequest(
33
+ { body: { title: '', count: 'not-a-number' } },
34
+ { body: schema as unknown as Parameters<typeof service.validateRequest>[1]['body'] },
35
+ );
36
+
37
+ expect(result.success).toBe(false);
38
+ expect(result.errors).toBeDefined();
39
+ expect(result.errors!.length).toBeGreaterThan(0);
40
+ });
41
+ });
42
+
43
+ describe('Valibot validation', () => {
44
+ test('validates query with Valibot schema', async () => {
45
+ const schema = v.object({
46
+ page: v.string(),
47
+ limit: v.string(),
48
+ });
49
+
50
+ const result = await service.validateRequest(
51
+ { query: { page: '1', limit: '10' } },
52
+ { query: schema as unknown as Parameters<typeof service.validateRequest>[1]['query'] },
53
+ );
54
+
55
+ expect(result.success).toBe(true);
56
+ expect(result.data?.query).toEqual({ page: '1', limit: '10' });
57
+ });
58
+
59
+ test('rejects invalid query with Valibot schema', async () => {
60
+ const schema = v.object({
61
+ page: v.pipe(v.string(), v.minLength(1)),
62
+ });
63
+
64
+ const result = await service.validateRequest(
65
+ { query: { page: '' } },
66
+ { query: schema as unknown as Parameters<typeof service.validateRequest>[1]['query'] },
67
+ );
68
+
69
+ expect(result.success).toBe(false);
70
+ expect(result.errors).toBeDefined();
71
+ });
72
+ });
73
+
74
+ describe('ArkType validation', () => {
75
+ test('validates headers with ArkType schema', async () => {
76
+ const schema = type({
77
+ 'content-type': 'string',
78
+ authorization: 'string',
79
+ });
80
+
81
+ const result = await service.validateRequest(
82
+ {
83
+ headers: {
84
+ 'content-type': 'application/json',
85
+ authorization: 'Bearer token',
86
+ },
87
+ },
88
+ { headers: schema as unknown as Parameters<typeof service.validateRequest>[1]['headers'] },
89
+ );
90
+
91
+ expect(result.success).toBe(true);
92
+ expect(result.data?.headers).toEqual({
93
+ 'content-type': 'application/json',
94
+ authorization: 'Bearer token',
95
+ });
96
+ });
97
+
98
+ test('rejects invalid headers with ArkType schema', async () => {
99
+ const schema = type({
100
+ 'content-type': 'string',
101
+ 'x-custom': 'string>5',
102
+ });
103
+
104
+ const result = await service.validateRequest(
105
+ {
106
+ headers: {
107
+ 'content-type': 'application/json',
108
+ 'x-custom': 'ab',
109
+ },
110
+ },
111
+ { headers: schema as unknown as Parameters<typeof service.validateRequest>[1]['headers'] },
112
+ );
113
+
114
+ expect(result.success).toBe(false);
115
+ expect(result.errors).toBeDefined();
116
+ });
117
+ });
118
+
119
+ describe('Combined validation', () => {
120
+ test('validates multiple sources at once', async () => {
121
+ const bodySchema = z.object({
122
+ title: z.string(),
123
+ });
124
+ const querySchema = v.object({
125
+ format: v.string(),
126
+ });
127
+
128
+ const result = await service.validateRequest(
129
+ {
130
+ body: { title: 'Post Title' },
131
+ query: { format: 'json' },
132
+ },
133
+ {
134
+ body: bodySchema as unknown as Parameters<typeof service.validateRequest>[1]['body'],
135
+ query: querySchema as unknown as Parameters<typeof service.validateRequest>[1]['query'],
136
+ },
137
+ );
138
+
139
+ expect(result.success).toBe(true);
140
+ expect(result.data?.body).toEqual({ title: 'Post Title' });
141
+ expect(result.data?.query).toEqual({ format: 'json' });
142
+ });
143
+
144
+ test('validates route params with schema', async () => {
145
+ const paramsSchema = z.object({
146
+ id: z.coerce.number().int(),
147
+ });
148
+
149
+ const result = await service.validateRequest(
150
+ {
151
+ params: { id: '42' },
152
+ },
153
+ {
154
+ params: paramsSchema as unknown as Parameters<typeof service.validateRequest>[1]['params'],
155
+ },
156
+ );
157
+
158
+ expect(result.success).toBe(true);
159
+ expect(result.data?.params).toEqual({ id: 42 });
160
+ });
161
+
162
+ test('aggregates errors from multiple sources', async () => {
163
+ const bodySchema = z.object({
164
+ title: z.string().min(5),
165
+ });
166
+ const querySchema = v.object({
167
+ page: v.pipe(v.string(), v.regex(/^\d+$/)),
168
+ });
169
+
170
+ const result = await service.validateRequest(
171
+ {
172
+ body: { title: 'ab' },
173
+ query: { page: 'invalid' },
174
+ },
175
+ {
176
+ body: bodySchema as unknown as Parameters<typeof service.validateRequest>[1]['body'],
177
+ query: querySchema as unknown as Parameters<typeof service.validateRequest>[1]['query'],
178
+ },
179
+ );
180
+
181
+ expect(result.success).toBe(false);
182
+ expect(result.errors).toBeDefined();
183
+ expect(result.errors!.length).toBeGreaterThan(1);
184
+ });
185
+ });
186
+
187
+ describe('Edge cases', () => {
188
+ test('handles missing optional schemas', async () => {
189
+ const result = await service.validateRequest({ body: { data: 'test' } }, {});
190
+
191
+ expect(result.success).toBe(true);
192
+ expect(result.data).toEqual({});
193
+ });
194
+
195
+ test('handles undefined source data', async () => {
196
+ const schema = z.object({ name: z.string() });
197
+
198
+ const result = await service.validateRequest(
199
+ { body: undefined },
200
+ { body: schema as unknown as Parameters<typeof service.validateRequest>[1]['body'] },
201
+ );
202
+
203
+ expect(result.success).toBe(true);
204
+ });
205
+
206
+ test('catches validation exceptions', async () => {
207
+ const brokenSchema = {
208
+ '~standard': {
209
+ version: 1,
210
+ vendor: 'test',
211
+ validate: () => {
212
+ throw new Error('Validation crashed');
213
+ },
214
+ },
215
+ } as const;
216
+
217
+ const result = await service.validateRequest({ body: { test: true } }, { body: brokenSchema });
218
+
219
+ expect(result.success).toBe(false);
220
+ expect(result.errors?.[0]?.message).toBe('Validation crashed');
221
+ });
222
+ });
223
+ });
@@ -1,4 +1,4 @@
1
- import type { StandardSchema, StandardSchemaIssue } from './validation/standard-schema.types.ts';
1
+ import type { StandardSchema, StandardSchemaIssue } from './standard-schema.types.js';
2
2
 
3
3
  export interface ValidationResult<T = unknown> {
4
4
  success: boolean;
@@ -0,0 +1,26 @@
1
+ # Static Site Generation
2
+
3
+ This directory contains the static-build execution path used when Ecopages renders pages ahead of time.
4
+
5
+ ## Purpose
6
+
7
+ The static-site generator reuses the same app-owned config, route matching, and rendering services that development and preview flows use, but drives them in a build-oriented loop.
8
+
9
+ It is responsible for:
10
+
11
+ - enumerating renderable routes
12
+ - rendering static outputs through the normal rendering pipeline
13
+ - respecting route-level constraints such as cache policy and unsupported dynamic server-only paths
14
+
15
+ ## Design Rule
16
+
17
+ Static generation should follow the same ownership model as runtime rendering.
18
+
19
+ That means it should reuse:
20
+
21
+ - built app config
22
+ - route matching
23
+ - render orchestration
24
+ - asset processing
25
+
26
+ It should not invent a parallel rendering stack just for build mode.
@@ -0,0 +1,307 @@
1
+ import { describe, expect, test, beforeEach, afterEach, vi } from 'vitest';
2
+ import { fileSystem } from '@ecopages/file-system';
3
+ import { StaticSiteGenerator } from './static-site-generator';
4
+ import type { EcoPagesAppConfig } from '../internal-types';
5
+ import type { FSRouter } from '../router/server/fs-router';
6
+ import type { RouteRendererFactory } from '../route-renderer/route-renderer';
7
+ import { appLogger } from '../global/app-logger.ts';
8
+ import { PageModuleImportService } from '../services/module-loading/page-module-import.service';
9
+ import { DEFAULT_ECOPAGES_WORK_DIR } from '../constants.ts';
10
+
11
+ const originalEnsureDir = fileSystem.ensureDir;
12
+ const originalWrite = fileSystem.write;
13
+
14
+ const createMockConfig = (overrides: Partial<EcoPagesAppConfig> = {}): EcoPagesAppConfig =>
15
+ ({
16
+ rootDir: '/test/project',
17
+ distDir: 'dist',
18
+ workDir: DEFAULT_ECOPAGES_WORK_DIR,
19
+ srcDir: 'src',
20
+ robotsTxt: {
21
+ preferences: {
22
+ '*': ['/admin', '/private'],
23
+ Googlebot: ['/no-google'],
24
+ },
25
+ },
26
+ absolutePaths: {
27
+ distDir: '/test/project/dist',
28
+ workDir: '/test/project/.eco',
29
+ } as EcoPagesAppConfig['absolutePaths'],
30
+ integrations: [],
31
+ ...overrides,
32
+ }) as EcoPagesAppConfig;
33
+
34
+ describe('StaticSiteGenerator', () => {
35
+ let ensureDirMock: any;
36
+ let writeMock: any;
37
+
38
+ beforeEach(() => {
39
+ ensureDirMock = vi.fn(() => {});
40
+ writeMock = vi.fn(() => {});
41
+ fileSystem.ensureDir = ensureDirMock;
42
+ fileSystem.write = writeMock;
43
+ vi.spyOn(PageModuleImportService.prototype, 'importModule').mockResolvedValue({
44
+ default: Object.assign(() => null, { cache: 'static' }),
45
+ });
46
+ vi.spyOn(appLogger, 'warn').mockReturnValue(appLogger);
47
+ });
48
+
49
+ afterEach(() => {
50
+ fileSystem.ensureDir = originalEnsureDir;
51
+ fileSystem.write = originalWrite;
52
+ vi.restoreAllMocks();
53
+ });
54
+
55
+ describe('constructor', () => {
56
+ test('should create instance with appConfig', () => {
57
+ const config = createMockConfig();
58
+ const ssg = new StaticSiteGenerator({ appConfig: config });
59
+ expect(ssg.appConfig).toBe(config);
60
+ });
61
+ });
62
+
63
+ describe('isRootDir', () => {
64
+ test('should return true for root path /', () => {
65
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
66
+ expect(ssg.isRootDir('/')).toBe(true);
67
+ });
68
+
69
+ test('should return false for nested path /foo/bar', () => {
70
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
71
+ expect(ssg.isRootDir('/foo/bar')).toBe(false);
72
+ });
73
+
74
+ test('should return false for deeply nested paths', () => {
75
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
76
+ expect(ssg.isRootDir('/a/b/c/d')).toBe(false);
77
+ });
78
+
79
+ test('should return null (falsy) for paths without slashes', () => {
80
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
81
+ expect(ssg.isRootDir('no-slashes')).toBeFalsy();
82
+ });
83
+ });
84
+
85
+ describe('getDirectories', () => {
86
+ test('should return empty array for root-level routes', () => {
87
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
88
+ const dirs = ssg.getDirectories(['/about', '/contact']);
89
+ expect(dirs).toEqual([]);
90
+ });
91
+
92
+ test('should extract directories from nested routes', () => {
93
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
94
+ const dirs = ssg.getDirectories(['/blog/post-1', '/blog/post-2', '/docs/api']);
95
+ expect(dirs).toContain('/blog');
96
+ expect(dirs).toContain('/docs');
97
+ });
98
+
99
+ test('should handle HTTP URLs and extract pathname', () => {
100
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
101
+ const dirs = ssg.getDirectories(['http://localhost:3000/blog/post']);
102
+ expect(dirs).toContain('/blog');
103
+ });
104
+
105
+ test('should deduplicate directories', () => {
106
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
107
+ const dirs = ssg.getDirectories(['/blog/a', '/blog/b', '/blog/c']);
108
+ expect(dirs.filter((d) => d === '/blog').length).toBe(1);
109
+ });
110
+
111
+ test('should handle deeply nested paths', () => {
112
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
113
+ const dirs = ssg.getDirectories(['/a/b/c/page']);
114
+ expect(dirs).toContain('/a/b/c');
115
+ });
116
+ });
117
+
118
+ describe('generateRobotsTxt', () => {
119
+ test('should generate robots.txt with preferences from config', () => {
120
+ const config = createMockConfig();
121
+ const ssg = new StaticSiteGenerator({ appConfig: config });
122
+
123
+ ssg.generateRobotsTxt();
124
+
125
+ expect(ensureDirMock).toHaveBeenCalledWith('/test/project/dist');
126
+ expect(writeMock).toHaveBeenCalledWith('/test/project/dist/robots.txt', expect.any(String));
127
+
128
+ const writtenContent = writeMock.mock.calls[0][1] as string;
129
+ expect(writtenContent).toContain('user-agent: *');
130
+ expect(writtenContent).toContain('disallow: /admin');
131
+ expect(writtenContent).toContain('disallow: /private');
132
+ expect(writtenContent).toContain('user-agent: Googlebot');
133
+ expect(writtenContent).toContain('disallow: /no-google');
134
+ });
135
+
136
+ test('should handle empty preferences', () => {
137
+ const config = createMockConfig({
138
+ robotsTxt: { preferences: {} },
139
+ });
140
+ const ssg = new StaticSiteGenerator({ appConfig: config });
141
+
142
+ ssg.generateRobotsTxt();
143
+
144
+ expect(writeMock).toHaveBeenCalledWith('/test/project/dist/robots.txt', '');
145
+ });
146
+ });
147
+
148
+ describe('generateStaticPages', () => {
149
+ const createMockRouter = (routes: Record<string, { filePath: string; pathname: string }>) =>
150
+ ({
151
+ routes: Object.fromEntries(
152
+ Object.entries(routes).map(([key, value]) => [key, { ...value, kind: 'exact' }]),
153
+ ),
154
+ origin: 'http://localhost:3000',
155
+ }) as unknown as FSRouter;
156
+
157
+ test('should filter out dynamic routes containing [', async () => {
158
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
159
+ const Router = createMockRouter({
160
+ '/static': { filePath: '/src/pages/static.ghtml.ts', pathname: '/static' },
161
+ '/dynamic/[id]': { filePath: '/src/pages/dynamic/[id].ghtml.ts', pathname: '/dynamic/[id]' },
162
+ });
163
+
164
+ const RendererFactory = {
165
+ createRenderer: vi.fn(() => ({
166
+ createRoute: vi.fn(async () => ({ body: '<html>Static</html>' })),
167
+ })),
168
+ } as unknown as RouteRendererFactory;
169
+
170
+ await ssg.generateStaticPages(Router, 'http://localhost:3000', RendererFactory);
171
+
172
+ expect(writeMock).toHaveBeenCalledTimes(1);
173
+ });
174
+
175
+ test('should create directories for nested routes', async () => {
176
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
177
+ const Router = createMockRouter({
178
+ '/blog/post': { filePath: '/src/pages/blog/post.ghtml.ts', pathname: '/blog/post' },
179
+ });
180
+
181
+ const RendererFactory = {
182
+ createRenderer: vi.fn(() => ({
183
+ createRoute: vi.fn(async () => ({ body: '<html>Blog Post</html>' })),
184
+ })),
185
+ } as unknown as RouteRendererFactory;
186
+
187
+ await ssg.generateStaticPages(Router, 'http://localhost:3000', RendererFactory);
188
+
189
+ expect(ensureDirMock).toHaveBeenCalled();
190
+ });
191
+
192
+ test('should throw error when routeRendererFactory is missing for render strategy', async () => {
193
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
194
+ const Router = createMockRouter({
195
+ '/page': { filePath: '/src/pages/page.ghtml.ts', pathname: '/page' },
196
+ });
197
+
198
+ await ssg.generateStaticPages(Router, 'http://localhost:3000', undefined);
199
+ });
200
+
201
+ test('should write index.html for root path', async () => {
202
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
203
+ const Router = createMockRouter({
204
+ '/': { filePath: '/src/pages/index.ghtml.ts', pathname: '/' },
205
+ });
206
+
207
+ const RendererFactory = {
208
+ createRenderer: vi.fn(() => ({
209
+ createRoute: vi.fn(async () => ({ body: '<html>Home</html>' })),
210
+ })),
211
+ } as unknown as RouteRendererFactory;
212
+
213
+ await ssg.generateStaticPages(Router, 'http://localhost:3000', RendererFactory);
214
+
215
+ expect(writeMock).toHaveBeenCalledWith(expect.stringContaining('index.html'), '<html>Home</html>');
216
+ });
217
+
218
+ test('should handle Buffer content from renderer', async () => {
219
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
220
+ const Router = createMockRouter({
221
+ '/': { filePath: '/src/pages/index.ghtml.ts', pathname: '/' },
222
+ });
223
+
224
+ const bufferContent = Buffer.from('<html>Buffer Content</html>');
225
+ const RendererFactory = {
226
+ createRenderer: vi.fn(() => ({
227
+ createRoute: vi.fn(async () => ({ body: bufferContent })),
228
+ })),
229
+ } as unknown as RouteRendererFactory;
230
+
231
+ await ssg.generateStaticPages(Router, 'http://localhost:3000', RendererFactory);
232
+
233
+ expect(writeMock).toHaveBeenCalledWith(expect.stringContaining('index.html'), bufferContent);
234
+ });
235
+
236
+ test('should skip cache dynamic pages during static generation and log a warning', async () => {
237
+ vi.spyOn(PageModuleImportService.prototype, 'importModule').mockResolvedValue({
238
+ default: Object.assign(() => null, { cache: 'dynamic' }),
239
+ });
240
+
241
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
242
+ const Router = createMockRouter({
243
+ '/dashboard': { filePath: '/src/pages/dashboard.tsx', pathname: '/dashboard' },
244
+ });
245
+
246
+ const RendererFactory = {
247
+ createRenderer: vi.fn(() => ({
248
+ createRoute: vi.fn(async () => ({ body: '<html>Dashboard</html>' })),
249
+ })),
250
+ } as unknown as RouteRendererFactory;
251
+
252
+ await ssg.generateStaticPages(Router, 'http://localhost:3000', RendererFactory);
253
+
254
+ expect(RendererFactory.createRenderer).not.toHaveBeenCalled();
255
+ expect(writeMock).not.toHaveBeenCalled();
256
+ expect(appLogger.warn).toHaveBeenCalledWith(
257
+ "Pages with cache: 'dynamic' are not supported in static generation or preview, so they will be skipped\n",
258
+ '➤ /src/pages/dashboard.tsx',
259
+ );
260
+ });
261
+ });
262
+
263
+ describe('run', () => {
264
+ test('should call generateRobotsTxt and generateStaticPages', async () => {
265
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
266
+ const Router = {
267
+ routes: {},
268
+ origin: 'http://localhost:3000',
269
+ } as unknown as FSRouter;
270
+
271
+ await ssg.run({
272
+ router: Router,
273
+ baseUrl: 'http://localhost:3000',
274
+ });
275
+
276
+ expect(ensureDirMock).toHaveBeenCalled();
277
+ expect(writeMock).toHaveBeenCalledWith('/test/project/dist/robots.txt', expect.any(String));
278
+ });
279
+
280
+ test('should skip explicit static routes backed by cache dynamic views', async () => {
281
+ const ssg = new StaticSiteGenerator({ appConfig: createMockConfig() });
282
+ const dynamicView = Object.assign(() => null, { cache: 'dynamic' }) as any;
283
+
284
+ await ssg.run({
285
+ router: {
286
+ routes: {},
287
+ origin: 'http://localhost:3000',
288
+ } as unknown as FSRouter,
289
+ baseUrl: 'http://localhost:3000',
290
+ routeRendererFactory: {
291
+ getRendererByIntegration: vi.fn(),
292
+ } as unknown as RouteRendererFactory,
293
+ staticRoutes: [
294
+ {
295
+ path: '/dashboard',
296
+ loader: async () => ({ default: dynamicView }),
297
+ },
298
+ ],
299
+ });
300
+
301
+ expect(appLogger.warn).toHaveBeenCalledWith(
302
+ "Pages with cache: 'dynamic' are not supported in static generation or preview, so they will be skipped\n",
303
+ '➤ /dashboard',
304
+ );
305
+ });
306
+ });
307
+ });