@jasonshimmy/vite-plugin-cer-app 0.23.2 → 0.24.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 (392) hide show
  1. package/dist/cli/checks/lighthouse.d.ts +26 -0
  2. package/dist/cli/checks/lighthouse.d.ts.map +1 -0
  3. package/dist/cli/checks/lighthouse.js +121 -0
  4. package/dist/cli/checks/lighthouse.js.map +1 -0
  5. package/dist/cli/checks/links.d.ts +12 -0
  6. package/dist/cli/checks/links.d.ts.map +1 -0
  7. package/dist/cli/checks/links.js +89 -0
  8. package/dist/cli/checks/links.js.map +1 -0
  9. package/dist/cli/checks/performance.d.ts +17 -0
  10. package/dist/cli/checks/performance.d.ts.map +1 -0
  11. package/dist/cli/checks/performance.js +61 -0
  12. package/dist/cli/checks/performance.js.map +1 -0
  13. package/dist/cli/commands/check.d.ts +3 -0
  14. package/dist/cli/commands/check.d.ts.map +1 -0
  15. package/dist/cli/commands/check.js +85 -0
  16. package/dist/cli/commands/check.js.map +1 -0
  17. package/dist/cli/create/index.d.ts +11 -1
  18. package/dist/cli/create/index.d.ts.map +1 -1
  19. package/dist/cli/create/index.js +135 -65
  20. package/dist/cli/create/index.js.map +1 -1
  21. package/dist/cli/create/templates/spa/package.json.tpl +5 -3
  22. package/dist/cli/create/templates/ssg/cer.config.ts.tpl +2 -0
  23. package/dist/cli/create/templates/ssg/package.json.tpl +5 -3
  24. package/dist/cli/create/templates/ssr/package.json.tpl +5 -3
  25. package/dist/cli/index.js +2 -0
  26. package/dist/cli/index.js.map +1 -1
  27. package/dist/index.d.ts +3 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/plugin/build-ssg.d.ts +22 -6
  30. package/dist/plugin/build-ssg.d.ts.map +1 -1
  31. package/dist/plugin/build-ssg.js +227 -17
  32. package/dist/plugin/build-ssg.js.map +1 -1
  33. package/dist/plugin/content/parser.d.ts.map +1 -1
  34. package/dist/plugin/content/parser.js +54 -10
  35. package/dist/plugin/content/parser.js.map +1 -1
  36. package/dist/plugin/dev-server.d.ts +4 -1
  37. package/dist/plugin/dev-server.d.ts.map +1 -1
  38. package/dist/plugin/dev-server.js.map +1 -1
  39. package/dist/plugin/dts-generator.d.ts.map +1 -1
  40. package/dist/plugin/dts-generator.js +50 -8
  41. package/dist/plugin/dts-generator.js.map +1 -1
  42. package/dist/plugin/generated-dir.d.ts +2 -0
  43. package/dist/plugin/generated-dir.d.ts.map +1 -1
  44. package/dist/plugin/generated-dir.js +17 -6
  45. package/dist/plugin/generated-dir.js.map +1 -1
  46. package/dist/plugin/html-post-process.d.ts +6 -0
  47. package/dist/plugin/html-post-process.d.ts.map +1 -1
  48. package/dist/plugin/html-post-process.js +24 -0
  49. package/dist/plugin/html-post-process.js.map +1 -1
  50. package/dist/plugin/index.d.ts.map +1 -1
  51. package/dist/plugin/index.js +60 -13
  52. package/dist/plugin/index.js.map +1 -1
  53. package/dist/plugin/transforms/auto-import.d.ts.map +1 -1
  54. package/dist/plugin/transforms/auto-import.js +7 -0
  55. package/dist/plugin/transforms/auto-import.js.map +1 -1
  56. package/dist/plugin/transforms/prune-runtime-css.d.ts +8 -0
  57. package/dist/plugin/transforms/prune-runtime-css.d.ts.map +1 -0
  58. package/dist/plugin/transforms/prune-runtime-css.js +40 -0
  59. package/dist/plugin/transforms/prune-runtime-css.js.map +1 -0
  60. package/dist/runtime/app-template.d.ts +1 -1
  61. package/dist/runtime/app-template.d.ts.map +1 -1
  62. package/dist/runtime/app-template.js +206 -36
  63. package/dist/runtime/app-template.js.map +1 -1
  64. package/dist/runtime/composables/index.d.ts +4 -0
  65. package/dist/runtime/composables/index.d.ts.map +1 -1
  66. package/dist/runtime/composables/index.js +2 -0
  67. package/dist/runtime/composables/index.js.map +1 -1
  68. package/dist/runtime/composables/use-active-headings.d.ts +24 -0
  69. package/dist/runtime/composables/use-active-headings.d.ts.map +1 -0
  70. package/dist/runtime/composables/use-active-headings.js +112 -0
  71. package/dist/runtime/composables/use-active-headings.js.map +1 -0
  72. package/dist/runtime/composables/use-content-page.d.ts +45 -0
  73. package/dist/runtime/composables/use-content-page.d.ts.map +1 -0
  74. package/dist/runtime/composables/use-content-page.js +179 -0
  75. package/dist/runtime/composables/use-content-page.js.map +1 -0
  76. package/dist/runtime/composables/use-content-search.d.ts.map +1 -1
  77. package/dist/runtime/composables/use-content-search.js +1 -5
  78. package/dist/runtime/composables/use-content-search.js.map +1 -1
  79. package/dist/runtime/composables/use-fetch.d.ts +2 -1
  80. package/dist/runtime/composables/use-fetch.d.ts.map +1 -1
  81. package/dist/runtime/composables/use-fetch.js +112 -43
  82. package/dist/runtime/composables/use-fetch.js.map +1 -1
  83. package/dist/runtime/composables/use-route.d.ts.map +1 -1
  84. package/dist/runtime/composables/use-route.js +39 -11
  85. package/dist/runtime/composables/use-route.js.map +1 -1
  86. package/dist/runtime/content/client.js +2 -2
  87. package/dist/runtime/content/client.js.map +1 -1
  88. package/dist/runtime/entry-server-template.d.ts +16 -1
  89. package/dist/runtime/entry-server-template.d.ts.map +1 -1
  90. package/dist/runtime/entry-server-template.js +120 -13
  91. package/dist/runtime/entry-server-template.js.map +1 -1
  92. package/dist/types/config.d.ts +45 -4
  93. package/dist/types/config.d.ts.map +1 -1
  94. package/dist/types/config.js.map +1 -1
  95. package/dist/types/middleware.d.ts +2 -2
  96. package/dist/types/middleware.d.ts.map +1 -1
  97. package/package.json +22 -19
  98. package/.github/copilot-instructions.md +0 -169
  99. package/.github/workflows/publish.yml +0 -257
  100. package/.nvmrc +0 -1
  101. package/CHANGELOG.md +0 -236
  102. package/CLAUDE.md +0 -113
  103. package/commits.txt +0 -1
  104. package/cypress.config.ts +0 -16
  105. package/docs/authentication.md +0 -285
  106. package/docs/cli.md +0 -324
  107. package/docs/components.md +0 -237
  108. package/docs/composables.md +0 -907
  109. package/docs/configuration.md +0 -696
  110. package/docs/content.md +0 -570
  111. package/docs/data-loading.md +0 -336
  112. package/docs/getting-started.md +0 -237
  113. package/docs/head-management.md +0 -212
  114. package/docs/i18n.md +0 -159
  115. package/docs/layouts.md +0 -224
  116. package/docs/middleware.md +0 -234
  117. package/docs/plugins.md +0 -170
  118. package/docs/rendering-modes.md +0 -377
  119. package/docs/routing.md +0 -485
  120. package/docs/server-api.md +0 -253
  121. package/docs/testing.md +0 -455
  122. package/docs/use-fetch.md +0 -183
  123. package/e2e/cypress/e2e/api.cy.ts +0 -123
  124. package/e2e/cypress/e2e/async-component.cy.ts +0 -27
  125. package/e2e/cypress/e2e/component-splitting.cy.ts +0 -50
  126. package/e2e/cypress/e2e/content.cy.ts +0 -425
  127. package/e2e/cypress/e2e/cookie.cy.ts +0 -85
  128. package/e2e/cypress/e2e/data.cy.ts +0 -158
  129. package/e2e/cypress/e2e/error-boundary.cy.ts +0 -88
  130. package/e2e/cypress/e2e/fouc.cy.ts +0 -254
  131. package/e2e/cypress/e2e/group-meta.cy.ts +0 -36
  132. package/e2e/cypress/e2e/head.cy.ts +0 -89
  133. package/e2e/cypress/e2e/i18n.cy.ts +0 -79
  134. package/e2e/cypress/e2e/interactive.cy.ts +0 -137
  135. package/e2e/cypress/e2e/isr-nested-runtime.cy.ts +0 -102
  136. package/e2e/cypress/e2e/jit-css-custom-colors.cy.ts +0 -43
  137. package/e2e/cypress/e2e/middleware-chain.cy.ts +0 -89
  138. package/e2e/cypress/e2e/middleware-status.cy.ts +0 -30
  139. package/e2e/cypress/e2e/middleware.cy.ts +0 -45
  140. package/e2e/cypress/e2e/navigate.cy.ts +0 -39
  141. package/e2e/cypress/e2e/observability.cy.ts +0 -77
  142. package/e2e/cypress/e2e/per-route-error.cy.ts +0 -42
  143. package/e2e/cypress/e2e/per-route-render.cy.ts +0 -70
  144. package/e2e/cypress/e2e/preview-hardening.cy.ts +0 -88
  145. package/e2e/cypress/e2e/routes.cy.ts +0 -128
  146. package/e2e/cypress/e2e/seo-meta.cy.ts +0 -108
  147. package/e2e/cypress/e2e/server-middleware.cy.ts +0 -46
  148. package/e2e/cypress/e2e/session-rotation.cy.ts +0 -25
  149. package/e2e/cypress/e2e/session.cy.ts +0 -73
  150. package/e2e/cypress/e2e/ssr-render-error.cy.ts +0 -68
  151. package/e2e/cypress/e2e/synthetic-404.cy.ts +0 -45
  152. package/e2e/cypress/e2e/use-page-data.cy.ts +0 -122
  153. package/e2e/cypress/e2e/use-state.cy.ts +0 -138
  154. package/e2e/cypress/support/commands.ts +0 -120
  155. package/e2e/cypress/support/e2e.ts +0 -10
  156. package/e2e/cypress/tsconfig.json +0 -14
  157. package/e2e/kitchen-sink/app/components/ks-badge.ts +0 -8
  158. package/e2e/kitchen-sink/app/composables/useKsCounter.ts +0 -9
  159. package/e2e/kitchen-sink/app/error.ts +0 -18
  160. package/e2e/kitchen-sink/app/layouts/admin.ts +0 -13
  161. package/e2e/kitchen-sink/app/layouts/default.ts +0 -25
  162. package/e2e/kitchen-sink/app/layouts/group.ts +0 -9
  163. package/e2e/kitchen-sink/app/layouts/minimal.ts +0 -7
  164. package/e2e/kitchen-sink/app/loading.ts +0 -9
  165. package/e2e/kitchen-sink/app/middleware/auth.ts +0 -9
  166. package/e2e/kitchen-sink/app/middleware/custom-log.ts +0 -4
  167. package/e2e/kitchen-sink/app/middleware/group-auth.ts +0 -7
  168. package/e2e/kitchen-sink/app/middleware/logger.ts +0 -14
  169. package/e2e/kitchen-sink/app/pages/(auth)/login.ts +0 -13
  170. package/e2e/kitchen-sink/app/pages/(auth)/protected.ts +0 -16
  171. package/e2e/kitchen-sink/app/pages/404.ts +0 -9
  172. package/e2e/kitchen-sink/app/pages/about.ts +0 -17
  173. package/e2e/kitchen-sink/app/pages/admin/_layout.ts +0 -1
  174. package/e2e/kitchen-sink/app/pages/admin/dashboard.ts +0 -11
  175. package/e2e/kitchen-sink/app/pages/async-component-error-test.ts +0 -18
  176. package/e2e/kitchen-sink/app/pages/async-component-test.ts +0 -18
  177. package/e2e/kitchen-sink/app/pages/blog/[slug].ts +0 -59
  178. package/e2e/kitchen-sink/app/pages/blog/index.ts +0 -51
  179. package/e2e/kitchen-sink/app/pages/content-blog.ts +0 -37
  180. package/e2e/kitchen-sink/app/pages/content-doc.ts +0 -42
  181. package/e2e/kitchen-sink/app/pages/content-fallback.ts +0 -36
  182. package/e2e/kitchen-sink/app/pages/content-guides.ts +0 -35
  183. package/e2e/kitchen-sink/app/pages/content-index.ts +0 -39
  184. package/e2e/kitchen-sink/app/pages/content-search.ts +0 -36
  185. package/e2e/kitchen-sink/app/pages/cookie-test.ts +0 -22
  186. package/e2e/kitchen-sink/app/pages/counter.ts +0 -17
  187. package/e2e/kitchen-sink/app/pages/group-auth-blocked.ts +0 -9
  188. package/e2e/kitchen-sink/app/pages/group-meta-test/_layout.ts +0 -6
  189. package/e2e/kitchen-sink/app/pages/group-meta-test/custom-mw.ts +0 -14
  190. package/e2e/kitchen-sink/app/pages/group-meta-test/page.ts +0 -9
  191. package/e2e/kitchen-sink/app/pages/group-meta-test/protected.ts +0 -8
  192. package/e2e/kitchen-sink/app/pages/head.ts +0 -20
  193. package/e2e/kitchen-sink/app/pages/i18n-test.ts +0 -14
  194. package/e2e/kitchen-sink/app/pages/index.ts +0 -27
  195. package/e2e/kitchen-sink/app/pages/isr-test.ts +0 -17
  196. package/e2e/kitchen-sink/app/pages/items/[id].ts +0 -20
  197. package/e2e/kitchen-sink/app/pages/jit-css-custom-colors-test.ts +0 -14
  198. package/e2e/kitchen-sink/app/pages/loader-error-test.ts +0 -13
  199. package/e2e/kitchen-sink/app/pages/loader-props-test.ts +0 -19
  200. package/e2e/kitchen-sink/app/pages/loader-response-error-test.ts +0 -13
  201. package/e2e/kitchen-sink/app/pages/middleware-chain-test.ts +0 -12
  202. package/e2e/kitchen-sink/app/pages/middleware-status-test.ts +0 -9
  203. package/e2e/kitchen-sink/app/pages/navigate-test.ts +0 -16
  204. package/e2e/kitchen-sink/app/pages/observability-test.ts +0 -25
  205. package/e2e/kitchen-sink/app/pages/per-route-error-test.error.ts +0 -13
  206. package/e2e/kitchen-sink/app/pages/per-route-error-test.ts +0 -15
  207. package/e2e/kitchen-sink/app/pages/plugin-dsd-test.ts +0 -10
  208. package/e2e/kitchen-sink/app/pages/render-error-test.ts +0 -12
  209. package/e2e/kitchen-sink/app/pages/render-server-test.ts +0 -12
  210. package/e2e/kitchen-sink/app/pages/render-spa-test.ts +0 -12
  211. package/e2e/kitchen-sink/app/pages/route-info.ts +0 -14
  212. package/e2e/kitchen-sink/app/pages/seo-test.ts +0 -23
  213. package/e2e/kitchen-sink/app/pages/session-rotation-test.ts +0 -25
  214. package/e2e/kitchen-sink/app/pages/use-state-test.ts +0 -37
  215. package/e2e/kitchen-sink/app/plugins/01.setup.ts +0 -7
  216. package/e2e/kitchen-sink/app/plugins/02.ks-plugin-components.ts +0 -27
  217. package/e2e/kitchen-sink/cer-auto-imports.d.ts +0 -51
  218. package/e2e/kitchen-sink/cer-env.d.ts +0 -35
  219. package/e2e/kitchen-sink/cer-tsconfig.json +0 -30
  220. package/e2e/kitchen-sink/cer.config.ts +0 -43
  221. package/e2e/kitchen-sink/content/01.guides/01.index.md +0 -8
  222. package/e2e/kitchen-sink/content/01.guides/02.intro.md +0 -8
  223. package/e2e/kitchen-sink/content/01.guides/10.advanced.md +0 -8
  224. package/e2e/kitchen-sink/content/blog/2026-04-01-hello.md +0 -26
  225. package/e2e/kitchen-sink/content/blog/2026-04-02-draft.md +0 -10
  226. package/e2e/kitchen-sink/content/blog/index.md +0 -8
  227. package/e2e/kitchen-sink/content/blog/no-frontmatter.md +0 -7
  228. package/e2e/kitchen-sink/content/docs/getting-started.md +0 -48
  229. package/e2e/kitchen-sink/content/index.md +0 -16
  230. package/e2e/kitchen-sink/server/api/echo.ts +0 -12
  231. package/e2e/kitchen-sink/server/api/health.ts +0 -3
  232. package/e2e/kitchen-sink/server/api/posts/[slug].ts +0 -11
  233. package/e2e/kitchen-sink/server/api/posts/index.ts +0 -5
  234. package/e2e/kitchen-sink/server/api/session.ts +0 -23
  235. package/e2e/kitchen-sink/server/data/posts.ts +0 -21
  236. package/e2e/kitchen-sink/server/middleware/01-headers.ts +0 -6
  237. package/e2e/kitchen-sink/server/middleware/02-status-test.ts +0 -10
  238. package/e2e/kitchen-sink/tsconfig.json +0 -3
  239. package/e2e/scripts/clean.mjs +0 -14
  240. package/eslint.config.ts +0 -22
  241. package/src/__tests__/cli/adapters/cloudflare-worker.integration.test.ts +0 -132
  242. package/src/__tests__/cli/adapters/cloudflare.test.ts +0 -332
  243. package/src/__tests__/cli/adapters/netlify-bridge.integration.test.ts +0 -139
  244. package/src/__tests__/cli/adapters/netlify.test.ts +0 -286
  245. package/src/__tests__/cli/adapters/vercel-launcher.integration.test.ts +0 -129
  246. package/src/__tests__/cli/adapters/vercel.test.ts +0 -263
  247. package/src/__tests__/cli/preview-hardening.test.ts +0 -265
  248. package/src/__tests__/cli/preview-isr.test.ts +0 -320
  249. package/src/__tests__/index.test.ts +0 -21
  250. package/src/__tests__/plugin/app-template.test.ts +0 -166
  251. package/src/__tests__/plugin/build-ssg-render.test.ts +0 -155
  252. package/src/__tests__/plugin/build-ssg.test.ts +0 -598
  253. package/src/__tests__/plugin/build-ssr.test.ts +0 -192
  254. package/src/__tests__/plugin/cer-app-plugin.test.ts +0 -552
  255. package/src/__tests__/plugin/content/emitter.test.ts +0 -117
  256. package/src/__tests__/plugin/content/loader.test.ts +0 -154
  257. package/src/__tests__/plugin/content/parser.test.ts +0 -381
  258. package/src/__tests__/plugin/content/path-utils.test.ts +0 -69
  259. package/src/__tests__/plugin/content/search.test.ts +0 -119
  260. package/src/__tests__/plugin/dev-server.test.ts +0 -813
  261. package/src/__tests__/plugin/dts-generator.test.ts +0 -394
  262. package/src/__tests__/plugin/entry-server-template.test.ts +0 -385
  263. package/src/__tests__/plugin/generated-dir.test.ts +0 -144
  264. package/src/__tests__/plugin/html-post-process.test.ts +0 -146
  265. package/src/__tests__/plugin/path-utils.test.ts +0 -411
  266. package/src/__tests__/plugin/resolve-config.test.ts +0 -233
  267. package/src/__tests__/plugin/scanner.test.ts +0 -186
  268. package/src/__tests__/plugin/transforms/auto-import.test.ts +0 -510
  269. package/src/__tests__/plugin/transforms/head-inject.test.ts +0 -178
  270. package/src/__tests__/plugin/virtual/composables.test.ts +0 -57
  271. package/src/__tests__/plugin/virtual/content-components.test.ts +0 -66
  272. package/src/__tests__/plugin/virtual/error.test.ts +0 -71
  273. package/src/__tests__/plugin/virtual/layouts.test.ts +0 -70
  274. package/src/__tests__/plugin/virtual/loading.test.ts +0 -72
  275. package/src/__tests__/plugin/virtual/middleware.test.ts +0 -83
  276. package/src/__tests__/plugin/virtual/plugins.test.ts +0 -129
  277. package/src/__tests__/plugin/virtual/routes.test.ts +0 -884
  278. package/src/__tests__/plugin/virtual/server-api.test.ts +0 -164
  279. package/src/__tests__/plugin/virtual/server-middleware.test.ts +0 -102
  280. package/src/__tests__/runtime/app-template.test.ts +0 -208
  281. package/src/__tests__/runtime/define-middleware.test.ts +0 -64
  282. package/src/__tests__/runtime/define-server-middleware.test.ts +0 -54
  283. package/src/__tests__/runtime/entry-client-template.test.ts +0 -61
  284. package/src/__tests__/runtime/isr-handler.test.ts +0 -338
  285. package/src/__tests__/runtime/oauth/handler.test.ts +0 -358
  286. package/src/__tests__/runtime/oauth/providers.test.ts +0 -47
  287. package/src/__tests__/runtime/oauth-index.test.ts +0 -43
  288. package/src/__tests__/runtime/use-auth.test.ts +0 -169
  289. package/src/__tests__/runtime/use-content-search-composable.test.ts +0 -405
  290. package/src/__tests__/runtime/use-content-search.test.ts +0 -163
  291. package/src/__tests__/runtime/use-content.test.ts +0 -226
  292. package/src/__tests__/runtime/use-cookie.test.ts +0 -277
  293. package/src/__tests__/runtime/use-fetch-component.test.ts +0 -214
  294. package/src/__tests__/runtime/use-fetch.test.ts +0 -377
  295. package/src/__tests__/runtime/use-head.test.ts +0 -311
  296. package/src/__tests__/runtime/use-inject-client.test.ts +0 -67
  297. package/src/__tests__/runtime/use-inject.test.ts +0 -66
  298. package/src/__tests__/runtime/use-locale.test.ts +0 -152
  299. package/src/__tests__/runtime/use-navigate.test.ts +0 -121
  300. package/src/__tests__/runtime/use-page-data.test.ts +0 -298
  301. package/src/__tests__/runtime/use-route.test.ts +0 -156
  302. package/src/__tests__/runtime/use-runtime-config.test.ts +0 -182
  303. package/src/__tests__/runtime/use-seo-meta.test.ts +0 -109
  304. package/src/__tests__/runtime/use-session.test.ts +0 -320
  305. package/src/__tests__/runtime/use-state.test.ts +0 -340
  306. package/src/__tests__/types/config.test.ts +0 -18
  307. package/src/cli/adapters/cloudflare.ts +0 -335
  308. package/src/cli/adapters/netlify.ts +0 -326
  309. package/src/cli/adapters/vercel.ts +0 -311
  310. package/src/cli/commands/adapt.ts +0 -84
  311. package/src/cli/commands/build.ts +0 -165
  312. package/src/cli/commands/dev.ts +0 -125
  313. package/src/cli/commands/generate.ts +0 -91
  314. package/src/cli/commands/preview-isr.ts +0 -172
  315. package/src/cli/commands/preview.ts +0 -523
  316. package/src/cli/create/index.ts +0 -275
  317. package/src/cli/create/templates/shared/.gitignore.tpl +0 -25
  318. package/src/cli/create/templates/shared/app/layouts/default.ts.tpl +0 -15
  319. package/src/cli/create/templates/shared/app/pages/index.ts.tpl +0 -8
  320. package/src/cli/create/templates/shared/index.html.tpl +0 -12
  321. package/src/cli/create/templates/shared/tsconfig.json.tpl +0 -6
  322. package/src/cli/create/templates/spa/cer.config.ts.tpl +0 -6
  323. package/src/cli/create/templates/spa/package.json.tpl +0 -18
  324. package/src/cli/create/templates/ssg/cer.config.ts.tpl +0 -10
  325. package/src/cli/create/templates/ssg/package.json.tpl +0 -19
  326. package/src/cli/create/templates/ssr/cer.config.ts.tpl +0 -6
  327. package/src/cli/create/templates/ssr/package.json.tpl +0 -18
  328. package/src/cli/index.ts +0 -22
  329. package/src/index.ts +0 -20
  330. package/src/plugin/build-ssg.ts +0 -403
  331. package/src/plugin/build-ssr.ts +0 -134
  332. package/src/plugin/content/emitter.ts +0 -50
  333. package/src/plugin/content/index.ts +0 -233
  334. package/src/plugin/content/parser.ts +0 -259
  335. package/src/plugin/content/path-utils.ts +0 -55
  336. package/src/plugin/content/scanner.ts +0 -26
  337. package/src/plugin/content/search.ts +0 -28
  338. package/src/plugin/dev-server.ts +0 -379
  339. package/src/plugin/dts-generator.ts +0 -273
  340. package/src/plugin/generated-dir.ts +0 -121
  341. package/src/plugin/html-post-process.ts +0 -96
  342. package/src/plugin/index.ts +0 -584
  343. package/src/plugin/path-utils.ts +0 -186
  344. package/src/plugin/scanner.ts +0 -65
  345. package/src/plugin/transforms/auto-import.ts +0 -206
  346. package/src/plugin/transforms/head-inject.ts +0 -161
  347. package/src/plugin/virtual/composables.ts +0 -28
  348. package/src/plugin/virtual/content-components.ts +0 -83
  349. package/src/plugin/virtual/error.ts +0 -34
  350. package/src/plugin/virtual/layouts.ts +0 -41
  351. package/src/plugin/virtual/loading.ts +0 -32
  352. package/src/plugin/virtual/middleware.ts +0 -45
  353. package/src/plugin/virtual/plugins.ts +0 -46
  354. package/src/plugin/virtual/routes.ts +0 -514
  355. package/src/plugin/virtual/server-api.ts +0 -85
  356. package/src/plugin/virtual/server-middleware.ts +0 -44
  357. package/src/runtime/app-template.ts +0 -377
  358. package/src/runtime/composables/define-middleware.ts +0 -17
  359. package/src/runtime/composables/define-server-middleware.ts +0 -18
  360. package/src/runtime/composables/index.ts +0 -27
  361. package/src/runtime/composables/use-auth.ts +0 -125
  362. package/src/runtime/composables/use-content-search.ts +0 -205
  363. package/src/runtime/composables/use-content.ts +0 -146
  364. package/src/runtime/composables/use-cookie.ts +0 -135
  365. package/src/runtime/composables/use-fetch.ts +0 -438
  366. package/src/runtime/composables/use-head.ts +0 -234
  367. package/src/runtime/composables/use-inject.ts +0 -49
  368. package/src/runtime/composables/use-locale.ts +0 -109
  369. package/src/runtime/composables/use-navigate.ts +0 -58
  370. package/src/runtime/composables/use-page-data.ts +0 -93
  371. package/src/runtime/composables/use-route.ts +0 -71
  372. package/src/runtime/composables/use-runtime-config.ts +0 -123
  373. package/src/runtime/composables/use-seo-meta.ts +0 -80
  374. package/src/runtime/composables/use-session.ts +0 -186
  375. package/src/runtime/composables/use-state.ts +0 -92
  376. package/src/runtime/content/client.ts +0 -168
  377. package/src/runtime/entry-client-template.ts +0 -39
  378. package/src/runtime/entry-server-template.ts +0 -493
  379. package/src/runtime/isr-handler.ts +0 -184
  380. package/src/runtime/oauth/handler.ts +0 -407
  381. package/src/runtime/oauth/index.ts +0 -49
  382. package/src/runtime/oauth/providers.ts +0 -38
  383. package/src/types/api.ts +0 -40
  384. package/src/types/config.ts +0 -379
  385. package/src/types/content.ts +0 -66
  386. package/src/types/index.ts +0 -7
  387. package/src/types/middleware.ts +0 -63
  388. package/src/types/page.ts +0 -117
  389. package/src/types/plugin.ts +0 -34
  390. package/tsconfig.build.json +0 -10
  391. package/tsconfig.json +0 -19
  392. 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
- })