@jasonshimmy/vite-plugin-cer-app 0.23.2 → 0.25.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 (404) hide show
  1. package/dist/cli/adapters/netlify.js +4 -2
  2. package/dist/cli/adapters/netlify.js.map +1 -1
  3. package/dist/cli/checks/lighthouse.d.ts +26 -0
  4. package/dist/cli/checks/lighthouse.d.ts.map +1 -0
  5. package/dist/cli/checks/lighthouse.js +121 -0
  6. package/dist/cli/checks/lighthouse.js.map +1 -0
  7. package/dist/cli/checks/links.d.ts +12 -0
  8. package/dist/cli/checks/links.d.ts.map +1 -0
  9. package/dist/cli/checks/links.js +89 -0
  10. package/dist/cli/checks/links.js.map +1 -0
  11. package/dist/cli/checks/performance.d.ts +17 -0
  12. package/dist/cli/checks/performance.d.ts.map +1 -0
  13. package/dist/cli/checks/performance.js +61 -0
  14. package/dist/cli/checks/performance.js.map +1 -0
  15. package/dist/cli/commands/check.d.ts +3 -0
  16. package/dist/cli/commands/check.d.ts.map +1 -0
  17. package/dist/cli/commands/check.js +85 -0
  18. package/dist/cli/commands/check.js.map +1 -0
  19. package/dist/cli/commands/preview.d.ts.map +1 -1
  20. package/dist/cli/commands/preview.js +4 -2
  21. package/dist/cli/commands/preview.js.map +1 -1
  22. package/dist/cli/create/index.d.ts +11 -1
  23. package/dist/cli/create/index.d.ts.map +1 -1
  24. package/dist/cli/create/index.js +135 -65
  25. package/dist/cli/create/index.js.map +1 -1
  26. package/dist/cli/create/templates/spa/package.json.tpl +5 -3
  27. package/dist/cli/create/templates/ssg/cer.config.ts.tpl +2 -0
  28. package/dist/cli/create/templates/ssg/package.json.tpl +5 -3
  29. package/dist/cli/create/templates/ssr/package.json.tpl +5 -3
  30. package/dist/cli/index.js +2 -0
  31. package/dist/cli/index.js.map +1 -1
  32. package/dist/index.d.ts +4 -2
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/plugin/build-ssg.d.ts +22 -6
  35. package/dist/plugin/build-ssg.d.ts.map +1 -1
  36. package/dist/plugin/build-ssg.js +226 -17
  37. package/dist/plugin/build-ssg.js.map +1 -1
  38. package/dist/plugin/content/index.d.ts +1 -1
  39. package/dist/plugin/content/index.d.ts.map +1 -1
  40. package/dist/plugin/content/index.js +8 -8
  41. package/dist/plugin/content/index.js.map +1 -1
  42. package/dist/plugin/content/parser.d.ts +3 -3
  43. package/dist/plugin/content/parser.d.ts.map +1 -1
  44. package/dist/plugin/content/parser.js +103 -24
  45. package/dist/plugin/content/parser.js.map +1 -1
  46. package/dist/plugin/dev-server.d.ts +4 -1
  47. package/dist/plugin/dev-server.d.ts.map +1 -1
  48. package/dist/plugin/dev-server.js.map +1 -1
  49. package/dist/plugin/dts-generator.d.ts.map +1 -1
  50. package/dist/plugin/dts-generator.js +50 -8
  51. package/dist/plugin/dts-generator.js.map +1 -1
  52. package/dist/plugin/generated-dir.d.ts +2 -0
  53. package/dist/plugin/generated-dir.d.ts.map +1 -1
  54. package/dist/plugin/generated-dir.js +17 -6
  55. package/dist/plugin/generated-dir.js.map +1 -1
  56. package/dist/plugin/html-post-process.d.ts +7 -0
  57. package/dist/plugin/html-post-process.d.ts.map +1 -1
  58. package/dist/plugin/html-post-process.js +26 -0
  59. package/dist/plugin/html-post-process.js.map +1 -1
  60. package/dist/plugin/index.d.ts.map +1 -1
  61. package/dist/plugin/index.js +60 -13
  62. package/dist/plugin/index.js.map +1 -1
  63. package/dist/plugin/transforms/auto-import.d.ts.map +1 -1
  64. package/dist/plugin/transforms/auto-import.js +7 -0
  65. package/dist/plugin/transforms/auto-import.js.map +1 -1
  66. package/dist/plugin/transforms/prune-runtime-css.d.ts +8 -0
  67. package/dist/plugin/transforms/prune-runtime-css.d.ts.map +1 -0
  68. package/dist/plugin/transforms/prune-runtime-css.js +40 -0
  69. package/dist/plugin/transforms/prune-runtime-css.js.map +1 -0
  70. package/dist/runtime/app-template.d.ts +1 -1
  71. package/dist/runtime/app-template.d.ts.map +1 -1
  72. package/dist/runtime/app-template.js +206 -36
  73. package/dist/runtime/app-template.js.map +1 -1
  74. package/dist/runtime/composables/index.d.ts +4 -0
  75. package/dist/runtime/composables/index.d.ts.map +1 -1
  76. package/dist/runtime/composables/index.js +2 -0
  77. package/dist/runtime/composables/index.js.map +1 -1
  78. package/dist/runtime/composables/use-active-headings.d.ts +24 -0
  79. package/dist/runtime/composables/use-active-headings.d.ts.map +1 -0
  80. package/dist/runtime/composables/use-active-headings.js +112 -0
  81. package/dist/runtime/composables/use-active-headings.js.map +1 -0
  82. package/dist/runtime/composables/use-content-page.d.ts +45 -0
  83. package/dist/runtime/composables/use-content-page.d.ts.map +1 -0
  84. package/dist/runtime/composables/use-content-page.js +181 -0
  85. package/dist/runtime/composables/use-content-page.js.map +1 -0
  86. package/dist/runtime/composables/use-content-search.d.ts.map +1 -1
  87. package/dist/runtime/composables/use-content-search.js +1 -5
  88. package/dist/runtime/composables/use-content-search.js.map +1 -1
  89. package/dist/runtime/composables/use-fetch.d.ts +2 -1
  90. package/dist/runtime/composables/use-fetch.d.ts.map +1 -1
  91. package/dist/runtime/composables/use-fetch.js +112 -43
  92. package/dist/runtime/composables/use-fetch.js.map +1 -1
  93. package/dist/runtime/composables/use-route.d.ts.map +1 -1
  94. package/dist/runtime/composables/use-route.js +39 -11
  95. package/dist/runtime/composables/use-route.js.map +1 -1
  96. package/dist/runtime/content/client.js +2 -2
  97. package/dist/runtime/content/client.js.map +1 -1
  98. package/dist/runtime/entry-server-template.d.ts +16 -1
  99. package/dist/runtime/entry-server-template.d.ts.map +1 -1
  100. package/dist/runtime/entry-server-template.js +120 -13
  101. package/dist/runtime/entry-server-template.js.map +1 -1
  102. package/dist/types/config.d.ts +45 -4
  103. package/dist/types/config.d.ts.map +1 -1
  104. package/dist/types/config.js.map +1 -1
  105. package/dist/types/content.d.ts +18 -1
  106. package/dist/types/content.d.ts.map +1 -1
  107. package/dist/types/middleware.d.ts +2 -2
  108. package/dist/types/middleware.d.ts.map +1 -1
  109. package/package.json +22 -19
  110. package/.github/copilot-instructions.md +0 -169
  111. package/.github/workflows/publish.yml +0 -257
  112. package/.nvmrc +0 -1
  113. package/CHANGELOG.md +0 -236
  114. package/CLAUDE.md +0 -113
  115. package/commits.txt +0 -1
  116. package/cypress.config.ts +0 -16
  117. package/docs/authentication.md +0 -285
  118. package/docs/cli.md +0 -324
  119. package/docs/components.md +0 -237
  120. package/docs/composables.md +0 -907
  121. package/docs/configuration.md +0 -696
  122. package/docs/content.md +0 -570
  123. package/docs/data-loading.md +0 -336
  124. package/docs/getting-started.md +0 -237
  125. package/docs/head-management.md +0 -212
  126. package/docs/i18n.md +0 -159
  127. package/docs/layouts.md +0 -224
  128. package/docs/middleware.md +0 -234
  129. package/docs/plugins.md +0 -170
  130. package/docs/rendering-modes.md +0 -377
  131. package/docs/routing.md +0 -485
  132. package/docs/server-api.md +0 -253
  133. package/docs/testing.md +0 -455
  134. package/docs/use-fetch.md +0 -183
  135. package/e2e/cypress/e2e/api.cy.ts +0 -123
  136. package/e2e/cypress/e2e/async-component.cy.ts +0 -27
  137. package/e2e/cypress/e2e/component-splitting.cy.ts +0 -50
  138. package/e2e/cypress/e2e/content.cy.ts +0 -425
  139. package/e2e/cypress/e2e/cookie.cy.ts +0 -85
  140. package/e2e/cypress/e2e/data.cy.ts +0 -158
  141. package/e2e/cypress/e2e/error-boundary.cy.ts +0 -88
  142. package/e2e/cypress/e2e/fouc.cy.ts +0 -254
  143. package/e2e/cypress/e2e/group-meta.cy.ts +0 -36
  144. package/e2e/cypress/e2e/head.cy.ts +0 -89
  145. package/e2e/cypress/e2e/i18n.cy.ts +0 -79
  146. package/e2e/cypress/e2e/interactive.cy.ts +0 -137
  147. package/e2e/cypress/e2e/isr-nested-runtime.cy.ts +0 -102
  148. package/e2e/cypress/e2e/jit-css-custom-colors.cy.ts +0 -43
  149. package/e2e/cypress/e2e/middleware-chain.cy.ts +0 -89
  150. package/e2e/cypress/e2e/middleware-status.cy.ts +0 -30
  151. package/e2e/cypress/e2e/middleware.cy.ts +0 -45
  152. package/e2e/cypress/e2e/navigate.cy.ts +0 -39
  153. package/e2e/cypress/e2e/observability.cy.ts +0 -77
  154. package/e2e/cypress/e2e/per-route-error.cy.ts +0 -42
  155. package/e2e/cypress/e2e/per-route-render.cy.ts +0 -70
  156. package/e2e/cypress/e2e/preview-hardening.cy.ts +0 -88
  157. package/e2e/cypress/e2e/routes.cy.ts +0 -128
  158. package/e2e/cypress/e2e/seo-meta.cy.ts +0 -108
  159. package/e2e/cypress/e2e/server-middleware.cy.ts +0 -46
  160. package/e2e/cypress/e2e/session-rotation.cy.ts +0 -25
  161. package/e2e/cypress/e2e/session.cy.ts +0 -73
  162. package/e2e/cypress/e2e/ssr-render-error.cy.ts +0 -68
  163. package/e2e/cypress/e2e/synthetic-404.cy.ts +0 -45
  164. package/e2e/cypress/e2e/use-page-data.cy.ts +0 -122
  165. package/e2e/cypress/e2e/use-state.cy.ts +0 -138
  166. package/e2e/cypress/support/commands.ts +0 -120
  167. package/e2e/cypress/support/e2e.ts +0 -10
  168. package/e2e/cypress/tsconfig.json +0 -14
  169. package/e2e/kitchen-sink/app/components/ks-badge.ts +0 -8
  170. package/e2e/kitchen-sink/app/composables/useKsCounter.ts +0 -9
  171. package/e2e/kitchen-sink/app/error.ts +0 -18
  172. package/e2e/kitchen-sink/app/layouts/admin.ts +0 -13
  173. package/e2e/kitchen-sink/app/layouts/default.ts +0 -25
  174. package/e2e/kitchen-sink/app/layouts/group.ts +0 -9
  175. package/e2e/kitchen-sink/app/layouts/minimal.ts +0 -7
  176. package/e2e/kitchen-sink/app/loading.ts +0 -9
  177. package/e2e/kitchen-sink/app/middleware/auth.ts +0 -9
  178. package/e2e/kitchen-sink/app/middleware/custom-log.ts +0 -4
  179. package/e2e/kitchen-sink/app/middleware/group-auth.ts +0 -7
  180. package/e2e/kitchen-sink/app/middleware/logger.ts +0 -14
  181. package/e2e/kitchen-sink/app/pages/(auth)/login.ts +0 -13
  182. package/e2e/kitchen-sink/app/pages/(auth)/protected.ts +0 -16
  183. package/e2e/kitchen-sink/app/pages/404.ts +0 -9
  184. package/e2e/kitchen-sink/app/pages/about.ts +0 -17
  185. package/e2e/kitchen-sink/app/pages/admin/_layout.ts +0 -1
  186. package/e2e/kitchen-sink/app/pages/admin/dashboard.ts +0 -11
  187. package/e2e/kitchen-sink/app/pages/async-component-error-test.ts +0 -18
  188. package/e2e/kitchen-sink/app/pages/async-component-test.ts +0 -18
  189. package/e2e/kitchen-sink/app/pages/blog/[slug].ts +0 -59
  190. package/e2e/kitchen-sink/app/pages/blog/index.ts +0 -51
  191. package/e2e/kitchen-sink/app/pages/content-blog.ts +0 -37
  192. package/e2e/kitchen-sink/app/pages/content-doc.ts +0 -42
  193. package/e2e/kitchen-sink/app/pages/content-fallback.ts +0 -36
  194. package/e2e/kitchen-sink/app/pages/content-guides.ts +0 -35
  195. package/e2e/kitchen-sink/app/pages/content-index.ts +0 -39
  196. package/e2e/kitchen-sink/app/pages/content-search.ts +0 -36
  197. package/e2e/kitchen-sink/app/pages/cookie-test.ts +0 -22
  198. package/e2e/kitchen-sink/app/pages/counter.ts +0 -17
  199. package/e2e/kitchen-sink/app/pages/group-auth-blocked.ts +0 -9
  200. package/e2e/kitchen-sink/app/pages/group-meta-test/_layout.ts +0 -6
  201. package/e2e/kitchen-sink/app/pages/group-meta-test/custom-mw.ts +0 -14
  202. package/e2e/kitchen-sink/app/pages/group-meta-test/page.ts +0 -9
  203. package/e2e/kitchen-sink/app/pages/group-meta-test/protected.ts +0 -8
  204. package/e2e/kitchen-sink/app/pages/head.ts +0 -20
  205. package/e2e/kitchen-sink/app/pages/i18n-test.ts +0 -14
  206. package/e2e/kitchen-sink/app/pages/index.ts +0 -27
  207. package/e2e/kitchen-sink/app/pages/isr-test.ts +0 -17
  208. package/e2e/kitchen-sink/app/pages/items/[id].ts +0 -20
  209. package/e2e/kitchen-sink/app/pages/jit-css-custom-colors-test.ts +0 -14
  210. package/e2e/kitchen-sink/app/pages/loader-error-test.ts +0 -13
  211. package/e2e/kitchen-sink/app/pages/loader-props-test.ts +0 -19
  212. package/e2e/kitchen-sink/app/pages/loader-response-error-test.ts +0 -13
  213. package/e2e/kitchen-sink/app/pages/middleware-chain-test.ts +0 -12
  214. package/e2e/kitchen-sink/app/pages/middleware-status-test.ts +0 -9
  215. package/e2e/kitchen-sink/app/pages/navigate-test.ts +0 -16
  216. package/e2e/kitchen-sink/app/pages/observability-test.ts +0 -25
  217. package/e2e/kitchen-sink/app/pages/per-route-error-test.error.ts +0 -13
  218. package/e2e/kitchen-sink/app/pages/per-route-error-test.ts +0 -15
  219. package/e2e/kitchen-sink/app/pages/plugin-dsd-test.ts +0 -10
  220. package/e2e/kitchen-sink/app/pages/render-error-test.ts +0 -12
  221. package/e2e/kitchen-sink/app/pages/render-server-test.ts +0 -12
  222. package/e2e/kitchen-sink/app/pages/render-spa-test.ts +0 -12
  223. package/e2e/kitchen-sink/app/pages/route-info.ts +0 -14
  224. package/e2e/kitchen-sink/app/pages/seo-test.ts +0 -23
  225. package/e2e/kitchen-sink/app/pages/session-rotation-test.ts +0 -25
  226. package/e2e/kitchen-sink/app/pages/use-state-test.ts +0 -37
  227. package/e2e/kitchen-sink/app/plugins/01.setup.ts +0 -7
  228. package/e2e/kitchen-sink/app/plugins/02.ks-plugin-components.ts +0 -27
  229. package/e2e/kitchen-sink/cer-auto-imports.d.ts +0 -51
  230. package/e2e/kitchen-sink/cer-env.d.ts +0 -35
  231. package/e2e/kitchen-sink/cer-tsconfig.json +0 -30
  232. package/e2e/kitchen-sink/cer.config.ts +0 -43
  233. package/e2e/kitchen-sink/content/01.guides/01.index.md +0 -8
  234. package/e2e/kitchen-sink/content/01.guides/02.intro.md +0 -8
  235. package/e2e/kitchen-sink/content/01.guides/10.advanced.md +0 -8
  236. package/e2e/kitchen-sink/content/blog/2026-04-01-hello.md +0 -26
  237. package/e2e/kitchen-sink/content/blog/2026-04-02-draft.md +0 -10
  238. package/e2e/kitchen-sink/content/blog/index.md +0 -8
  239. package/e2e/kitchen-sink/content/blog/no-frontmatter.md +0 -7
  240. package/e2e/kitchen-sink/content/docs/getting-started.md +0 -48
  241. package/e2e/kitchen-sink/content/index.md +0 -16
  242. package/e2e/kitchen-sink/server/api/echo.ts +0 -12
  243. package/e2e/kitchen-sink/server/api/health.ts +0 -3
  244. package/e2e/kitchen-sink/server/api/posts/[slug].ts +0 -11
  245. package/e2e/kitchen-sink/server/api/posts/index.ts +0 -5
  246. package/e2e/kitchen-sink/server/api/session.ts +0 -23
  247. package/e2e/kitchen-sink/server/data/posts.ts +0 -21
  248. package/e2e/kitchen-sink/server/middleware/01-headers.ts +0 -6
  249. package/e2e/kitchen-sink/server/middleware/02-status-test.ts +0 -10
  250. package/e2e/kitchen-sink/tsconfig.json +0 -3
  251. package/e2e/scripts/clean.mjs +0 -14
  252. package/eslint.config.ts +0 -22
  253. package/src/__tests__/cli/adapters/cloudflare-worker.integration.test.ts +0 -132
  254. package/src/__tests__/cli/adapters/cloudflare.test.ts +0 -332
  255. package/src/__tests__/cli/adapters/netlify-bridge.integration.test.ts +0 -139
  256. package/src/__tests__/cli/adapters/netlify.test.ts +0 -286
  257. package/src/__tests__/cli/adapters/vercel-launcher.integration.test.ts +0 -129
  258. package/src/__tests__/cli/adapters/vercel.test.ts +0 -263
  259. package/src/__tests__/cli/preview-hardening.test.ts +0 -265
  260. package/src/__tests__/cli/preview-isr.test.ts +0 -320
  261. package/src/__tests__/index.test.ts +0 -21
  262. package/src/__tests__/plugin/app-template.test.ts +0 -166
  263. package/src/__tests__/plugin/build-ssg-render.test.ts +0 -155
  264. package/src/__tests__/plugin/build-ssg.test.ts +0 -598
  265. package/src/__tests__/plugin/build-ssr.test.ts +0 -192
  266. package/src/__tests__/plugin/cer-app-plugin.test.ts +0 -552
  267. package/src/__tests__/plugin/content/emitter.test.ts +0 -117
  268. package/src/__tests__/plugin/content/loader.test.ts +0 -154
  269. package/src/__tests__/plugin/content/parser.test.ts +0 -381
  270. package/src/__tests__/plugin/content/path-utils.test.ts +0 -69
  271. package/src/__tests__/plugin/content/search.test.ts +0 -119
  272. package/src/__tests__/plugin/dev-server.test.ts +0 -813
  273. package/src/__tests__/plugin/dts-generator.test.ts +0 -394
  274. package/src/__tests__/plugin/entry-server-template.test.ts +0 -385
  275. package/src/__tests__/plugin/generated-dir.test.ts +0 -144
  276. package/src/__tests__/plugin/html-post-process.test.ts +0 -146
  277. package/src/__tests__/plugin/path-utils.test.ts +0 -411
  278. package/src/__tests__/plugin/resolve-config.test.ts +0 -233
  279. package/src/__tests__/plugin/scanner.test.ts +0 -186
  280. package/src/__tests__/plugin/transforms/auto-import.test.ts +0 -510
  281. package/src/__tests__/plugin/transforms/head-inject.test.ts +0 -178
  282. package/src/__tests__/plugin/virtual/composables.test.ts +0 -57
  283. package/src/__tests__/plugin/virtual/content-components.test.ts +0 -66
  284. package/src/__tests__/plugin/virtual/error.test.ts +0 -71
  285. package/src/__tests__/plugin/virtual/layouts.test.ts +0 -70
  286. package/src/__tests__/plugin/virtual/loading.test.ts +0 -72
  287. package/src/__tests__/plugin/virtual/middleware.test.ts +0 -83
  288. package/src/__tests__/plugin/virtual/plugins.test.ts +0 -129
  289. package/src/__tests__/plugin/virtual/routes.test.ts +0 -884
  290. package/src/__tests__/plugin/virtual/server-api.test.ts +0 -164
  291. package/src/__tests__/plugin/virtual/server-middleware.test.ts +0 -102
  292. package/src/__tests__/runtime/app-template.test.ts +0 -208
  293. package/src/__tests__/runtime/define-middleware.test.ts +0 -64
  294. package/src/__tests__/runtime/define-server-middleware.test.ts +0 -54
  295. package/src/__tests__/runtime/entry-client-template.test.ts +0 -61
  296. package/src/__tests__/runtime/isr-handler.test.ts +0 -338
  297. package/src/__tests__/runtime/oauth/handler.test.ts +0 -358
  298. package/src/__tests__/runtime/oauth/providers.test.ts +0 -47
  299. package/src/__tests__/runtime/oauth-index.test.ts +0 -43
  300. package/src/__tests__/runtime/use-auth.test.ts +0 -169
  301. package/src/__tests__/runtime/use-content-search-composable.test.ts +0 -405
  302. package/src/__tests__/runtime/use-content-search.test.ts +0 -163
  303. package/src/__tests__/runtime/use-content.test.ts +0 -226
  304. package/src/__tests__/runtime/use-cookie.test.ts +0 -277
  305. package/src/__tests__/runtime/use-fetch-component.test.ts +0 -214
  306. package/src/__tests__/runtime/use-fetch.test.ts +0 -377
  307. package/src/__tests__/runtime/use-head.test.ts +0 -311
  308. package/src/__tests__/runtime/use-inject-client.test.ts +0 -67
  309. package/src/__tests__/runtime/use-inject.test.ts +0 -66
  310. package/src/__tests__/runtime/use-locale.test.ts +0 -152
  311. package/src/__tests__/runtime/use-navigate.test.ts +0 -121
  312. package/src/__tests__/runtime/use-page-data.test.ts +0 -298
  313. package/src/__tests__/runtime/use-route.test.ts +0 -156
  314. package/src/__tests__/runtime/use-runtime-config.test.ts +0 -182
  315. package/src/__tests__/runtime/use-seo-meta.test.ts +0 -109
  316. package/src/__tests__/runtime/use-session.test.ts +0 -320
  317. package/src/__tests__/runtime/use-state.test.ts +0 -340
  318. package/src/__tests__/types/config.test.ts +0 -18
  319. package/src/cli/adapters/cloudflare.ts +0 -335
  320. package/src/cli/adapters/netlify.ts +0 -326
  321. package/src/cli/adapters/vercel.ts +0 -311
  322. package/src/cli/commands/adapt.ts +0 -84
  323. package/src/cli/commands/build.ts +0 -165
  324. package/src/cli/commands/dev.ts +0 -125
  325. package/src/cli/commands/generate.ts +0 -91
  326. package/src/cli/commands/preview-isr.ts +0 -172
  327. package/src/cli/commands/preview.ts +0 -523
  328. package/src/cli/create/index.ts +0 -275
  329. package/src/cli/create/templates/shared/.gitignore.tpl +0 -25
  330. package/src/cli/create/templates/shared/app/layouts/default.ts.tpl +0 -15
  331. package/src/cli/create/templates/shared/app/pages/index.ts.tpl +0 -8
  332. package/src/cli/create/templates/shared/index.html.tpl +0 -12
  333. package/src/cli/create/templates/shared/tsconfig.json.tpl +0 -6
  334. package/src/cli/create/templates/spa/cer.config.ts.tpl +0 -6
  335. package/src/cli/create/templates/spa/package.json.tpl +0 -18
  336. package/src/cli/create/templates/ssg/cer.config.ts.tpl +0 -10
  337. package/src/cli/create/templates/ssg/package.json.tpl +0 -19
  338. package/src/cli/create/templates/ssr/cer.config.ts.tpl +0 -6
  339. package/src/cli/create/templates/ssr/package.json.tpl +0 -18
  340. package/src/cli/index.ts +0 -22
  341. package/src/index.ts +0 -20
  342. package/src/plugin/build-ssg.ts +0 -403
  343. package/src/plugin/build-ssr.ts +0 -134
  344. package/src/plugin/content/emitter.ts +0 -50
  345. package/src/plugin/content/index.ts +0 -233
  346. package/src/plugin/content/parser.ts +0 -259
  347. package/src/plugin/content/path-utils.ts +0 -55
  348. package/src/plugin/content/scanner.ts +0 -26
  349. package/src/plugin/content/search.ts +0 -28
  350. package/src/plugin/dev-server.ts +0 -379
  351. package/src/plugin/dts-generator.ts +0 -273
  352. package/src/plugin/generated-dir.ts +0 -121
  353. package/src/plugin/html-post-process.ts +0 -96
  354. package/src/plugin/index.ts +0 -584
  355. package/src/plugin/path-utils.ts +0 -186
  356. package/src/plugin/scanner.ts +0 -65
  357. package/src/plugin/transforms/auto-import.ts +0 -206
  358. package/src/plugin/transforms/head-inject.ts +0 -161
  359. package/src/plugin/virtual/composables.ts +0 -28
  360. package/src/plugin/virtual/content-components.ts +0 -83
  361. package/src/plugin/virtual/error.ts +0 -34
  362. package/src/plugin/virtual/layouts.ts +0 -41
  363. package/src/plugin/virtual/loading.ts +0 -32
  364. package/src/plugin/virtual/middleware.ts +0 -45
  365. package/src/plugin/virtual/plugins.ts +0 -46
  366. package/src/plugin/virtual/routes.ts +0 -514
  367. package/src/plugin/virtual/server-api.ts +0 -85
  368. package/src/plugin/virtual/server-middleware.ts +0 -44
  369. package/src/runtime/app-template.ts +0 -377
  370. package/src/runtime/composables/define-middleware.ts +0 -17
  371. package/src/runtime/composables/define-server-middleware.ts +0 -18
  372. package/src/runtime/composables/index.ts +0 -27
  373. package/src/runtime/composables/use-auth.ts +0 -125
  374. package/src/runtime/composables/use-content-search.ts +0 -205
  375. package/src/runtime/composables/use-content.ts +0 -146
  376. package/src/runtime/composables/use-cookie.ts +0 -135
  377. package/src/runtime/composables/use-fetch.ts +0 -438
  378. package/src/runtime/composables/use-head.ts +0 -234
  379. package/src/runtime/composables/use-inject.ts +0 -49
  380. package/src/runtime/composables/use-locale.ts +0 -109
  381. package/src/runtime/composables/use-navigate.ts +0 -58
  382. package/src/runtime/composables/use-page-data.ts +0 -93
  383. package/src/runtime/composables/use-route.ts +0 -71
  384. package/src/runtime/composables/use-runtime-config.ts +0 -123
  385. package/src/runtime/composables/use-seo-meta.ts +0 -80
  386. package/src/runtime/composables/use-session.ts +0 -186
  387. package/src/runtime/composables/use-state.ts +0 -92
  388. package/src/runtime/content/client.ts +0 -168
  389. package/src/runtime/entry-client-template.ts +0 -39
  390. package/src/runtime/entry-server-template.ts +0 -493
  391. package/src/runtime/isr-handler.ts +0 -184
  392. package/src/runtime/oauth/handler.ts +0 -407
  393. package/src/runtime/oauth/index.ts +0 -49
  394. package/src/runtime/oauth/providers.ts +0 -38
  395. package/src/types/api.ts +0 -40
  396. package/src/types/config.ts +0 -379
  397. package/src/types/content.ts +0 -66
  398. package/src/types/index.ts +0 -7
  399. package/src/types/middleware.ts +0 -63
  400. package/src/types/page.ts +0 -117
  401. package/src/types/plugin.ts +0 -34
  402. package/tsconfig.build.json +0 -10
  403. package/tsconfig.json +0 -19
  404. package/vitest.config.ts +0 -33
@@ -1,320 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest'
2
- import type { IncomingMessage, ServerResponse } from 'node:http'
3
- import {
4
- isPathBounded,
5
- matchRoutePattern,
6
- findRevalidate,
7
- findRenderMode,
8
- renderForIsr,
9
- serveFromIsrCache,
10
- type IsrCacheEntry,
11
- } from '../../cli/commands/preview-isr.js'
12
-
13
- // ─── isPathBounded ────────────────────────────────────────────────────────────
14
-
15
- describe('isPathBounded', () => {
16
- it('allows normal file paths inside the root', () => {
17
- expect(isPathBounded('/dist', '/index.html')).toBe(true)
18
- })
19
-
20
- it('allows nested paths inside the root', () => {
21
- expect(isPathBounded('/dist', '/assets/app.js')).toBe(true)
22
- })
23
-
24
- it('allows the root path itself', () => {
25
- expect(isPathBounded('/dist', '/')).toBe(true)
26
- })
27
-
28
- it('blocks simple path traversal (../ escape)', () => {
29
- expect(isPathBounded('/dist', '/../../../../etc/passwd')).toBe(false)
30
- })
31
-
32
- it('blocks a path that escapes by one level', () => {
33
- expect(isPathBounded('/dist', '/../secret')).toBe(false)
34
- })
35
-
36
- it('does not confuse a sibling directory for the root', () => {
37
- // /dist-other starts with /dist but is NOT inside /dist
38
- expect(isPathBounded('/dist', '/../dist-other/file')).toBe(false)
39
- })
40
- })
41
-
42
- // ─── matchRoutePattern ────────────────────────────────────────────────────────
43
-
44
- describe('matchRoutePattern', () => {
45
- it('matches identical paths', () => {
46
- expect(matchRoutePattern('/about', '/about')).toBe(true)
47
- })
48
-
49
- it('matches root path', () => {
50
- expect(matchRoutePattern('/', '/')).toBe(true)
51
- })
52
-
53
- it('does not match different static paths', () => {
54
- expect(matchRoutePattern('/about', '/contact')).toBe(false)
55
- })
56
-
57
- it('matches :param segments', () => {
58
- expect(matchRoutePattern('/blog/:slug', '/blog/hello-world')).toBe(true)
59
- })
60
-
61
- it('does not match when param segment is missing', () => {
62
- expect(matchRoutePattern('/blog/:slug', '/blog')).toBe(false)
63
- })
64
-
65
- it('matches :param* catch-all against single segment', () => {
66
- expect(matchRoutePattern('/:all*', '/about')).toBe(true)
67
- })
68
-
69
- it('matches :param* catch-all against multi-segment path', () => {
70
- expect(matchRoutePattern('/:all*', '/deeply/nested/path')).toBe(true)
71
- })
72
-
73
- it('matches :param* catch-all against root', () => {
74
- expect(matchRoutePattern('/:all*', '/')).toBe(true)
75
- })
76
-
77
- it('does not match longer path against shorter static pattern', () => {
78
- expect(matchRoutePattern('/blog', '/blog/extra')).toBe(false)
79
- })
80
-
81
- it('handles trailing slashes gracefully', () => {
82
- expect(matchRoutePattern('/about/', '/about')).toBe(true)
83
- expect(matchRoutePattern('/about', '/about/')).toBe(true)
84
- })
85
-
86
- it('matches multiple :param segments', () => {
87
- expect(matchRoutePattern('/users/:id/posts/:postId', '/users/42/posts/99')).toBe(true)
88
- })
89
-
90
- it('does not match paths that differ only by a regex wildcard character (dot-safety)', () => {
91
- // Without escaping, '/api.v1' regex would be '^/apixv1$' which matches '/apixv1'.
92
- // With escaping, the dot is literal and '/apixv1' must not match '/api.v1'.
93
- expect(matchRoutePattern('/api.v1/users', '/apixv1/users')).toBe(false)
94
- })
95
-
96
- it('matches route with literal dot in static segment', () => {
97
- expect(matchRoutePattern('/api.v1/users', '/api.v1/users')).toBe(true)
98
- })
99
- })
100
-
101
- // ─── findRevalidate ───────────────────────────────────────────────────────────
102
-
103
- describe('findRevalidate', () => {
104
- it('returns null for an empty routes array', () => {
105
- expect(findRevalidate([], '/about')).toBeNull()
106
- })
107
-
108
- it('returns null when no route matches', () => {
109
- const routes = [{ path: '/contact', meta: { ssg: { revalidate: 60 } } }]
110
- expect(findRevalidate(routes, '/about')).toBeNull()
111
- })
112
-
113
- it('returns null when matched route has no meta', () => {
114
- const routes = [{ path: '/about' }]
115
- expect(findRevalidate(routes, '/about')).toBeNull()
116
- })
117
-
118
- it('returns null when matched route has no ssg.revalidate', () => {
119
- const routes = [{ path: '/about', meta: { layout: 'default' } }]
120
- expect(findRevalidate(routes, '/about')).toBeNull()
121
- })
122
-
123
- it('returns revalidate value for a matching static route', () => {
124
- const routes = [{ path: '/about', meta: { ssg: { revalidate: 60 } } }]
125
- expect(findRevalidate(routes, '/about')).toBe(60)
126
- })
127
-
128
- it('returns revalidate value for a matching dynamic route', () => {
129
- const routes = [{ path: '/blog/:slug', meta: { ssg: { revalidate: 300 } } }]
130
- expect(findRevalidate(routes, '/blog/hello')).toBe(300)
131
- })
132
-
133
- it('returns revalidate value for a catch-all route', () => {
134
- const routes = [{ path: '/:all*', meta: { ssg: { revalidate: 120 } } }]
135
- expect(findRevalidate(routes, '/some/unmatched/path')).toBe(120)
136
- })
137
-
138
- it('picks the first matching route when multiple match', () => {
139
- const routes = [
140
- { path: '/blog/:slug', meta: { ssg: { revalidate: 300 } } },
141
- { path: '/:all*', meta: { ssg: { revalidate: 60 } } },
142
- ]
143
- // /blog/:slug matches first
144
- expect(findRevalidate(routes, '/blog/post')).toBe(300)
145
- })
146
-
147
- it('ignores non-numeric revalidate values', () => {
148
- const routes = [{ path: '/about', meta: { ssg: { revalidate: 'invalid' } } }]
149
- expect(findRevalidate(routes, '/about')).toBeNull()
150
- })
151
- })
152
-
153
- // ─── findRenderMode ───────────────────────────────────────────────────────────
154
-
155
- describe('findRenderMode', () => {
156
- it('returns null for an empty routes array', () => {
157
- expect(findRenderMode([], '/about')).toBeNull()
158
- })
159
-
160
- it('returns null when no route matches', () => {
161
- const routes = [{ path: '/contact', meta: { render: 'server' } }]
162
- expect(findRenderMode(routes, '/about')).toBeNull()
163
- })
164
-
165
- it('returns null when matched route has no render meta', () => {
166
- const routes = [{ path: '/about' }]
167
- expect(findRenderMode(routes, '/about')).toBeNull()
168
- })
169
-
170
- it('returns "server" for a matching route with render: server', () => {
171
- const routes = [{ path: '/dashboard', meta: { render: 'server' } }]
172
- expect(findRenderMode(routes, '/dashboard')).toBe('server')
173
- })
174
-
175
- it('returns "spa" for a matching route with render: spa', () => {
176
- const routes = [{ path: '/profile', meta: { render: 'spa' } }]
177
- expect(findRenderMode(routes, '/profile')).toBe('spa')
178
- })
179
-
180
- it('returns "static" for a matching route with render: static', () => {
181
- const routes = [{ path: '/about', meta: { render: 'static' } }]
182
- expect(findRenderMode(routes, '/about')).toBe('static')
183
- })
184
-
185
- it('returns null for unrecognised render values', () => {
186
- const routes = [{ path: '/about', meta: { render: 'unknown' } }]
187
- expect(findRenderMode(routes, '/about')).toBeNull()
188
- })
189
-
190
- it('matches dynamic routes', () => {
191
- const routes = [{ path: '/blog/:slug', meta: { render: 'server' } }]
192
- expect(findRenderMode(routes, '/blog/my-post')).toBe('server')
193
- })
194
- })
195
-
196
- // ─── renderForIsr ─────────────────────────────────────────────────────────────
197
-
198
- describe('renderForIsr', () => {
199
- it('captures HTML from the handler', async () => {
200
- const handler = (_req: IncomingMessage, res: ServerResponse) => {
201
- res.setHeader('Content-Type', 'text/html')
202
- res.end('<html>hello</html>')
203
- }
204
- const entry = await renderForIsr('/about', handler, 60)
205
- expect(entry).not.toBeNull()
206
- expect(entry!.html).toBe('<html>hello</html>')
207
- })
208
-
209
- it('captures status code from the handler', async () => {
210
- const handler = (_req: IncomingMessage, res: ServerResponse) => {
211
- res.statusCode = 404
212
- res.end('Not Found')
213
- }
214
- const entry = await renderForIsr('/missing', handler, 30)
215
- expect(entry!.statusCode).toBe(404)
216
- })
217
-
218
- it('captures response headers from the handler', async () => {
219
- const handler = (_req: IncomingMessage, res: ServerResponse) => {
220
- res.setHeader('Content-Type', 'text/html; charset=utf-8')
221
- res.end('<html/>')
222
- }
223
- const entry = await renderForIsr('/about', handler, 60)
224
- expect(entry!.headers['content-type']).toBe('text/html; charset=utf-8')
225
- })
226
-
227
- it('sets revalidate to the provided TTL', async () => {
228
- const handler = (_req: IncomingMessage, res: ServerResponse) => { res.end('ok') }
229
- const entry = await renderForIsr('/about', handler, 300)
230
- expect(entry!.revalidate).toBe(300)
231
- })
232
-
233
- it('sets revalidating to false on the returned entry', async () => {
234
- const handler = (_req: IncomingMessage, res: ServerResponse) => { res.end('ok') }
235
- const entry = await renderForIsr('/about', handler, 60)
236
- expect(entry!.revalidating).toBe(false)
237
- })
238
-
239
- it('returns null when the handler throws', async () => {
240
- const handler = () => { throw new Error('boom') }
241
- const entry = await renderForIsr('/about', handler as SsrHandlerFn, 60)
242
- expect(entry).toBeNull()
243
- })
244
-
245
- it('passes the correct URL to the synthetic request', async () => {
246
- let capturedUrl = ''
247
- const handler = (req: IncomingMessage, res: ServerResponse) => {
248
- capturedUrl = req.url ?? ''
249
- res.end('ok')
250
- }
251
- await renderForIsr('/blog/hello', handler, 60)
252
- expect(capturedUrl).toBe('/blog/hello')
253
- })
254
- })
255
-
256
- type SsrHandlerFn = (req: IncomingMessage, res: ServerResponse) => void | Promise<void>
257
-
258
- // ─── serveFromIsrCache ────────────────────────────────────────────────────────
259
-
260
- describe('serveFromIsrCache', () => {
261
- function makeFakeRes() {
262
- const headers: Record<string, string> = {}
263
- let statusCode = 200
264
- let body = ''
265
- const res = {
266
- get statusCode() { return statusCode },
267
- set statusCode(v: number) { statusCode = v },
268
- setHeader: vi.fn((name: string, value: string) => { headers[name] = value }),
269
- end: vi.fn((chunk: string) => { body = chunk }),
270
- _headers: headers,
271
- _body: () => body,
272
- _status: () => statusCode,
273
- }
274
- return res
275
- }
276
-
277
- function makeEntry(overrides: Partial<IsrCacheEntry> = {}): IsrCacheEntry {
278
- return {
279
- html: '<html>cached</html>',
280
- headers: { 'content-type': 'text/html' },
281
- statusCode: 200,
282
- builtAt: Date.now(),
283
- revalidate: 60,
284
- revalidating: false,
285
- ...overrides,
286
- }
287
- }
288
-
289
- it('writes the cached HTML to the response', () => {
290
- const res = makeFakeRes()
291
- serveFromIsrCache(makeEntry(), res as unknown as ServerResponse, 'HIT')
292
- expect(res.end).toHaveBeenCalledWith('<html>cached</html>')
293
- })
294
-
295
- it('sets X-Cache: HIT header', () => {
296
- const res = makeFakeRes()
297
- serveFromIsrCache(makeEntry(), res as unknown as ServerResponse, 'HIT')
298
- expect(res.setHeader).toHaveBeenCalledWith('X-Cache', 'HIT')
299
- })
300
-
301
- it('sets X-Cache: STALE header', () => {
302
- const res = makeFakeRes()
303
- serveFromIsrCache(makeEntry(), res as unknown as ServerResponse, 'STALE')
304
- expect(res.setHeader).toHaveBeenCalledWith('X-Cache', 'STALE')
305
- })
306
-
307
- it('forwards cached headers to the response', () => {
308
- const entry = makeEntry({ headers: { 'content-type': 'text/html; charset=utf-8' } })
309
- const res = makeFakeRes()
310
- serveFromIsrCache(entry, res as unknown as ServerResponse, 'HIT')
311
- expect(res.setHeader).toHaveBeenCalledWith('content-type', 'text/html; charset=utf-8')
312
- })
313
-
314
- it('sets the status code from the cache entry', () => {
315
- const entry = makeEntry({ statusCode: 404 })
316
- const res = makeFakeRes()
317
- serveFromIsrCache(entry, res as unknown as ServerResponse, 'HIT')
318
- expect(res._status()).toBe(404)
319
- })
320
- })
@@ -1,21 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
-
3
- // Import from the main package entry to trigger coverage of src/index.ts
4
- // re-exports. These are all re-exports of other modules so we just verify
5
- // the named exports resolve without errors.
6
- import { defineConfig, cerApp } from '../index.js'
7
-
8
- describe('package main entry', () => {
9
- it('exports defineConfig', () => {
10
- expect(typeof defineConfig).toBe('function')
11
- })
12
-
13
- it('defineConfig is a pass-through', () => {
14
- const cfg = { mode: 'spa' as const }
15
- expect(defineConfig(cfg)).toBe(cfg)
16
- })
17
-
18
- it('exports cerApp', () => {
19
- expect(typeof cerApp).toBe('function')
20
- })
21
- })
@@ -1,166 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { readFileSync } from 'node:fs'
3
- import { resolve } from 'pathe'
4
- import { generateAppEntryTemplate } from '../../runtime/app-template.js'
5
- import { generateJitInitModule } from '../../plugin/index.js'
6
-
7
- const src = readFileSync(
8
- resolve(import.meta.dirname, '../../runtime/app-template.ts'),
9
- 'utf-8',
10
- )
11
-
12
- describe('app-template (source content)', () => {
13
- it('does not import virtual:cer-components (components injected per-file by cerComponentImports)', () => {
14
- expect(src).not.toContain('virtual:cer-components')
15
- })
16
-
17
- it('imports virtual:cer-routes', () => {
18
- expect(src).toContain('virtual:cer-routes')
19
- })
20
-
21
- it('imports virtual:cer-layouts', () => {
22
- expect(src).toContain('virtual:cer-layouts')
23
- })
24
-
25
- it('imports virtual:cer-plugins', () => {
26
- expect(src).toContain('virtual:cer-plugins')
27
- })
28
-
29
- it('imports registerBuiltinComponents from custom-elements-runtime', () => {
30
- expect(src).toContain('registerBuiltinComponents')
31
- expect(src).toContain('setDevMode')
32
- expect(src).toContain('@jasonshimmy/custom-elements-runtime')
33
- })
34
-
35
- it('enables runtime dev logging from the downstream Vite env', () => {
36
- expect(src).toContain('const _cerRuntimeDev')
37
- expect(src).toContain('import.meta.env?.DEV')
38
- expect(src).toContain('_cerProcess?.env')
39
- expect(src).toContain('(globalThis).__CE_RUNTIME_DEV__ = _cerRuntimeDev')
40
- expect(src).toContain('setDevMode(_cerRuntimeDev)')
41
- })
42
-
43
- it('imports initRouter from the router subpath', () => {
44
- expect(src).toContain('initRouter')
45
- expect(src).toContain('custom-elements-runtime/router')
46
- })
47
-
48
- it('imports virtual:cer-jit-css', () => {
49
- expect(src).toContain('virtual:cer-jit-css')
50
- })
51
-
52
- it('imports virtual:cer-jit-init before virtual:cer-layouts so JIT CSS is enabled before elements upgrade', () => {
53
- expect(src).toContain('virtual:cer-jit-init')
54
- const initIdx = src.indexOf('virtual:cer-jit-init')
55
- const layoutsIdx = src.indexOf('virtual:cer-layouts')
56
- const pluginsIdx = src.indexOf('virtual:cer-plugins')
57
- expect(initIdx).toBeLessThan(layoutsIdx)
58
- expect(initIdx).toBeLessThan(pluginsIdx)
59
- })
60
-
61
- it('does not import enableJITCSS in the module body (delegated to virtual:cer-jit-init)', () => {
62
- // The enableJITCSS import must not appear in the template literal — it belongs
63
- // in virtual:cer-jit-init which runs during the static import phase, before
64
- // virtual:cer-layouts and virtual:cer-plugins upgrade custom elements.
65
- const templateStart = src.indexOf('return `')
66
- expect(src.slice(templateStart)).not.toContain("import { enableJITCSS }")
67
- })
68
-
69
- it('imports virtual:cer-content-components for markdown-backed custom elements', () => {
70
- expect(src).toContain('virtual:cer-content-components')
71
- })
72
-
73
- it('exports router', () => {
74
- expect(src).toContain('export { router }')
75
- })
76
- })
77
-
78
- describe('generateAppEntryTemplate', () => {
79
- it('includes virtual:cer-jit-init import', () => {
80
- const out = generateAppEntryTemplate()
81
- expect(out).toContain("import 'virtual:cer-jit-init'")
82
- })
83
-
84
- it('places virtual:cer-jit-init before virtual:cer-layouts and virtual:cer-plugins', () => {
85
- const out = generateAppEntryTemplate()
86
- const initIdx = out.indexOf('virtual:cer-jit-init')
87
- const layoutsIdx = out.indexOf('virtual:cer-layouts')
88
- const pluginsIdx = out.indexOf('virtual:cer-plugins')
89
- expect(initIdx).toBeGreaterThanOrEqual(0)
90
- expect(initIdx).toBeLessThan(layoutsIdx)
91
- expect(initIdx).toBeLessThan(pluginsIdx)
92
- })
93
-
94
- it('does not import enableJITCSS in the generated output (delegated to virtual:cer-jit-init)', () => {
95
- const out = generateAppEntryTemplate()
96
- expect(out).not.toContain("import { enableJITCSS }")
97
- })
98
-
99
- it('still includes all standard template content', () => {
100
- const out = generateAppEntryTemplate()
101
- expect(out).toContain('virtual:cer-jit-css')
102
- expect(out).toContain('virtual:cer-routes')
103
- expect(out).toContain('export { router }')
104
- })
105
- })
106
-
107
- describe('generateJitInitModule', () => {
108
- it('calls enableJITCSS() with no arguments when no options are set', () => {
109
- const out = generateJitInitModule({ content: [], extendedColors: false, customColors: undefined })
110
- expect(out).toContain('enableJITCSS()')
111
- expect(out).not.toContain('customColors')
112
- expect(out).not.toContain('extendedColors')
113
- })
114
-
115
- it('calls enableJITCSS() with no arguments when customColors is an empty object', () => {
116
- const out = generateJitInitModule({ content: [], extendedColors: false, customColors: {} })
117
- expect(out).toContain('enableJITCSS()')
118
- expect(out).not.toContain('customColors')
119
- })
120
-
121
- it('serializes a single color family into the enableJITCSS call', () => {
122
- const out = generateJitInitModule({ content: [], extendedColors: false, customColors: { brand: { '500': '#7c3aed' } } })
123
- expect(out).toContain('enableJITCSS({ customColors:')
124
- expect(out).toContain('"brand"')
125
- expect(out).toContain('"500"')
126
- expect(out).toContain('"#7c3aed"')
127
- })
128
-
129
- it('serializes multiple color families correctly', () => {
130
- const out = generateJitInitModule({
131
- content: [],
132
- extendedColors: false,
133
- customColors: { brand: { '100': '#ede9fe', '900': '#4c1d95' }, accent: { DEFAULT: '#f59e0b' } },
134
- })
135
- expect(out).toContain('"brand"')
136
- expect(out).toContain('"accent"')
137
- expect(out).toContain('"DEFAULT"')
138
- expect(out).toContain('"#f59e0b"')
139
- })
140
-
141
- it('serializes CSS variable references as color values', () => {
142
- const out = generateJitInitModule({
143
- content: [],
144
- extendedColors: false,
145
- customColors: { surface: { DEFAULT: 'var(--md-sys-color-surface)' } },
146
- })
147
- expect(out).toContain('"surface"')
148
- expect(out).toContain('var(--md-sys-color-surface)')
149
- })
150
-
151
- it('includes extendedColors: true when set', () => {
152
- const out = generateJitInitModule({ content: [], extendedColors: true, customColors: undefined })
153
- expect(out).toContain('extendedColors: true')
154
- })
155
-
156
- it('includes extendedColors array when set', () => {
157
- const out = generateJitInitModule({ content: [], extendedColors: ['slate', 'blue'], customColors: undefined })
158
- expect(out).toContain('extendedColors: ["slate","blue"]')
159
- })
160
-
161
- it('imports enableJITCSS from the jit-css subpath', () => {
162
- const out = generateJitInitModule({ content: [], extendedColors: false, customColors: undefined })
163
- expect(out).toContain('enableJITCSS')
164
- expect(out).toContain('custom-elements-runtime/jit-css')
165
- })
166
- })
@@ -1,155 +0,0 @@
1
- /**
2
- * Integration tests for the build-ssg renderPath success path.
3
- *
4
- * These tests use a real temporary ESM module as the "server bundle" so that
5
- * the dynamic import() inside renderPath actually resolves, exercising the
6
- * success branches (writeRenderedPath call, generatedPaths.push, etc.) that
7
- * are unreachable when the bundle is absent.
8
- *
9
- * A separate test file is required so the node:fs/promises mock does NOT
10
- * shadow the real writeFile/mkdir used to set up the temp bundle.
11
- */
12
- import { vi, describe, it, expect, beforeAll, afterAll } from 'vitest'
13
- import { mkdirSync, writeFileSync, rmSync } from 'node:fs'
14
- import { tmpdir } from 'node:os'
15
- import { join } from 'pathe'
16
-
17
- // Mock buildSSR so the SSG pipeline skips the Vite build step.
18
- vi.mock('../../plugin/build-ssr.js', () => ({ buildSSR: vi.fn().mockResolvedValue(undefined) }))
19
- vi.mock('fast-glob', () => ({ default: vi.fn().mockResolvedValue([]) }))
20
- // Intentionally NOT mocking node:fs or node:fs/promises so real writes work.
21
-
22
- import type { ResolvedCerConfig } from '../../plugin/dev-server.js'
23
-
24
- let tmpRoot: string
25
-
26
- beforeAll(() => {
27
- // Create a minimal "server bundle" that exports a handler.
28
- // The handler writes a minimal HTML string to res.end so renderPath captures it.
29
- tmpRoot = join(tmpdir(), `cer-ssg-render-${Date.now()}`)
30
- const serverDir = join(tmpRoot, 'dist', 'server')
31
- mkdirSync(serverDir, { recursive: true })
32
- writeFileSync(
33
- join(serverDir, 'server.js'),
34
- // ESM module — works because Vitest runs with Node's native ESM loader.
35
- `export const handler = async (req, res) => {
36
- res.setHeader('Content-Type', 'text/html');
37
- res.end('<!DOCTYPE html><html><head></head><body>Hello from ' + req.url + '</body></html>');
38
- };
39
- export const apiRoutes = [];
40
- export const plugins = [];
41
- export const layouts = {};
42
- `,
43
- 'utf-8',
44
- )
45
- })
46
-
47
- afterAll(() => {
48
- rmSync(tmpRoot, { recursive: true, force: true })
49
- })
50
-
51
- function makeConfig(overrides: Partial<ResolvedCerConfig> = {}): ResolvedCerConfig {
52
- return {
53
- root: tmpRoot,
54
- srcDir: join(tmpRoot, 'app'),
55
- pagesDir: join(tmpRoot, 'app', 'pages'),
56
- mode: 'ssg',
57
- ssg: { routes: ['/'], concurrency: 1 },
58
- ...overrides,
59
- } as unknown as ResolvedCerConfig
60
- }
61
-
62
- describe('buildSSG — renderPath success (real server bundle)', () => {
63
- it('writes rendered HTML for the root path to dist/index.html', async () => {
64
- // Reset module registry so _serverMod cache is cleared between test runs.
65
- await vi.resetModules()
66
- const { buildSSG } = await import('../../plugin/build-ssg.js')
67
- await buildSSG(makeConfig())
68
-
69
- const { readFileSync, existsSync } = await import('node:fs')
70
- const outPath = join(tmpRoot, 'dist', 'index.html')
71
- expect(existsSync(outPath)).toBe(true)
72
- const html = readFileSync(outPath, 'utf-8')
73
- expect(html).toContain('Hello from /')
74
- })
75
-
76
- it('records the path in the ssg-manifest paths array', async () => {
77
- await vi.resetModules()
78
- const { buildSSG } = await import('../../plugin/build-ssg.js')
79
- await buildSSG(makeConfig())
80
-
81
- const { readFileSync } = await import('node:fs')
82
- const manifest = JSON.parse(readFileSync(join(tmpRoot, 'dist', 'ssg-manifest.json'), 'utf-8'))
83
- expect(manifest.paths).toContain('/')
84
- expect(manifest.errors).toHaveLength(0)
85
- })
86
-
87
- it('renders multiple paths with concurrency > 1', async () => {
88
- await vi.resetModules()
89
- const { buildSSG } = await import('../../plugin/build-ssg.js')
90
- const config = makeConfig({ ssg: { routes: ['/', '/about'], concurrency: 2 } } as Partial<ResolvedCerConfig>)
91
- await buildSSG(config)
92
-
93
- const { readFileSync, existsSync } = await import('node:fs')
94
- expect(existsSync(join(tmpRoot, 'dist', 'index.html'))).toBe(true)
95
- expect(existsSync(join(tmpRoot, 'dist', 'about', 'index.html'))).toBe(true)
96
- const manifest = JSON.parse(readFileSync(join(tmpRoot, 'dist', 'ssg-manifest.json'), 'utf-8'))
97
- expect(manifest.paths).toHaveLength(2)
98
- })
99
-
100
- it('captures HTML from a streaming handler that calls write() then end()', async () => {
101
- // Simulate the renderToStreamWithJITCSSDSD-based handler which calls
102
- // res.write(firstChunk) for sync content and res.end(polyfill + tail).
103
- // Use a completely separate tmpdir with a unique path so Node's native ESM
104
- // import cache cannot return a previously-loaded module for the same URL.
105
- const streamRoot = join(tmpdir(), `cer-ssg-stream-${Date.now()}`)
106
- const streamServerDir = join(streamRoot, 'dist', 'server')
107
- mkdirSync(streamServerDir, { recursive: true })
108
- writeFileSync(
109
- join(streamServerDir, 'server.js'),
110
- `export const handler = async (req, res) => {
111
- res.setHeader('Content-Type', 'text/html');
112
- res.setHeader('Transfer-Encoding', 'chunked');
113
- res.write('<html><head></head>');
114
- res.write('<body>streamed</body>');
115
- res.end('</html>');
116
- };
117
- export const apiRoutes = [];
118
- export const plugins = [];
119
- export const layouts = {};
120
- `,
121
- 'utf-8',
122
- )
123
-
124
- await vi.resetModules()
125
- const { buildSSG } = await import('../../plugin/build-ssg.js')
126
- const config = {
127
- root: streamRoot,
128
- srcDir: join(streamRoot, 'app'),
129
- pagesDir: join(streamRoot, 'app', 'pages'),
130
- mode: 'ssg',
131
- ssg: { routes: ['/'], concurrency: 1 },
132
- } as unknown as ResolvedCerConfig
133
- await buildSSG(config)
134
-
135
- const { readFileSync, existsSync } = await import('node:fs')
136
- const outPath = join(streamRoot, 'dist', 'index.html')
137
- expect(existsSync(outPath)).toBe(true)
138
- const html = readFileSync(outPath, 'utf-8')
139
- expect(html).toContain('<html><head></head>')
140
- expect(html).toContain('<body>streamed</body>')
141
- expect(html).toContain('</html>')
142
-
143
- rmSync(streamRoot, { recursive: true, force: true })
144
- })
145
-
146
- it('uses cached _serverMod on second renderPath call (no double import)', async () => {
147
- // In a fresh module instance, render two paths sequentially.
148
- // The second renderPath call hits the !_serverMod === false branch (cache).
149
- await vi.resetModules()
150
- const { buildSSG } = await import('../../plugin/build-ssg.js')
151
- const config = makeConfig({ ssg: { routes: ['/', '/page2'], concurrency: 1 } } as Partial<ResolvedCerConfig>)
152
- // Should complete without error — second call uses cached module
153
- await expect(buildSSG(config)).resolves.not.toThrow()
154
- })
155
- })