meno-core 1.0.53 → 1.1.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 (415) hide show
  1. package/.claude/settings.local.json +1 -3
  2. package/bin/cli.ts +66 -261
  3. package/build-astro.ts +150 -128
  4. package/dist/bin/cli.js +42 -185
  5. package/dist/bin/cli.js.map +2 -2
  6. package/dist/chunks/chunk-2AR55GYH.js +42 -0
  7. package/dist/chunks/chunk-2AR55GYH.js.map +7 -0
  8. package/dist/chunks/{chunk-JGWFTO6P.js → chunk-2IIQK7T3.js} +2624 -1389
  9. package/dist/chunks/chunk-2IIQK7T3.js.map +7 -0
  10. package/dist/chunks/chunk-4ZRU52J2.js +169 -0
  11. package/dist/chunks/chunk-4ZRU52J2.js.map +7 -0
  12. package/dist/chunks/{chunk-UB44F4Z2.js → chunk-5X4HCN7J.js} +5 -7
  13. package/dist/chunks/chunk-5X4HCN7J.js.map +7 -0
  14. package/dist/chunks/{chunk-WQFG7PAH.js → chunk-7CCVOL5M.js} +15 -19
  15. package/dist/chunks/chunk-7CCVOL5M.js.map +7 -0
  16. package/dist/chunks/{chunk-YBLHKYFF.js → chunk-AR7LHIFY.js} +8 -2
  17. package/dist/chunks/chunk-AR7LHIFY.js.map +7 -0
  18. package/dist/chunks/{chunk-O3NAGJP4.js → chunk-NUP7H7D3.js} +135 -41
  19. package/dist/chunks/chunk-NUP7H7D3.js.map +7 -0
  20. package/dist/chunks/{chunk-X754AHS5.js → chunk-QWTQZHG3.js} +194 -90
  21. package/dist/chunks/chunk-QWTQZHG3.js.map +7 -0
  22. package/dist/chunks/{chunk-H3GJ4H2U.js → chunk-XTKNX4FW.js} +216 -87
  23. package/dist/chunks/chunk-XTKNX4FW.js.map +7 -0
  24. package/dist/chunks/{fs-JGINUXGL.js → fs-G3ANWEFP.js} +2 -2
  25. package/dist/lib/client/index.js +1003 -475
  26. package/dist/lib/client/index.js.map +3 -3
  27. package/dist/lib/server/index.js +14393 -6371
  28. package/dist/lib/server/index.js.map +4 -4
  29. package/dist/lib/shared/index.js +342 -101
  30. package/dist/lib/shared/index.js.map +4 -4
  31. package/dist/lib/shared/richtext/index.js +1 -1
  32. package/dist/lib/test-utils/index.js +64 -80
  33. package/dist/lib/test-utils/index.js.map +2 -2
  34. package/entries/client-router.tsx +10 -8
  35. package/lib/client/ClientInitializer.ts +8 -8
  36. package/lib/client/ErrorBoundary.test.tsx +246 -186
  37. package/lib/client/ErrorBoundary.tsx +183 -132
  38. package/lib/client/componentRegistry.test.ts +96 -108
  39. package/lib/client/componentRegistry.ts +1 -3
  40. package/lib/client/contexts/ThemeContext.tsx +3 -2
  41. package/lib/client/core/ComponentBuilder.test.ts +663 -560
  42. package/lib/client/core/ComponentBuilder.ts +427 -155
  43. package/lib/client/core/ComponentRenderer.test.tsx +2 -4
  44. package/lib/client/core/ComponentRenderer.tsx +46 -33
  45. package/lib/client/core/builders/embedBuilder.ts +242 -54
  46. package/lib/client/core/builders/linkBuilder.ts +72 -45
  47. package/lib/client/core/builders/linkNodeBuilder.ts +79 -54
  48. package/lib/client/core/builders/listBuilder.ts +155 -89
  49. package/lib/client/core/builders/localeListBuilder.ts +97 -62
  50. package/lib/client/core/builders/types.ts +5 -5
  51. package/lib/client/core/cmsTemplateProcessor.ts +8 -9
  52. package/lib/client/elementRegistry.ts +3 -3
  53. package/lib/client/fontFamiliesService.test.ts +2 -10
  54. package/lib/client/fontFamiliesService.ts +3 -3
  55. package/lib/client/hmr/HMRManager.tsx +47 -30
  56. package/lib/client/hmrCssReload.ts +49 -14
  57. package/lib/client/hmrWebSocket.ts +14 -19
  58. package/lib/client/hooks/useColorVariables.test.ts +21 -21
  59. package/lib/client/hooks/useColorVariables.ts +23 -18
  60. package/lib/client/hooks/usePropertyAutocomplete.ts +4 -6
  61. package/lib/client/hooks/useVariables.ts +6 -4
  62. package/lib/client/hydration/HydrationUtils.test.ts +24 -25
  63. package/lib/client/hydration/HydrationUtils.ts +3 -4
  64. package/lib/client/i18nConfigService.test.ts +2 -7
  65. package/lib/client/i18nConfigService.ts +2 -2
  66. package/lib/client/meno-filter/MenoFilter.test.ts +47 -49
  67. package/lib/client/meno-filter/MenoFilter.ts +14 -15
  68. package/lib/client/meno-filter/bindings.ts +18 -43
  69. package/lib/client/meno-filter/init.ts +4 -4
  70. package/lib/client/meno-filter/renderer.ts +30 -32
  71. package/lib/client/meno-filter/script.generated.ts +1 -3
  72. package/lib/client/meno-filter/ui.ts +4 -6
  73. package/lib/client/meno-filter/updates.ts +18 -23
  74. package/lib/client/meno-filter/utils.ts +1 -1
  75. package/lib/client/navigation.test.ts +174 -178
  76. package/lib/client/navigation.ts +0 -1
  77. package/lib/client/responsiveStyleResolver.knownTokens.test.ts +71 -0
  78. package/lib/client/responsiveStyleResolver.test.ts +234 -232
  79. package/lib/client/responsiveStyleResolver.ts +74 -20
  80. package/lib/client/routing/RouteLoader.test.ts +24 -25
  81. package/lib/client/routing/RouteLoader.ts +27 -35
  82. package/lib/client/routing/Router.tsx +210 -153
  83. package/lib/client/scripts/ScriptExecutor.test.ts +157 -158
  84. package/lib/client/scripts/ScriptExecutor.ts +18 -36
  85. package/lib/client/services/PrefetchService.test.ts +3 -3
  86. package/lib/client/services/PrefetchService.ts +23 -29
  87. package/lib/client/styleProcessor.test.ts +9 -9
  88. package/lib/client/styleProcessor.ts +24 -15
  89. package/lib/client/styles/StyleInjector.test.ts +122 -115
  90. package/lib/client/styles/StyleInjector.ts +10 -7
  91. package/lib/client/styles/UtilityClassCollector.ts +62 -28
  92. package/lib/client/styles/cspNonce.test.ts +2 -5
  93. package/lib/client/templateEngine.test.ts +554 -488
  94. package/lib/client/templateEngine.ts +203 -73
  95. package/lib/client/theme.test.ts +1 -1
  96. package/lib/client/theme.ts +0 -1
  97. package/lib/client/utils/toast.ts +0 -1
  98. package/lib/server/__integration__/api-routes.test.ts +8 -4
  99. package/lib/server/__integration__/cms-integration.test.ts +1 -4
  100. package/lib/server/__integration__/server-lifecycle.test.ts +4 -5
  101. package/lib/server/__integration__/ssr-rendering.test.ts +47 -37
  102. package/lib/server/__integration__/static-assets.test.ts +3 -3
  103. package/lib/server/__integration__/test-helpers.ts +87 -74
  104. package/lib/server/ab/generateFunctions.ts +12 -10
  105. package/lib/server/astro/cmsPageEmitter.ts +26 -42
  106. package/lib/server/astro/componentEmitter.ts +35 -43
  107. package/lib/server/astro/cssCollector.ts +10 -26
  108. package/lib/server/astro/nodeToAstro.test.ts +1754 -34
  109. package/lib/server/astro/nodeToAstro.ts +232 -216
  110. package/lib/server/astro/normalizeOrphanTemplateProps.test.ts +115 -119
  111. package/lib/server/astro/normalizeOrphanTemplateProps.ts +11 -18
  112. package/lib/server/astro/pageEmitter.ts +9 -13
  113. package/lib/server/astro/tailwindMapper.test.ts +10 -37
  114. package/lib/server/astro/tailwindMapper.ts +33 -40
  115. package/lib/server/astro/templateTransformer.ts +17 -20
  116. package/lib/server/createServer.ts +7 -19
  117. package/lib/server/cssGenerator.test.ts +35 -44
  118. package/lib/server/cssGenerator.ts +8 -19
  119. package/lib/server/fileWatcher.test.ts +164 -13
  120. package/lib/server/fileWatcher.ts +209 -124
  121. package/lib/server/index.ts +14 -17
  122. package/lib/server/jsonLoader.test.ts +39 -2
  123. package/lib/server/jsonLoader.ts +39 -34
  124. package/lib/server/middleware/cors.test.ts +21 -21
  125. package/lib/server/middleware/cors.ts +28 -4
  126. package/lib/server/middleware/errorHandler.test.ts +7 -5
  127. package/lib/server/middleware/errorHandler.ts +3 -8
  128. package/lib/server/middleware/index.ts +0 -1
  129. package/lib/server/middleware/logger.test.ts +10 -8
  130. package/lib/server/middleware/logger.ts +17 -29
  131. package/lib/server/migrateTemplates.ts +3 -3
  132. package/lib/server/pageCache.test.ts +76 -77
  133. package/lib/server/pageCache.ts +0 -1
  134. package/lib/server/projectContext.ts +5 -4
  135. package/lib/server/providers/fileSystemCMSProvider.test.ts +142 -99
  136. package/lib/server/providers/fileSystemCMSProvider.ts +62 -38
  137. package/lib/server/routes/api/cms.test.ts +26 -14
  138. package/lib/server/routes/api/cms.ts +9 -14
  139. package/lib/server/routes/api/colors.test.ts +2 -2
  140. package/lib/server/routes/api/components.ts +31 -35
  141. package/lib/server/routes/api/config.ts +3 -4
  142. package/lib/server/routes/api/core-routes.ts +49 -76
  143. package/lib/server/routes/api/enums.test.ts +2 -2
  144. package/lib/server/routes/api/functions.ts +9 -17
  145. package/lib/server/routes/api/index.ts +3 -6
  146. package/lib/server/routes/api/pages.ts +8 -11
  147. package/lib/server/routes/api/shared.test.ts +1 -1
  148. package/lib/server/routes/api/shared.ts +12 -9
  149. package/lib/server/routes/api/variables.test.ts +3 -5
  150. package/lib/server/routes/api/variables.ts +1 -1
  151. package/lib/server/routes/index.ts +25 -28
  152. package/lib/server/routes/pages.ts +35 -31
  153. package/lib/server/routes/static.ts +17 -6
  154. package/lib/server/runtime/bundler.ts +98 -61
  155. package/lib/server/runtime/fs.ts +16 -26
  156. package/lib/server/runtime/httpServer.ts +8 -12
  157. package/lib/server/services/ColorService.test.ts +3 -3
  158. package/lib/server/services/ColorService.ts +37 -29
  159. package/lib/server/services/EnumService.test.ts +4 -8
  160. package/lib/server/services/EnumService.ts +11 -3
  161. package/lib/server/services/VariableService.test.ts +8 -12
  162. package/lib/server/services/VariableService.ts +11 -3
  163. package/lib/server/services/cmsService.test.ts +158 -120
  164. package/lib/server/services/cmsService.ts +36 -146
  165. package/lib/server/services/componentService.test.ts +125 -45
  166. package/lib/server/services/componentService.ts +70 -46
  167. package/lib/server/services/configService.test.ts +22 -45
  168. package/lib/server/services/configService.ts +50 -27
  169. package/lib/server/services/fileWatcherService.ts +42 -8
  170. package/lib/server/services/index.ts +0 -1
  171. package/lib/server/services/pageService.test.ts +8 -10
  172. package/lib/server/services/pageService.ts +32 -18
  173. package/lib/server/ssr/attributeBuilder.ts +18 -8
  174. package/lib/server/ssr/buildErrorOverlay.ts +11 -12
  175. package/lib/server/ssr/clientDataInjector.ts +7 -21
  176. package/lib/server/ssr/cmsSSRProcessor.ts +4 -8
  177. package/lib/server/ssr/cssCollector.ts +1 -1
  178. package/lib/server/ssr/errorOverlay.test.ts +1 -1
  179. package/lib/server/ssr/errorOverlay.ts +3 -9
  180. package/lib/server/ssr/htmlGenerator.nonce.test.ts +9 -14
  181. package/lib/server/ssr/htmlGenerator.test.ts +120 -44
  182. package/lib/server/ssr/htmlGenerator.ts +126 -91
  183. package/lib/server/ssr/imageMetadata.test.ts +3 -1
  184. package/lib/server/ssr/imageMetadata.ts +27 -21
  185. package/lib/server/ssr/jsCollector.test.ts +8 -18
  186. package/lib/server/ssr/jsCollector.ts +3 -8
  187. package/lib/server/ssr/liveReloadIntegration.test.ts +76 -36
  188. package/lib/server/ssr/metaTagGenerator.ts +2 -2
  189. package/lib/server/ssr/ssrRenderer.branches.test.ts +1103 -0
  190. package/lib/server/ssr/ssrRenderer.test.ts +316 -256
  191. package/lib/server/ssr/ssrRenderer.ts +795 -243
  192. package/lib/server/ssrRenderer.test.ts +1048 -954
  193. package/lib/server/utils/jsonLineMapper.test.ts +28 -28
  194. package/lib/server/utils/jsonLineMapper.ts +7 -7
  195. package/lib/server/validateStyleCoverage.ts +18 -21
  196. package/lib/server/websocketManager.ts +28 -19
  197. package/lib/shared/attributeNodeUtils.test.ts +15 -15
  198. package/lib/shared/attributeNodeUtils.ts +5 -12
  199. package/lib/shared/breakpoints.test.ts +5 -5
  200. package/lib/shared/breakpoints.ts +4 -11
  201. package/lib/shared/cmsQuery.test.ts +81 -0
  202. package/lib/shared/cmsQuery.ts +92 -0
  203. package/lib/shared/cmsQueryParser.test.ts +50 -42
  204. package/lib/shared/cmsQueryParser.ts +60 -38
  205. package/lib/shared/colorConversions.ts +9 -9
  206. package/lib/shared/colorVariableUtils.test.ts +27 -5
  207. package/lib/shared/colorVariableUtils.ts +21 -12
  208. package/lib/shared/componentRefs.ts +1 -5
  209. package/lib/shared/constants.test.ts +3 -3
  210. package/lib/shared/constants.ts +8 -8
  211. package/lib/shared/cssGeneration.test.ts +285 -144
  212. package/lib/shared/cssGeneration.ts +217 -531
  213. package/lib/shared/cssNamedColors.ts +152 -30
  214. package/lib/shared/cssProperties.test.ts +69 -70
  215. package/lib/shared/cssProperties.ts +298 -114
  216. package/lib/shared/elementClassName.test.ts +109 -109
  217. package/lib/shared/elementClassName.ts +3 -3
  218. package/lib/shared/elementUtils.ts +12 -16
  219. package/lib/shared/errorLogger.test.ts +12 -12
  220. package/lib/shared/errorLogger.ts +2 -10
  221. package/lib/shared/errors.test.ts +2 -13
  222. package/lib/shared/errors.ts +2 -8
  223. package/lib/shared/expressionEvaluator.test.ts +145 -0
  224. package/lib/shared/expressionEvaluator.ts +52 -24
  225. package/lib/shared/fontLoader.test.ts +32 -18
  226. package/lib/shared/fontLoader.ts +2 -2
  227. package/lib/shared/friendlyError.ts +2 -3
  228. package/lib/shared/gradientUtils.test.ts +3 -7
  229. package/lib/shared/gradientUtils.ts +17 -14
  230. package/lib/shared/hrefRefs.test.ts +2 -2
  231. package/lib/shared/hrefRefs.ts +2 -10
  232. package/lib/shared/i18n.test.ts +4 -4
  233. package/lib/shared/i18n.ts +18 -38
  234. package/lib/shared/index.ts +27 -0
  235. package/lib/shared/inlineSvgStyleRules.ts +14 -13
  236. package/lib/shared/interactiveStyleMappings.test.ts +32 -54
  237. package/lib/shared/interactiveStyleMappings.ts +11 -24
  238. package/lib/shared/interactiveStyles.test.ts +165 -188
  239. package/lib/shared/interfaces/contentProvider.ts +1 -1
  240. package/lib/shared/itemTemplateUtils.test.ts +11 -17
  241. package/lib/shared/itemTemplateUtils.ts +27 -39
  242. package/lib/shared/jsonRepair.ts +16 -10
  243. package/lib/shared/libraryLoader.test.ts +21 -55
  244. package/lib/shared/libraryLoader.ts +7 -22
  245. package/lib/shared/linkUtils.ts +1 -1
  246. package/lib/shared/logger.test.ts +66 -0
  247. package/lib/shared/logger.ts +94 -0
  248. package/lib/shared/markdown.ts +25 -0
  249. package/lib/shared/netlifyLocale404.test.ts +179 -0
  250. package/lib/shared/netlifyLocale404.ts +110 -0
  251. package/lib/shared/nodeUtils.test.ts +28 -16
  252. package/lib/shared/nodeUtils.ts +76 -23
  253. package/lib/shared/pathArrayUtils.test.ts +1 -2
  254. package/lib/shared/pathArrayUtils.ts +1 -1
  255. package/lib/shared/pathSecurity.ts +2 -2
  256. package/lib/shared/pathUtils.test.ts +4 -6
  257. package/lib/shared/pathUtils.ts +42 -49
  258. package/lib/shared/paths/Path.test.ts +2 -2
  259. package/lib/shared/paths/Path.ts +0 -1
  260. package/lib/shared/paths/PathConverter.test.ts +1 -1
  261. package/lib/shared/paths/PathConverter.ts +17 -20
  262. package/lib/shared/paths/PathUtils.ts +13 -13
  263. package/lib/shared/paths/PathValidator.test.ts +2 -15
  264. package/lib/shared/paths/PathValidator.ts +12 -10
  265. package/lib/shared/paths/index.ts +1 -2
  266. package/lib/shared/permissions.test.ts +168 -0
  267. package/lib/shared/permissions.ts +162 -0
  268. package/lib/shared/propResolver.test.ts +240 -244
  269. package/lib/shared/propResolver.ts +15 -26
  270. package/lib/shared/pxToRem.test.ts +7 -6
  271. package/lib/shared/pxToRem.ts +2 -5
  272. package/lib/shared/registry/BaseNodeTypeRegistry.test.ts +12 -6
  273. package/lib/shared/registry/ClientRegistry.ts +0 -2
  274. package/lib/shared/registry/ComponentRegistry.test.ts +46 -32
  275. package/lib/shared/registry/ComponentRegistry.ts +12 -9
  276. package/lib/shared/registry/NodeTypeDefinition.ts +16 -9
  277. package/lib/shared/registry/RegistryManager.ts +1 -2
  278. package/lib/shared/registry/SSRRegistry.ts +0 -2
  279. package/lib/shared/registry/createNodeType.ts +7 -9
  280. package/lib/shared/registry/defineNodeType.ts +2 -6
  281. package/lib/shared/registry/fieldPresets.ts +3 -1
  282. package/lib/shared/registry/index.ts +0 -1
  283. package/lib/shared/registry/nodeTypes/ComponentInstanceNodeType.ts +14 -15
  284. package/lib/shared/registry/nodeTypes/CustomNodeType.ts +103 -0
  285. package/lib/shared/registry/nodeTypes/EmbedNodeType.ts +18 -11
  286. package/lib/shared/registry/nodeTypes/HtmlNodeType.ts +48 -19
  287. package/lib/shared/registry/nodeTypes/IslandNodeType.ts +129 -0
  288. package/lib/shared/registry/nodeTypes/LinkNodeType.ts +21 -19
  289. package/lib/shared/registry/nodeTypes/ListNodeType.ts +117 -77
  290. package/lib/shared/registry/nodeTypes/LocaleListNodeType.ts +27 -21
  291. package/lib/shared/registry/nodeTypes/MarkdownNodeType.ts +78 -0
  292. package/lib/shared/registry/nodeTypes/SlotMarkerType.ts +12 -8
  293. package/lib/shared/registry/nodeTypes/index.ts +26 -3
  294. package/lib/shared/responsiveScaling.test.ts +16 -34
  295. package/lib/shared/responsiveScaling.ts +61 -42
  296. package/lib/shared/responsiveStyleUtils.test.ts +0 -1
  297. package/lib/shared/responsiveStyleUtils.ts +11 -13
  298. package/lib/shared/richtext/htmlToTiptap.test.ts +139 -130
  299. package/lib/shared/richtext/htmlToTiptap.ts +2 -4
  300. package/lib/shared/richtext/tiptapToHtml.test.ts +5 -6
  301. package/lib/shared/richtext/types.ts +1 -8
  302. package/lib/shared/slugTranslator.test.ts +13 -13
  303. package/lib/shared/slugTranslator.ts +12 -16
  304. package/lib/shared/slugify.ts +9 -15
  305. package/lib/shared/styleNodeUtils.test.ts +8 -8
  306. package/lib/shared/styleNodeUtils.ts +18 -20
  307. package/lib/shared/styleUtils.test.ts +87 -61
  308. package/lib/shared/styleUtils.ts +5 -6
  309. package/lib/shared/themeDefaults.test.ts +11 -14
  310. package/lib/shared/themeDefaults.ts +3 -4
  311. package/lib/shared/tree/PathBuilder.test.ts +63 -145
  312. package/lib/shared/tree/PathBuilder.ts +59 -47
  313. package/lib/shared/treePathUtils.test.ts +51 -12
  314. package/lib/shared/treePathUtils.ts +91 -60
  315. package/lib/shared/types/api.ts +105 -8
  316. package/lib/shared/types/cms.test.ts +34 -0
  317. package/lib/shared/types/cms.ts +90 -34
  318. package/lib/shared/types/comment.ts +49 -16
  319. package/lib/shared/types/components.ts +51 -25
  320. package/lib/shared/types/errors.test.ts +1 -6
  321. package/lib/shared/types/errors.ts +3 -7
  322. package/lib/shared/types/experiments.ts +28 -28
  323. package/lib/shared/types/index.ts +25 -2
  324. package/lib/shared/types/permissions.ts +139 -0
  325. package/lib/shared/types/styles.ts +0 -1
  326. package/lib/shared/types/variables.test.ts +4 -13
  327. package/lib/shared/types/variables.ts +51 -30
  328. package/lib/shared/types.ts +1 -2
  329. package/lib/shared/utilityClassConfig.ts +751 -321
  330. package/lib/shared/utilityClassMapper.durability.test.ts +117 -0
  331. package/lib/shared/utilityClassMapper.test.ts +433 -95
  332. package/lib/shared/utilityClassMapper.ts +322 -249
  333. package/lib/shared/utilityClassNames.test.ts +38 -0
  334. package/lib/shared/utilityClassNames.ts +458 -0
  335. package/lib/shared/utils.test.ts +2 -10
  336. package/lib/shared/utils.ts +19 -10
  337. package/lib/shared/validation/cmsValidators.ts +2 -1
  338. package/lib/shared/validation/commentValidators.test.ts +53 -0
  339. package/lib/shared/validation/commentValidators.ts +12 -1
  340. package/lib/shared/validation/index.ts +1 -0
  341. package/lib/shared/validation/permissionsValidators.test.ts +49 -0
  342. package/lib/shared/validation/permissionsValidators.ts +49 -0
  343. package/lib/shared/validation/propValidator.test.ts +19 -21
  344. package/lib/shared/validation/propValidator.ts +13 -18
  345. package/lib/shared/validation/schemas.test.ts +64 -32
  346. package/lib/shared/validation/schemas.ts +616 -345
  347. package/lib/shared/validation/validators.test.ts +3 -8
  348. package/lib/shared/validation/validators.ts +89 -68
  349. package/lib/shared/viewportUnits.integration.test.ts +14 -10
  350. package/lib/shared/viewportUnits.test.ts +24 -23
  351. package/lib/shared/viewportUnits.ts +12 -5
  352. package/lib/test-utils/dom-setup.ts +1 -1
  353. package/lib/test-utils/factories/ConsoleMockFactory.ts +10 -14
  354. package/lib/test-utils/factories/DomMockFactory.ts +17 -23
  355. package/lib/test-utils/factories/EventMockFactory.ts +7 -13
  356. package/lib/test-utils/factories/FetchMockFactory.ts +39 -57
  357. package/lib/test-utils/factories/ServerMockFactory.ts +6 -10
  358. package/lib/test-utils/factories/StoreMockFactory.ts +18 -29
  359. package/lib/test-utils/fixtures.ts +45 -45
  360. package/lib/test-utils/helpers/asyncHelpers.test.ts +15 -18
  361. package/lib/test-utils/helpers/asyncHelpers.ts +11 -20
  362. package/lib/test-utils/helpers.ts +1 -5
  363. package/lib/test-utils/index.ts +0 -4
  364. package/lib/test-utils/mockFactories.ts +13 -19
  365. package/lib/test-utils/mocks.ts +6 -4
  366. package/package.json +3 -5
  367. package/scripts/build-for-publish.mjs +2 -4
  368. package/scripts/build-meno-filter.ts +4 -7
  369. package/tsconfig.json +1 -0
  370. package/vite.config.ts +4 -4
  371. package/build-next.ts +0 -1361
  372. package/build-static.test.ts +0 -424
  373. package/build-static.ts +0 -1074
  374. package/dist/build-static.js +0 -36
  375. package/dist/chunks/chunk-2MHDV5BF.js +0 -251
  376. package/dist/chunks/chunk-2MHDV5BF.js.map +0 -7
  377. package/dist/chunks/chunk-AZQYF6KE.js +0 -559
  378. package/dist/chunks/chunk-AZQYF6KE.js.map +0 -7
  379. package/dist/chunks/chunk-GZHGVVW3.js +0 -322
  380. package/dist/chunks/chunk-GZHGVVW3.js.map +0 -7
  381. package/dist/chunks/chunk-H3GJ4H2U.js.map +0 -7
  382. package/dist/chunks/chunk-I7YIGZXT.js +0 -467
  383. package/dist/chunks/chunk-I7YIGZXT.js.map +0 -7
  384. package/dist/chunks/chunk-IGYR22T6.js +0 -6192
  385. package/dist/chunks/chunk-IGYR22T6.js.map +0 -7
  386. package/dist/chunks/chunk-JGP5A3Y5.js +0 -1136
  387. package/dist/chunks/chunk-JGP5A3Y5.js.map +0 -7
  388. package/dist/chunks/chunk-JGWFTO6P.js.map +0 -7
  389. package/dist/chunks/chunk-O3NAGJP4.js.map +0 -7
  390. package/dist/chunks/chunk-QB2LNO4W.js +0 -77
  391. package/dist/chunks/chunk-QB2LNO4W.js.map +0 -7
  392. package/dist/chunks/chunk-R6XHAFBF.js +0 -3821
  393. package/dist/chunks/chunk-R6XHAFBF.js.map +0 -7
  394. package/dist/chunks/chunk-UB44F4Z2.js.map +0 -7
  395. package/dist/chunks/chunk-WQFG7PAH.js.map +0 -7
  396. package/dist/chunks/chunk-X754AHS5.js.map +0 -7
  397. package/dist/chunks/chunk-YBLHKYFF.js.map +0 -7
  398. package/dist/chunks/configService-R3OGU2UD.js +0 -13
  399. package/dist/chunks/configService-R3OGU2UD.js.map +0 -7
  400. package/dist/chunks/constants-STK2YBIW.js +0 -46
  401. package/dist/chunks/constants-STK2YBIW.js.map +0 -7
  402. package/dist/chunks/fs-JGINUXGL.js.map +0 -7
  403. package/dist/entries/server-router.js +0 -67
  404. package/dist/entries/server-router.js.map +0 -7
  405. package/entries/server-router.tsx +0 -81
  406. package/lib/server/providers/fileSystemPageProvider.ts +0 -160
  407. package/lib/server/webflow/buildWebflow.ts +0 -635
  408. package/lib/server/webflow/index.ts +0 -23
  409. package/lib/server/webflow/nodeToWebflow.test.ts +0 -3170
  410. package/lib/server/webflow/nodeToWebflow.ts +0 -2435
  411. package/lib/server/webflow/styleMapper.test.ts +0 -389
  412. package/lib/server/webflow/styleMapper.ts +0 -695
  413. package/lib/server/webflow/templateWrapper.ts +0 -49
  414. package/lib/server/webflow/types.ts +0 -396
  415. /package/dist/{build-static.js.map → chunks/fs-G3ANWEFP.js.map} +0 -0
@@ -3,15 +3,14 @@
3
3
  * Handles page route requests with SSR, i18n, and CMS support
4
4
  */
5
5
 
6
- import { randomBytes } from 'crypto';
6
+ import { randomBytes } from 'node:crypto';
7
7
  import type { RouteContext } from './index';
8
8
  import { generateSSRHTML, type SSRHTMLResult } from '../ssrRenderer';
9
9
  import { getStaticFilePath } from '../../shared/pathUtils';
10
10
  import { parseJSON, loadI18nConfig } from '../jsonLoader';
11
- import { packagePaths, projectPaths } from '../projectContext';
11
+ import { packagePaths } from '../projectContext';
12
12
  import { parseLocaleFromPath } from '../../shared/i18n';
13
13
  import { buildSlugIndex, resolveSlugToPageId } from '../../shared/slugTranslator';
14
- import type { CMSItem } from '../../shared/types';
15
14
  import { generateErrorPage } from '../ssr/errorOverlay';
16
15
  import { cacheScript, hashContent } from '../scriptCache';
17
16
  import { readTextFile, fileExists, serveFile } from '../runtime';
@@ -40,11 +39,7 @@ function generateCspNonce(): string {
40
39
  /**
41
40
  * Handle page route requests
42
41
  */
43
- export async function handlePageRoute(
44
- url: URL,
45
- context: RouteContext,
46
- req?: Request
47
- ): Promise<Response | undefined> {
42
+ export async function handlePageRoute(url: URL, context: RouteContext, req?: Request): Promise<Response | undefined> {
48
43
  const { pageService, componentService, cmsService, injectLiveReload, isEditor, serverPort } = context;
49
44
  const pagePath = url.pathname;
50
45
  // Editor selection attributes (data-element-path, data-cms-context, ...).
@@ -88,17 +83,26 @@ export async function handlePageRoute(
88
83
  cmsMatch.item = draft;
89
84
  }
90
85
  }
91
- // Load template page content by file path
92
- const templatePageContent = await loadPageByFilePath(cmsMatch.pagePath);
86
+ // Load the CMS template page. PageService caches it at `/templates/<collection>`
87
+ // already converted to JSON — for astro projects the provider parses the
88
+ // `[slug].astro` dialect file into the JSON model there. Reading the raw file
89
+ // (loadPageByFilePath) only yields JSON in JSON-format projects; in astro
90
+ // projects it would hand parseJSON() raw `.astro` source and throw
91
+ // ("Content that should be valid JSON couldn't be parsed"). Fall back to the raw
92
+ // read for JSON-project edge cases (template filename ≠ collection id) / a cold cache.
93
+ const templatePageContent =
94
+ pageService.getPage(`/templates/${cmsMatch.collection}`) ?? (await loadPageByFilePath(cmsMatch.pagePath));
93
95
 
94
96
  if (templatePageContent) {
95
- // Convert absolute template path to URL path for client-side hydration
96
- // e.g., /Users/.../templates/posts.json -> /templates/posts
97
- const templatesDir = projectPaths.templates();
98
- const cmsTemplatePath = '/templates' + cmsMatch.pagePath
99
- .replace(templatesDir, '') // Remove templates directory prefix
100
- .replace(/\\/g, '/') // Normalize Windows backslashes
101
- .replace(/\.json$/, ''); // Remove .json extension
97
+ // The editor page-path of the CMS template `/templates/<collectionId>` — which
98
+ // is also the PageCache key for both formats (JSON provider scans templates/ to
99
+ // /templates/<stem>; AstroPageProvider maps [slug].astro to /templates/<cms.id>).
100
+ // The client (window.__MENO_CMS__.templatePath) reloads this on HMR, so it MUST be
101
+ // the cache key. Deriving it from cmsMatch.pagePath via string-stripping only works
102
+ // for JSON (a templates/<id>.json file); in astro pagePath is the absolute
103
+ // src/pages/<col>/[slug].astro, so stripping produced a bogus path → the canvas
104
+ // rendered the SSR'd page then 404'd on its first HMR/mount reload.
105
+ const cmsTemplatePath = `/templates/${cmsMatch.collection}`;
102
106
 
103
107
  try {
104
108
  // Parse page JSON
@@ -113,7 +117,7 @@ export async function handlePageRoute(
113
117
 
114
118
  // SSR preview mode: use external JS file (same pattern as static build)
115
119
  if (injectLiveReload) {
116
- const result = await generateSSRHTML({
120
+ const result = (await generateSSRHTML({
117
121
  pageData: typedPageData,
118
122
  globalComponents: globalComponentsRecord,
119
123
  pagePath,
@@ -125,14 +129,14 @@ export async function handlePageRoute(
125
129
  cmsService,
126
130
  cmsTemplatePath,
127
131
  pageLibraries: typedPageData.meta?.libraries,
128
- pageCustomCode: typedPageData.meta?.customCode,
132
+ pageCustomCode: typedPageData.meta?.customCode,
129
133
  injectLiveReload,
130
134
  injectEditorAttrs,
131
135
  isEditor,
132
136
  serverPort,
133
137
  returnSeparateJS: true,
134
138
  cspNonce,
135
- }) as SSRHTMLResult;
139
+ })) as SSRHTMLResult;
136
140
 
137
141
  let finalHtml = result.html;
138
142
  if (result.javascript) {
@@ -145,8 +149,8 @@ export async function handlePageRoute(
145
149
  headers: {
146
150
  'Content-Type': 'text/html; charset=utf-8',
147
151
  'Cache-Control': 'no-store, max-age=0',
148
- 'Pragma': 'no-cache',
149
- 'Expires': '0',
152
+ Pragma: 'no-cache',
153
+ Expires: '0',
150
154
  [CSP_NONCE_HEADER]: cspNonce,
151
155
  },
152
156
  });
@@ -175,8 +179,8 @@ export async function handlePageRoute(
175
179
  headers: {
176
180
  'Content-Type': 'text/html; charset=utf-8',
177
181
  'Cache-Control': 'no-store, max-age=0',
178
- 'Pragma': 'no-cache',
179
- 'Expires': '0',
182
+ Pragma: 'no-cache',
183
+ Expires: '0',
180
184
  [CSP_NONCE_HEADER]: cspNonce,
181
185
  },
182
186
  });
@@ -245,7 +249,7 @@ export async function handlePageRoute(
245
249
 
246
250
  // SSR preview mode: use external JS file (same pattern as static build)
247
251
  if (injectLiveReload) {
248
- const result = await generateSSRHTML({
252
+ const result = (await generateSSRHTML({
249
253
  pageData,
250
254
  globalComponents: globalComponentsRecord,
251
255
  pagePath,
@@ -255,14 +259,14 @@ export async function handlePageRoute(
255
259
  slugMappings,
256
260
  cmsService,
257
261
  pageLibraries: pageData.meta?.libraries,
258
- pageCustomCode: pageData.meta?.customCode,
262
+ pageCustomCode: pageData.meta?.customCode,
259
263
  injectLiveReload,
260
264
  injectEditorAttrs,
261
265
  isEditor,
262
266
  serverPort,
263
267
  returnSeparateJS: true,
264
268
  cspNonce,
265
- }) as SSRHTMLResult;
269
+ })) as SSRHTMLResult;
266
270
 
267
271
  let finalHtml = result.html;
268
272
  if (result.javascript) {
@@ -275,8 +279,8 @@ export async function handlePageRoute(
275
279
  headers: {
276
280
  'Content-Type': 'text/html; charset=utf-8',
277
281
  'Cache-Control': 'no-store, max-age=0',
278
- 'Pragma': 'no-cache',
279
- 'Expires': '0',
282
+ Pragma: 'no-cache',
283
+ Expires: '0',
280
284
  [CSP_NONCE_HEADER]: cspNonce,
281
285
  },
282
286
  });
@@ -303,8 +307,8 @@ export async function handlePageRoute(
303
307
  headers: {
304
308
  'Content-Type': 'text/html; charset=utf-8',
305
309
  'Cache-Control': 'no-store, max-age=0',
306
- 'Pragma': 'no-cache',
307
- 'Expires': '0',
310
+ Pragma: 'no-cache',
311
+ Expires: '0',
308
312
  [CSP_NONCE_HEADER]: cspNonce,
309
313
  },
310
314
  });
@@ -3,17 +3,22 @@
3
3
  * Serves static files and handles TypeScript/TSX file requests
4
4
  */
5
5
 
6
- import { join } from 'path';
7
- import { resolveProjectPath, resolvePackagePath, packagePaths, getProjectRoot, getPackageRoot } from '../projectContext';
6
+ import {
7
+ resolveProjectPath,
8
+ resolvePackagePath,
9
+ packagePaths,
10
+ getProjectRoot,
11
+ getPackageRoot,
12
+ } from '../projectContext';
8
13
  import { isPathWithinRoot } from '../../shared/pathSecurity';
9
14
  import { fileExists, serveFile, bundleFile } from '../runtime';
10
15
 
11
- export async function handleStaticRoute(url: URL, req?: Request): Promise<Response | undefined> {
16
+ export async function handleStaticRoute(url: URL, _req?: Request): Promise<Response | undefined> {
12
17
  // Handle client-router requests (both .js and .tsx)
13
18
  if (url.pathname === '/client-router.js' || url.pathname === '/client-router.tsx') {
14
19
  // Check for pre-bundled version first (Electron packaged mode)
15
20
  const preBundledPath = packagePaths.clientRouter().replace(/\.tsx$/, '.js');
16
- if (preBundledPath !== packagePaths.clientRouter() && await fileExists(preBundledPath)) {
21
+ if (preBundledPath !== packagePaths.clientRouter() && (await fileExists(preBundledPath))) {
17
22
  return serveFile(preBundledPath, {
18
23
  'Content-Type': 'application/javascript',
19
24
  'Cache-Control': 'no-cache, no-store, must-revalidate',
@@ -71,7 +76,14 @@ export async function handleStaticRoute(url: URL, req?: Request): Promise<Respon
71
76
  // Other static files (editor assets) resolve relative to package root
72
77
  let filePath: string;
73
78
  let rootPath: string;
74
- if (decodedPathname.startsWith('/fonts/') || decodedPathname.startsWith('/images/') || decodedPathname.startsWith('/icons/') || decodedPathname.startsWith('/assets/') || decodedPathname.startsWith('/libraries/') || decodedPathname.startsWith('/videos/')) {
79
+ if (
80
+ decodedPathname.startsWith('/fonts/') ||
81
+ decodedPathname.startsWith('/images/') ||
82
+ decodedPathname.startsWith('/icons/') ||
83
+ decodedPathname.startsWith('/assets/') ||
84
+ decodedPathname.startsWith('/libraries/') ||
85
+ decodedPathname.startsWith('/videos/')
86
+ ) {
75
87
  rootPath = getProjectRoot();
76
88
  filePath = resolveProjectPath(decodedPathname.slice(1)); // Remove leading /
77
89
  } else {
@@ -93,4 +105,3 @@ export async function handleStaticRoute(url: URL, req?: Request): Promise<Respon
93
105
 
94
106
  return undefined;
95
107
  }
96
-
@@ -20,14 +20,31 @@ export interface BundleOptions {
20
20
  throw?: boolean;
21
21
  }
22
22
 
23
+ /** The fields we read from a Bun build-log entry (`Bun.build` result `logs`). */
24
+ interface BunBuildLog {
25
+ message?: string;
26
+ position?: { file?: string; line?: number; column?: number; lineText?: string };
27
+ }
28
+
29
+ /** The fields we read from an esbuild diagnostic message (`error.errors[]`). */
30
+ interface EsbuildMessage {
31
+ text?: string;
32
+ location?: { file?: string; line?: number; column?: number; lineText?: string };
33
+ }
34
+
35
+ /** Structural shape of a thrown build error — Bun exposes `logs`, esbuild `errors`. */
36
+ interface BuildErrorLike {
37
+ logs?: BunBuildLog[];
38
+ errors?: EsbuildMessage[];
39
+ message?: string;
40
+ stack?: string;
41
+ }
42
+
23
43
  /**
24
44
  * Bundle a file entry point.
25
45
  * Returns the bundled code as a string.
26
46
  */
27
- export async function bundleFile(
28
- entrypoint: string,
29
- opts: BundleOptions = {},
30
- ): Promise<BundleResult> {
47
+ export async function bundleFile(entrypoint: string, opts: BundleOptions = {}): Promise<BundleResult> {
31
48
  if (isBun) {
32
49
  return bundleWithBun(entrypoint, opts);
33
50
  }
@@ -61,17 +78,14 @@ export async function validateJS(code: string): Promise<string | null> {
61
78
 
62
79
  // ── Bun implementations ──────────────────────────────────────────────
63
80
 
64
- async function bundleWithBun(
65
- entrypoint: string,
66
- opts: BundleOptions,
67
- ): Promise<BundleResult> {
81
+ async function bundleWithBun(entrypoint: string, opts: BundleOptions): Promise<BundleResult> {
68
82
  try {
69
83
  const result = await Bun.build({
70
84
  entrypoints: [entrypoint],
71
85
  target: opts.target || 'browser',
72
86
  format: opts.format || 'esm',
73
87
  minify: opts.minify ?? false,
74
- sourcemap: opts.sourcemap === true ? 'inline' : (opts.sourcemap || 'none'),
88
+ sourcemap: opts.sourcemap === true ? 'inline' : opts.sourcemap || 'none',
75
89
  throw: opts.throw ?? false,
76
90
  });
77
91
 
@@ -80,7 +94,7 @@ async function bundleWithBun(
80
94
  return { code, success: true, errors: [] };
81
95
  }
82
96
 
83
- const errors = (result.logs || []).map((log: any) => {
97
+ const errors = (result.logs || []).map((log) => {
84
98
  const parts: string[] = [];
85
99
  if (log.position?.file) parts.push(`File: ${log.position.file}`);
86
100
  if (log.position?.line) parts.push(`Line ${log.position.line}:${log.position.column || 0}`);
@@ -90,12 +104,13 @@ async function bundleWithBun(
90
104
  });
91
105
 
92
106
  return { code: '', success: false, errors };
93
- } catch (err: any) {
107
+ } catch (err) {
108
+ const be = err as BuildErrorLike;
94
109
  if (opts.throw) throw err;
95
110
 
96
111
  const errors: string[] = [];
97
- if (err.logs && Array.isArray(err.logs)) {
98
- for (const log of err.logs) {
112
+ if (be.logs && Array.isArray(be.logs)) {
113
+ for (const log of be.logs) {
99
114
  const parts: string[] = [];
100
115
  if (log.position?.line) parts.push(`Line ${log.position.line}:${log.position.column || 0}`);
101
116
  if (log.position?.lineText) parts.push(log.position.lineText);
@@ -103,7 +118,7 @@ async function bundleWithBun(
103
118
  errors.push(parts.length > 0 ? parts.join('\n') : String(log));
104
119
  }
105
120
  } else {
106
- errors.push(err.message || String(err));
121
+ errors.push(be.message || String(err));
107
122
  }
108
123
 
109
124
  return { code: '', success: false, errors };
@@ -111,8 +126,8 @@ async function bundleWithBun(
111
126
  }
112
127
 
113
128
  async function minifyWithBun(code: string): Promise<BundleResult> {
114
- const { writeFile, rm } = await import('fs/promises');
115
- const { join } = await import('path');
129
+ const { writeFile, rm: _rm } = await import('node:fs/promises');
130
+ const { join } = await import('node:path');
116
131
  const tempFile = join('/tmp', `meno-minify-${Date.now()}.js`);
117
132
 
118
133
  try {
@@ -124,36 +139,47 @@ async function minifyWithBun(code: string): Promise<BundleResult> {
124
139
  throw: true,
125
140
  });
126
141
 
127
- if (result.outputs.length > 0) {
128
- const minified = await result.outputs[0].text();
142
+ const firstOutput = result.outputs[0];
143
+ if (firstOutput) {
144
+ const minified = await firstOutput.text();
129
145
  return { code: minified, success: true, errors: [] };
130
146
  }
131
147
 
132
148
  return { code: '', success: false, errors: ['Minification produced no output'] };
133
- } catch (err: any) {
149
+ } catch (err) {
150
+ const be = err as BuildErrorLike;
134
151
  const { inspect } = await import('./fs');
135
152
  let details = '';
136
- if (err.logs && Array.isArray(err.logs)) {
137
- details = err.logs.map((log: any) => {
138
- const parts: string[] = [];
139
- if (log.position?.line) parts.push(`Line ${log.position.line}:${log.position.column || 0}`);
140
- if (log.position?.lineText) parts.push(log.position.lineText);
141
- if (log.message) parts.push(log.message);
142
- return parts.length > 0 ? parts.join('\n') : String(log);
143
- }).join('\n\n');
153
+ if (be.logs && Array.isArray(be.logs)) {
154
+ details = be.logs
155
+ .map((log: BunBuildLog) => {
156
+ const parts: string[] = [];
157
+ if (log.position?.line) parts.push(`Line ${log.position.line}:${log.position.column || 0}`);
158
+ if (log.position?.lineText) parts.push(log.position.lineText);
159
+ if (log.message) parts.push(log.message);
160
+ return parts.length > 0 ? parts.join('\n') : String(log);
161
+ })
162
+ .join('\n\n');
144
163
  }
145
164
  if (!details) {
146
- try { details = inspect(err); } catch { details = err.stack || err.message || String(err); }
165
+ try {
166
+ details = inspect(err);
167
+ } catch {
168
+ details = be.stack || be.message || String(err);
169
+ }
147
170
  }
148
171
  return { code: '', success: false, errors: [details] };
149
172
  } finally {
150
- try { const { rm } = await import('fs/promises'); await rm(tempFile, { force: true }); } catch {}
173
+ try {
174
+ const { rm } = await import('node:fs/promises');
175
+ await rm(tempFile, { force: true });
176
+ } catch {}
151
177
  }
152
178
  }
153
179
 
154
180
  async function validateWithBun(code: string): Promise<string | null> {
155
- const { writeFile, rm } = await import('fs/promises');
156
- const { join } = await import('path');
181
+ const { writeFile, rm } = await import('node:fs/promises');
182
+ const { join } = await import('node:path');
157
183
  const tempFile = join('/tmp', `meno-validate-${Date.now()}-${Math.random().toString(36).slice(2)}.js`);
158
184
 
159
185
  try {
@@ -164,24 +190,33 @@ async function validateWithBun(code: string): Promise<string | null> {
164
190
  throw: true,
165
191
  });
166
192
  return null; // Valid
167
- } catch (err: any) {
193
+ } catch (err) {
194
+ const be = err as BuildErrorLike;
168
195
  const { inspect } = await import('./fs');
169
196
  let details = '';
170
- if (err.logs && Array.isArray(err.logs)) {
171
- details = err.logs.map((log: any) => {
172
- const parts: string[] = [];
173
- if (log.position?.line) parts.push(`Line ${log.position.line}:${log.position.column || 0}`);
174
- if (log.position?.lineText) parts.push(log.position.lineText);
175
- if (log.message) parts.push(log.message);
176
- return parts.length > 0 ? parts.join('\n') : String(log);
177
- }).join('\n\n');
197
+ if (be.logs && Array.isArray(be.logs)) {
198
+ details = be.logs
199
+ .map((log: BunBuildLog) => {
200
+ const parts: string[] = [];
201
+ if (log.position?.line) parts.push(`Line ${log.position.line}:${log.position.column || 0}`);
202
+ if (log.position?.lineText) parts.push(log.position.lineText);
203
+ if (log.message) parts.push(log.message);
204
+ return parts.length > 0 ? parts.join('\n') : String(log);
205
+ })
206
+ .join('\n\n');
178
207
  }
179
208
  if (!details) {
180
- try { details = inspect(err); } catch { details = err.stack || err.message || String(err); }
209
+ try {
210
+ details = inspect(err);
211
+ } catch {
212
+ details = be.stack || be.message || String(err);
213
+ }
181
214
  }
182
215
  return details || 'Unknown JavaScript error';
183
216
  } finally {
184
- try { await rm(tempFile, { force: true }); } catch {}
217
+ try {
218
+ await rm(tempFile, { force: true });
219
+ } catch {}
185
220
  }
186
221
  }
187
222
 
@@ -191,10 +226,7 @@ async function getEsbuild() {
191
226
  return await import('esbuild');
192
227
  }
193
228
 
194
- async function bundleWithEsbuild(
195
- entrypoint: string,
196
- opts: BundleOptions,
197
- ): Promise<BundleResult> {
229
+ async function bundleWithEsbuild(entrypoint: string, opts: BundleOptions): Promise<BundleResult> {
198
230
  const esbuild = await getEsbuild();
199
231
 
200
232
  try {
@@ -205,23 +237,26 @@ async function bundleWithEsbuild(
205
237
  platform: opts.target === 'node' ? 'node' : 'browser',
206
238
  format: opts.format || 'esm',
207
239
  minify: opts.minify ?? false,
208
- sourcemap: opts.sourcemap === true ? 'inline' : (opts.sourcemap === 'inline' ? 'inline' : opts.sourcemap === 'external' ? true : false),
240
+ sourcemap:
241
+ opts.sourcemap === true ? 'inline' : opts.sourcemap === 'inline' ? 'inline' : opts.sourcemap === 'external',
209
242
  jsx: 'automatic',
210
243
  jsxImportSource: 'react',
211
244
  logLevel: 'silent',
212
245
  });
213
246
 
214
- if (result.outputFiles && result.outputFiles.length > 0) {
215
- return { code: result.outputFiles[0].text, success: true, errors: [] };
247
+ const firstOutputFile = result.outputFiles?.[0];
248
+ if (firstOutputFile) {
249
+ return { code: firstOutputFile.text, success: true, errors: [] };
216
250
  }
217
251
 
218
252
  return { code: '', success: false, errors: ['Build produced no output'] };
219
- } catch (err: any) {
253
+ } catch (err) {
254
+ const be = err as BuildErrorLike;
220
255
  if (opts.throw) throw err;
221
256
 
222
257
  const errors: string[] = [];
223
- if (err.errors && Array.isArray(err.errors)) {
224
- for (const e of err.errors) {
258
+ if (be.errors && Array.isArray(be.errors)) {
259
+ for (const e of be.errors) {
225
260
  const parts: string[] = [];
226
261
  if (e.location?.file) parts.push(`File: ${e.location.file}`);
227
262
  if (e.location?.line) parts.push(`Line ${e.location.line}:${e.location.column || 0}`);
@@ -230,7 +265,7 @@ async function bundleWithEsbuild(
230
265
  errors.push(parts.length > 0 ? parts.join('\n') : String(e));
231
266
  }
232
267
  } else {
233
- errors.push(err.message || String(err));
268
+ errors.push(be.message || String(err));
234
269
  }
235
270
 
236
271
  return { code: '', success: false, errors };
@@ -247,10 +282,11 @@ async function minifyWithEsbuild(code: string): Promise<BundleResult> {
247
282
  });
248
283
 
249
284
  return { code: result.code, success: true, errors: [] };
250
- } catch (err: any) {
285
+ } catch (err) {
286
+ const be = err as BuildErrorLike;
251
287
  const errors: string[] = [];
252
- if (err.errors && Array.isArray(err.errors)) {
253
- for (const e of err.errors) {
288
+ if (be.errors && Array.isArray(be.errors)) {
289
+ for (const e of be.errors) {
254
290
  const parts: string[] = [];
255
291
  if (e.location?.line) parts.push(`Line ${e.location.line}:${e.location.column || 0}`);
256
292
  if (e.location?.lineText) parts.push(e.location.lineText);
@@ -258,7 +294,7 @@ async function minifyWithEsbuild(code: string): Promise<BundleResult> {
258
294
  errors.push(parts.length > 0 ? parts.join('\n') : String(e));
259
295
  }
260
296
  } else {
261
- errors.push(err.message || String(err));
297
+ errors.push(be.message || String(err));
262
298
  }
263
299
 
264
300
  return { code: '', success: false, errors };
@@ -271,10 +307,11 @@ async function validateWithEsbuild(code: string): Promise<string | null> {
271
307
  try {
272
308
  await esbuild.transform(code, { loader: 'js' });
273
309
  return null; // Valid
274
- } catch (err: any) {
310
+ } catch (err) {
311
+ const be = err as BuildErrorLike;
275
312
  const errors: string[] = [];
276
- if (err.errors && Array.isArray(err.errors)) {
277
- for (const e of err.errors) {
313
+ if (be.errors && Array.isArray(be.errors)) {
314
+ for (const e of be.errors) {
278
315
  const parts: string[] = [];
279
316
  if (e.location?.line) parts.push(`Line ${e.location.line}:${e.location.column || 0}`);
280
317
  if (e.location?.lineText) parts.push(e.location.lineText);
@@ -282,7 +319,7 @@ async function validateWithEsbuild(code: string): Promise<string | null> {
282
319
  errors.push(parts.length > 0 ? parts.join('\n') : String(e));
283
320
  }
284
321
  } else {
285
- errors.push(err.message || String(err));
322
+ errors.push(be.message || String(err));
286
323
  }
287
324
 
288
325
  return errors.join('\n\n') || 'Unknown JavaScript error';
@@ -3,8 +3,8 @@
3
3
  * Uses Bun APIs when available, falls back to Node.js APIs.
4
4
  */
5
5
 
6
- import { dirname } from 'path';
7
- import { fileURLToPath } from 'url';
6
+ import { dirname } from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
8
 
9
9
  const isBun = typeof globalThis.Bun !== 'undefined';
10
10
 
@@ -14,7 +14,7 @@ export async function readTextFile(path: string): Promise<string> {
14
14
  if (isBun) {
15
15
  return Bun.file(path).text();
16
16
  }
17
- const { readFile } = await import('fs/promises');
17
+ const { readFile } = await import('node:fs/promises');
18
18
  return readFile(path, 'utf-8');
19
19
  }
20
20
 
@@ -22,7 +22,7 @@ export async function readJsonFile<T = unknown>(path: string): Promise<T> {
22
22
  if (isBun) {
23
23
  return Bun.file(path).json() as Promise<T>;
24
24
  }
25
- const { readFile } = await import('fs/promises');
25
+ const { readFile } = await import('node:fs/promises');
26
26
  const text = await readFile(path, 'utf-8');
27
27
  return JSON.parse(text) as T;
28
28
  }
@@ -33,7 +33,7 @@ export async function fileExists(path: string): Promise<boolean> {
33
33
  if (isBun) {
34
34
  return Bun.file(path).exists();
35
35
  }
36
- const { access } = await import('fs/promises');
36
+ const { access } = await import('node:fs/promises');
37
37
  try {
38
38
  await access(path);
39
39
  return true;
@@ -44,15 +44,12 @@ export async function fileExists(path: string): Promise<boolean> {
44
44
 
45
45
  // ── File writing ──────────────────────────────────────────────────────
46
46
 
47
- export async function writeFile(
48
- path: string,
49
- content: string | Uint8Array | ArrayBuffer,
50
- ): Promise<void> {
47
+ export async function writeFile(path: string, content: string | Uint8Array | ArrayBuffer): Promise<void> {
51
48
  if (isBun) {
52
49
  await Bun.write(path, content);
53
50
  return;
54
51
  }
55
- const { writeFile: fsWrite } = await import('fs/promises');
52
+ const { writeFile: fsWrite } = await import('node:fs/promises');
56
53
  if (typeof content === 'string') {
57
54
  await fsWrite(path, content, 'utf-8');
58
55
  } else if (content instanceof ArrayBuffer) {
@@ -103,17 +100,14 @@ export function getMimeType(filePath: string): string {
103
100
  return MIME_MAP[ext] || 'application/octet-stream';
104
101
  }
105
102
 
106
- export async function serveFile(
107
- path: string,
108
- headers?: Record<string, string>,
109
- ): Promise<Response> {
103
+ export async function serveFile(path: string, headers?: Record<string, string>): Promise<Response> {
110
104
  if (isBun) {
111
105
  return new Response(Bun.file(path), { headers });
112
106
  }
113
107
 
114
108
  // Node.js path: stream the file via Web ReadableStream
115
- const { createReadStream } = await import('fs');
116
- const { Readable } = await import('stream');
109
+ const { createReadStream } = await import('node:fs');
110
+ const { Readable } = await import('node:stream');
117
111
  const nodeStream = createReadStream(path);
118
112
  const webStream = Readable.toWeb(nodeStream) as unknown as ReadableStream;
119
113
 
@@ -132,7 +126,7 @@ export function hashContent(content: string): string {
132
126
  if (isBun) {
133
127
  return Bun.hash(content).toString(16).slice(0, 8);
134
128
  }
135
- const { createHash } = require('crypto') as typeof import('crypto');
129
+ const { createHash } = require('node:crypto') as typeof import('crypto');
136
130
  return createHash('sha256').update(content).digest('hex').slice(0, 8);
137
131
  }
138
132
 
@@ -142,14 +136,14 @@ export function inspect(value: unknown): string {
142
136
  if (isBun) {
143
137
  return Bun.inspect(value);
144
138
  }
145
- const { inspect: nodeInspect } = require('util') as typeof import('util');
139
+ const { inspect: nodeInspect } = require('node:util') as typeof import('util');
146
140
  return nodeInspect(value, { depth: 4 });
147
141
  }
148
142
 
149
143
  // ── Directory helpers ─────────────────────────────────────────────────
150
144
 
151
145
  export async function ensureDir(path: string): Promise<void> {
152
- const { mkdir } = await import('fs/promises');
146
+ const { mkdir } = await import('node:fs/promises');
153
147
  await mkdir(path, { recursive: true });
154
148
  }
155
149
 
@@ -189,15 +183,11 @@ export async function spawnProcess(
189
183
  return { exitCode };
190
184
  }
191
185
 
192
- const { spawn } = await import('child_process');
186
+ const { spawn } = await import('node:child_process');
193
187
  return new Promise((resolve, reject) => {
194
188
  const child = spawn(cmd, args, {
195
189
  cwd: opts?.cwd,
196
- stdio: [
197
- 'ignore',
198
- opts?.stdout === 'pipe' ? 'pipe' : 'inherit',
199
- opts?.stderr === 'pipe' ? 'pipe' : 'inherit',
200
- ],
190
+ stdio: ['ignore', opts?.stdout === 'pipe' ? 'pipe' : 'inherit', opts?.stderr === 'pipe' ? 'pipe' : 'inherit'],
201
191
  });
202
192
 
203
193
  let stdout = '';
@@ -227,7 +217,7 @@ export async function getFileSize(path: string): Promise<number> {
227
217
  if (isBun) {
228
218
  return Bun.file(path).size;
229
219
  }
230
- const { stat } = await import('fs/promises');
220
+ const { stat } = await import('node:fs/promises');
231
221
  const stats = await stat(path);
232
222
  return stats.size;
233
223
  }