@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,403 +0,0 @@
1
- import { writeFile, mkdir, readFile } from 'node:fs/promises'
2
- import { existsSync } from 'node:fs'
3
- import { join } from 'pathe'
4
- import {
5
- injectFaviconLink,
6
- injectCanonicalLink,
7
- addNoopenerToExternalLinks,
8
- generateRobotsTxt,
9
- } from './html-post-process.js'
10
- import { createServer, type UserConfig } from 'vite'
11
- import type { ResolvedCerConfig } from './dev-server.js'
12
- import type { ContentItem } from '../types/content.js'
13
- import { buildSSR } from './build-ssr.js'
14
- import { buildRouteEntry } from './path-utils.js'
15
- import fg from 'fast-glob'
16
-
17
- interface SsgManifest {
18
- generatedAt: string
19
- paths: string[]
20
- errors: Array<{ path: string; error: string }>
21
- }
22
-
23
- const CONTENT_STORE_KEY = '__CER_CONTENT_STORE__'
24
-
25
-
26
- /**
27
- * Collects all static paths to generate.
28
- * For 'auto' mode: scans app/pages/ and collects only static (non-dynamic) routes
29
- * plus any dynamic routes that provide ssg.paths().
30
- * For explicit string[] mode: uses those paths directly.
31
- */
32
- /**
33
- * Expands a set of base paths into locale-prefixed variants when i18n is
34
- * configured. Skips expansion for `no_prefix` strategy.
35
- */
36
- function _expandWithLocales(
37
- paths: string[],
38
- i18n: ResolvedCerConfig['i18n'],
39
- ): string[] {
40
- if (!i18n || i18n.strategy === 'no_prefix') return paths
41
- const { locales, defaultLocale, strategy } = i18n
42
- const expanded: string[] = []
43
- for (const p of paths) {
44
- for (const locale of locales) {
45
- const isDefault = locale === defaultLocale
46
- if (isDefault && strategy === 'prefix_except_default') {
47
- expanded.push(p)
48
- } else {
49
- expanded.push(`/${locale}${p === '/' ? '' : p}`)
50
- }
51
- }
52
- }
53
- return [...new Set(expanded)]
54
- }
55
-
56
- async function collectSsgPaths(
57
- config: ResolvedCerConfig,
58
- viteUserConfig: UserConfig,
59
- ): Promise<string[]> {
60
- const ssgConfig = config.ssg
61
-
62
- if (Array.isArray(ssgConfig.routes) && ssgConfig.routes.length > 0) {
63
- return _expandWithLocales(ssgConfig.routes, config.i18n)
64
- }
65
-
66
- // Auto-discover paths
67
- const paths: string[] = ['/']
68
-
69
- if (!existsSync(config.pagesDir)) return paths
70
-
71
- const files = await fg('**/*.ts', {
72
- cwd: config.pagesDir,
73
- absolute: true,
74
- onlyFiles: true,
75
- })
76
-
77
- const staticFiles: string[] = []
78
- const dynamicFiles: Array<{
79
- file: string
80
- entry: ReturnType<typeof buildRouteEntry>
81
- usesQueryContent: boolean
82
- }> = []
83
-
84
- for (const file of files) {
85
- // Skip routes that declare render: 'server' or render: 'spa' — they are
86
- // either always-SSR or client-only and must not be pre-rendered.
87
- let src = ''
88
- try {
89
- src = await readFile(file, 'utf-8')
90
- const renderMatch = src.match(/render\s*:\s*['"]([^'"]+)['"]/)
91
- const renderMode = renderMatch ? renderMatch[1] : null
92
- if (renderMode === 'server' || renderMode === 'spa') continue
93
- } catch { /* ignore read errors */ }
94
-
95
- const entry = buildRouteEntry(file, config.pagesDir)
96
- const usesQueryContent = /\bqueryContent\s*\(/.test(src)
97
-
98
- if (!entry.isDynamic && !entry.isCatchAll) {
99
- staticFiles.push(file)
100
- if (entry.routePath !== '/') {
101
- paths.push(entry.routePath)
102
- }
103
- } else if (entry.isDynamic) {
104
- dynamicFiles.push({ file, entry, usesQueryContent })
105
- }
106
- }
107
-
108
- if (dynamicFiles.length > 0) {
109
- // Use a Vite SSR dev server to load page modules with auto-imports applied
110
- const viteServer = await createServer({
111
- ...viteUserConfig,
112
- root: config.root,
113
- server: { middlewareMode: true },
114
- appType: 'custom',
115
- logLevel: 'silent',
116
- })
117
-
118
- try {
119
- for (const { file, entry, usesQueryContent } of dynamicFiles) {
120
- try {
121
- const pageMod = await viteServer.ssrLoadModule(file)
122
- const pageMeta = pageMod.meta ?? pageMod.pageMeta
123
-
124
- if (pageMeta?.render === 'server' || pageMeta?.render === 'spa') continue
125
- if (pageMeta?.ssg?.paths) {
126
- const pathsResult = await pageMeta.ssg.paths()
127
- for (const ctx of pathsResult) {
128
- let resolvedPath = entry.routePath
129
- for (const [key, value] of Object.entries(ctx.params as Record<string, unknown>)) {
130
- resolvedPath = resolvedPath.replace(`:${key}*`, String(value))
131
- resolvedPath = resolvedPath.replace(`:${key}`, String(value))
132
- }
133
- paths.push(resolvedPath)
134
- }
135
- continue
136
- }
137
-
138
- if (entry.isCatchAll && usesQueryContent) {
139
- const contentStore = (globalThis as Record<string, unknown>)[CONTENT_STORE_KEY] as ContentItem[] | undefined
140
- const catchAllPaths = _collectCatchAllContentPaths(entry.routePath, contentStore ?? [])
141
- paths.push(...catchAllPaths)
142
- }
143
- } catch {
144
- console.warn(`[cer-app] Could not enumerate paths for ${file}`)
145
- }
146
- }
147
- } finally {
148
- await viteServer.close()
149
- }
150
- }
151
-
152
- // When i18n is configured, expand every collected path into locale-prefixed
153
- // variants so each locale gets its own pre-rendered HTML file.
154
- // strategy 'prefix' → /en/about, /fr/about
155
- // strategy 'prefix_except_default' → /about, /fr/about
156
- // strategy 'no_prefix' → no expansion (locale detected from header/cookie only)
157
- if (config.i18n && config.i18n.strategy !== 'no_prefix') {
158
- const { locales, defaultLocale, strategy } = config.i18n
159
- const expanded: string[] = []
160
- for (const p of paths) {
161
- for (const locale of locales) {
162
- const isDefault = locale === defaultLocale
163
- if (isDefault && strategy === 'prefix_except_default') {
164
- expanded.push(p)
165
- } else {
166
- expanded.push(`/${locale}${p === '/' ? '' : p}`)
167
- }
168
- }
169
- }
170
- return [...new Set(expanded)]
171
- }
172
-
173
- return [...new Set(paths)] // deduplicate
174
- }
175
-
176
- function _collectCatchAllContentPaths(routePath: string, store: ContentItem[]): string[] {
177
- if (store.length === 0) return []
178
-
179
- const prefix = routePath
180
- .replace(/:[^/]+\*$/, '')
181
- .replace(/\/+$/, '') || '/'
182
-
183
- return store
184
- .map((item) => item._path)
185
- .filter((contentPath) => {
186
- if (prefix === '/') return true
187
- return contentPath === prefix || contentPath.startsWith(prefix + '/')
188
- })
189
- }
190
-
191
- // Cache the server module across renderPath calls (loaded once per SSG run)
192
- let _serverMod: Record<string, unknown> | null = null
193
-
194
- /**
195
- * Renders a single path using the SSR server bundle and returns the HTML.
196
- *
197
- * The server bundle's handler already merges the SSR output with
198
- * dist/client/index.html internally (via the _mergeWithClientTemplate helper
199
- * it embeds at build time), so this function simply captures the response.
200
- */
201
- async function renderPath(
202
- path: string,
203
- serverBundlePath: string,
204
- ): Promise<string> {
205
- // Load server bundle once
206
- if (!_serverMod) {
207
- try {
208
- _serverMod = await import(serverBundlePath) as Record<string, unknown>
209
- } catch (err) {
210
- throw new Error(`Failed to load server bundle at ${serverBundlePath}: ${err}`)
211
- }
212
- }
213
-
214
- const handlerFn =
215
- (typeof _serverMod['handler'] === 'function' ? _serverMod['handler'] : null) ??
216
- (typeof (_serverMod['default'] as Record<string, unknown> | undefined)?.['handler'] === 'function'
217
- ? (_serverMod['default'] as Record<string, unknown>)['handler']
218
- : null)
219
-
220
- if (typeof handlerFn !== 'function') {
221
- console.warn(`[cer-app] No handler function found in server bundle for path: ${path}`)
222
- return ''
223
- }
224
-
225
- // Mock req/res for the Express-style handler.
226
- // The handler internally merges with dist/client/index.html, so we just
227
- // capture whatever it writes/ends with.
228
- const mockReq = { url: path, headers: {} }
229
- return new Promise<string>((resolve, reject) => {
230
- const chunks: string[] = []
231
- const mockRes = {
232
- setHeader: () => {},
233
- write: (chunk: string) => { chunks.push(chunk) },
234
- end: (body?: string) => resolve(chunks.join('') + (body ?? '')),
235
- }
236
- ;(handlerFn as (req: unknown, res: unknown) => Promise<void>)(mockReq, mockRes).catch(reject)
237
- })
238
- }
239
-
240
- /**
241
- * Writes the rendered HTML to the output directory.
242
- * path '/' -> dist/index.html
243
- * path '/about' -> dist/about/index.html
244
- * @internal exported for unit testing
245
- */
246
- export async function writeRenderedPath(
247
- path: string,
248
- html: string,
249
- distDir: string,
250
- ): Promise<void> {
251
- let outputPath: string
252
- if (path === '/') {
253
- outputPath = join(distDir, 'index.html')
254
- } else {
255
- // Normalize path and create directory
256
- const cleanPath = path.replace(/^\//, '').replace(/\/$/, '')
257
- outputPath = join(distDir, cleanPath, 'index.html')
258
- }
259
-
260
- await mkdir(join(outputPath, '..'), { recursive: true })
261
- await writeFile(outputPath, html, 'utf-8')
262
- }
263
-
264
- /**
265
- * Detects which favicon href to use from the project's public directory.
266
- * Prefers .svg > .ico > .png. Returns null when none is found.
267
- */
268
- function detectFaviconHref(root: string): string | null {
269
- const candidates = ['/favicon.svg', '/favicon.ico', '/favicon.png']
270
- for (const href of candidates) {
271
- if (existsSync(join(root, 'public', href.slice(1)))) return href
272
- }
273
- return null
274
- }
275
-
276
- /**
277
- * Applies all HTML post-processing transforms to a rendered page.
278
- *
279
- * - Injects `<link rel="icon">` when a favicon exists in public/ and none
280
- * is already declared in the HTML.
281
- * - Injects `<link rel="canonical">` when `config.siteUrl` is set and none
282
- * is already declared.
283
- * - Adds `rel="noopener noreferrer"` to every `<a target="_blank">` link
284
- * that is missing it.
285
- */
286
- function postProcessHtml(
287
- html: string,
288
- path: string,
289
- config: ResolvedCerConfig,
290
- faviconHref: string | null,
291
- ): string {
292
- let out = html
293
-
294
- if (faviconHref) {
295
- out = injectFaviconLink(out, faviconHref)
296
- }
297
-
298
- if (config.siteUrl) {
299
- const canonicalUrl = config.siteUrl + (path === '/' ? '' : path)
300
- out = injectCanonicalLink(out, canonicalUrl)
301
- }
302
-
303
- out = addNoopenerToExternalLinks(out)
304
-
305
- return out
306
- }
307
-
308
- /**
309
- * Full SSG build pipeline:
310
- * 1. Run the SSR dual-build (client + server bundles)
311
- * 2. Enumerate all paths to generate
312
- * 3. Render each path using the server bundle
313
- * 4. Post-process HTML (favicon, canonical, noopener)
314
- * 5. Write HTML files to dist/
315
- * 6. Write robots.txt (when not already present in public/)
316
- * 7. Write ssg-manifest.json
317
- */
318
- export async function buildSSG(
319
- config: ResolvedCerConfig,
320
- viteUserConfig: UserConfig = {},
321
- ): Promise<void> {
322
- const distDir = join(config.root, 'dist')
323
- const serverDistDir = join(distDir, 'server')
324
- const serverBundlePath = join(serverDistDir, 'server.js')
325
-
326
- console.log('[cer-app] Starting SSG build...')
327
-
328
- // Step 1: Run the SSR build to produce client + server bundles
329
- await buildSSR(config, viteUserConfig)
330
-
331
- // Step 2: Collect paths to generate
332
- console.log('[cer-app] Collecting SSG paths...')
333
- const paths = await collectSsgPaths(config, viteUserConfig)
334
- console.log(`[cer-app] Found ${paths.length} path(s) to generate:`, paths)
335
-
336
- // Detect favicon once for use in every page's post-processing pass.
337
- const faviconHref = detectFaviconHref(config.root)
338
-
339
- // Step 3+4+5: Render, post-process, and write paths with bounded concurrency.
340
- // The server bundle uses per-request router instances (initRouter returns the
341
- // router; the factory passes it to createStreamingSSRHandler as { vnode, router })
342
- // so concurrent renders are safe — each request carries its own router with its
343
- // own URL state and never reads from the shared activeRouterProxy singleton.
344
- const concurrency = config.ssg?.concurrency ?? 4
345
- console.log(`[cer-app] Rendering ${paths.length} path(s) with concurrency ${concurrency}...`)
346
-
347
- const generatedPaths: string[] = []
348
- const errors: Array<{ path: string; error: string }> = []
349
-
350
- // Process paths in chunks of `concurrency` so we don't overwhelm the process
351
- // with hundreds of simultaneous renders on very large sites.
352
- for (let i = 0; i < paths.length; i += concurrency) {
353
- const chunk = paths.slice(i, i + concurrency)
354
- const results = await Promise.allSettled(
355
- chunk.map(async (path) => {
356
- console.log(`[cer-app] Generating: ${path}`)
357
- const raw = await renderPath(path, serverBundlePath)
358
- const html = postProcessHtml(raw, path, config, faviconHref)
359
- await writeRenderedPath(path, html, distDir)
360
- return path
361
- }),
362
- )
363
- for (let j = 0; j < results.length; j++) {
364
- const result = results[j]
365
- if (result.status === 'fulfilled') {
366
- generatedPaths.push(result.value)
367
- } else {
368
- const errorMsg = String(result.reason)
369
- console.error(`[cer-app] Failed to generate ${chunk[j]}: ${errorMsg}`)
370
- errors.push({ path: chunk[j], error: errorMsg })
371
- }
372
- }
373
- }
374
-
375
- // Step 6: Write robots.txt unless the project supplies its own via public/robots.txt,
376
- // which Vite copies to dist/ as-is. Always overwrite any previously generated file so
377
- // that siteUrl changes (e.g. adding the Sitemap directive) take effect on rebuild.
378
- const publicRobots = join(config.root, 'public', 'robots.txt')
379
- if (!existsSync(publicRobots)) {
380
- const distRobots = join(distDir, 'robots.txt')
381
- await mkdir(distDir, { recursive: true })
382
- await writeFile(distRobots, generateRobotsTxt(config.siteUrl), 'utf-8')
383
- console.log('[cer-app] Generated robots.txt')
384
- }
385
-
386
- // Step 7: Write SSG manifest
387
- const manifest: SsgManifest = {
388
- generatedAt: new Date().toISOString(),
389
- paths: generatedPaths,
390
- errors,
391
- }
392
-
393
- const manifestPath = join(distDir, 'ssg-manifest.json')
394
- await mkdir(distDir, { recursive: true })
395
- await writeFile(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8')
396
-
397
- console.log(`[cer-app] SSG build complete.`)
398
- console.log(` Generated ${generatedPaths.length} page(s).`)
399
- if (errors.length > 0) {
400
- console.warn(` ${errors.length} error(s) — see ${manifestPath} for details.`)
401
- }
402
- console.log(` Manifest: ${manifestPath}`)
403
- }
@@ -1,134 +0,0 @@
1
- import { build, type UserConfig } from 'vite'
2
- import { join, resolve } from 'pathe'
3
- import { existsSync, renameSync } from 'node:fs'
4
- import type { ResolvedCerConfig } from './dev-server.js'
5
- import { getGeneratedDir, writeGeneratedDir } from './generated-dir.js'
6
- import { ENTRY_SERVER_TEMPLATE } from '../runtime/entry-server-template.js'
7
-
8
- /**
9
- * Resolves the client build entry point for an SSR/SSG build.
10
- *
11
- * Priority order:
12
- * 1. `index.html` at the project root — consumer-provided HTML shell.
13
- * 2. `.cer/index.html` — auto-generated HTML shell (Nuxt-style magic).
14
- * 3. `app/entry-client.ts` — fallback for projects that manage HTML externally.
15
- * 4. `app/app.ts` — last resort (same bundle, no DSD hydration preamble).
16
- */
17
- export function resolveClientEntry(config: ResolvedCerConfig): string {
18
- const indexHtml = resolve(config.root, 'index.html')
19
- if (existsSync(indexHtml)) return indexHtml
20
- const cerIndexHtml = join(getGeneratedDir(config.root), 'index.html')
21
- if (existsSync(cerIndexHtml)) return cerIndexHtml
22
- const entryClient = resolve(config.srcDir, 'entry-client.ts')
23
- if (existsSync(entryClient)) return entryClient
24
- return resolve(config.srcDir, 'app.ts')
25
- }
26
-
27
- function generateServerEntryCode(): string {
28
- return ENTRY_SERVER_TEMPLATE
29
- }
30
-
31
- /**
32
- * Runs the dual (client + server) SSR build using Vite's programmatic API.
33
- *
34
- * 1. Client bundle: normal Vite build (outputs to dist/client)
35
- * 2. Server bundle: SSR build (outputs to dist/server), uses a generated entry
36
- */
37
- export async function buildSSR(
38
- config: ResolvedCerConfig,
39
- viteUserConfig: UserConfig = {},
40
- ): Promise<void> {
41
- const clientOutDir = join(config.root, 'dist/client')
42
- const serverOutDir = join(config.root, 'dist/server')
43
-
44
- // Write .cer/ generated files BEFORE resolving the client entry so that
45
- // .cer/index.html is on disk when resolveClientEntry checks for it.
46
- writeGeneratedDir(config)
47
-
48
- // Resolve the client entry — index.html is preferred so Vite writes a
49
- // processed index.html to dist/client/ for use as the SSG shell template.
50
- const clientEntry = resolveClientEntry(config)
51
-
52
- // Build the client bundle
53
- console.log('[cer-app] Building client bundle...')
54
- await build({
55
- ...viteUserConfig,
56
- root: config.root,
57
- build: {
58
- ...viteUserConfig.build,
59
- outDir: clientOutDir,
60
- ssrManifest: true,
61
- rollupOptions: {
62
- input: clientEntry,
63
- },
64
- },
65
- })
66
-
67
- // If the client entry was .cer/index.html, Vite outputs it as
68
- // dist/client/.cer/index.html (preserving relative path). The SSR server
69
- // template expects dist/client/index.html, so rename it into place.
70
- const generatedHtmlOut = join(clientOutDir, '.cer/index.html')
71
- const rootHtmlOut = join(clientOutDir, 'index.html')
72
- if (existsSync(generatedHtmlOut) && !existsSync(rootHtmlOut)) {
73
- renameSync(generatedHtmlOut, rootHtmlOut)
74
- }
75
-
76
- // Generate server entry source inline via a virtual plugin
77
- const serverEntryCode = generateServerEntryCode()
78
- const VIRTUAL_SERVER_ENTRY = 'virtual:cer-server-entry'
79
- const RESOLVED_SERVER_ENTRY = '\0virtual:cer-server-entry'
80
-
81
- // Build the server (SSR) bundle
82
- console.log('[cer-app] Building server bundle...')
83
- await build({
84
- ...viteUserConfig,
85
- root: config.root,
86
- plugins: [
87
- ...(viteUserConfig.plugins ?? []),
88
- {
89
- name: 'vite-plugin-cer-server-entry',
90
- enforce: 'pre' as const,
91
- resolveId(id: string) {
92
- if (id === VIRTUAL_SERVER_ENTRY) return RESOLVED_SERVER_ENTRY
93
- },
94
- load(id: string) {
95
- if (id === RESOLVED_SERVER_ENTRY) return serverEntryCode
96
- },
97
- },
98
- ],
99
- build: {
100
- ...viteUserConfig.build,
101
- outDir: serverOutDir,
102
- ssr: true,
103
- rollupOptions: {
104
- input: VIRTUAL_SERVER_ENTRY,
105
- output: {
106
- entryFileNames: 'server.js',
107
- },
108
- },
109
- },
110
- ssr: {
111
- // Keep vite-plugin-cer-app inlined so its virtual-module composables
112
- // (useRoute, useState, useFetch, etc.) are available in the server bundle.
113
- //
114
- // Do NOT add @jasonshimmy/custom-elements-runtime here. Inlining it
115
- // creates a second, isolated copy of the component registry (the module-
116
- // level Map in namespace-helpers). Third-party CER component libraries
117
- // (e.g. @jasonshimmy/cer-material) are external and resolve the runtime
118
- // from node_modules at runtime, giving them a *different* Map instance.
119
- // That means components registered by plugins never appear in the
120
- // renderer's registry → renderToStreamWithJITCSSDSD emits bare stubs
121
- // with no DSD → FOUC when the browser upgrades those elements.
122
- //
123
- // By keeping the runtime external both the server bundle and all
124
- // third-party plugins resolve it from node_modules at runtime, sharing
125
- // one Map and one registry, so DSD is generated for all registered
126
- // components regardless of which package called component().
127
- noExternal: ['@jasonshimmy/vite-plugin-cer-app'],
128
- },
129
- })
130
-
131
- console.log('[cer-app] SSR build complete.')
132
- console.log(` Client: ${clientOutDir}`)
133
- console.log(` Server: ${serverOutDir}`)
134
- }
@@ -1,50 +0,0 @@
1
- import { writeFileSync, mkdirSync } from 'node:fs'
2
- import { join, dirname } from 'pathe'
3
- import type { ContentItem, ContentMeta } from '../../types/content.js'
4
- import { toContentMeta } from './parser.js'
5
-
6
- /**
7
- * Converts a `_path` to the relative file path under `_content/`.
8
- *
9
- * Special case: `_path === '/'` writes to `_content/index.json` rather than
10
- * `_content/.json` (which would be invalid on most filesystems and confusing).
11
- */
12
- export function contentPathToFile(path: string): string {
13
- if (path === '/') return 'index.json'
14
- // Remove leading slash, append .json
15
- return path.slice(1) + '.json'
16
- }
17
-
18
- /**
19
- * Writes all content output files to `<outDir>/_content/`:
20
- *
21
- * - `manifest.json` — `ContentMeta[]` (no body, no toc, no excerpt)
22
- * - `search-index.json` — serialised MiniSearch index string
23
- * - `[path].json` — full `ContentItem` per document
24
- *
25
- * `router.base` is NOT prepended here — that is a client-side fetch concern.
26
- */
27
- export function emitContentFiles(
28
- items: ContentItem[],
29
- outDir: string,
30
- searchIndexJson: string,
31
- ): void {
32
- const contentDir = join(outDir, '_content')
33
- mkdirSync(contentDir, { recursive: true })
34
-
35
- // manifest.json — lean metadata only
36
- const manifest: ContentMeta[] = items.map(toContentMeta)
37
- writeFileSync(join(contentDir, 'manifest.json'), JSON.stringify(manifest), 'utf-8')
38
-
39
- // search-index.json
40
- writeFileSync(join(contentDir, 'search-index.json'), searchIndexJson, 'utf-8')
41
-
42
- // Per-document full JSON files
43
- for (const item of items) {
44
- const relFile = contentPathToFile(item._path)
45
- const absFile = join(contentDir, relFile)
46
- // Ensure subdirectory exists (e.g. _content/blog/ for _path: /blog/hello)
47
- mkdirSync(dirname(absFile), { recursive: true })
48
- writeFileSync(absFile, JSON.stringify(item), 'utf-8')
49
- }
50
- }