@jasonshimmy/vite-plugin-cer-app 0.23.1 → 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 (397) 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/commands/preview.d.ts.map +1 -1
  18. package/dist/cli/commands/preview.js +37 -4
  19. package/dist/cli/commands/preview.js.map +1 -1
  20. package/dist/cli/create/index.d.ts +11 -1
  21. package/dist/cli/create/index.d.ts.map +1 -1
  22. package/dist/cli/create/index.js +135 -65
  23. package/dist/cli/create/index.js.map +1 -1
  24. package/dist/cli/create/templates/spa/package.json.tpl +5 -3
  25. package/dist/cli/create/templates/ssg/cer.config.ts.tpl +2 -0
  26. package/dist/cli/create/templates/ssg/package.json.tpl +5 -3
  27. package/dist/cli/create/templates/ssr/package.json.tpl +5 -3
  28. package/dist/cli/index.js +2 -0
  29. package/dist/cli/index.js.map +1 -1
  30. package/dist/index.d.ts +3 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/plugin/build-ssg.d.ts +22 -4
  33. package/dist/plugin/build-ssg.d.ts.map +1 -1
  34. package/dist/plugin/build-ssg.js +273 -13
  35. package/dist/plugin/build-ssg.js.map +1 -1
  36. package/dist/plugin/content/parser.d.ts.map +1 -1
  37. package/dist/plugin/content/parser.js +54 -10
  38. package/dist/plugin/content/parser.js.map +1 -1
  39. package/dist/plugin/dev-server.d.ts +6 -1
  40. package/dist/plugin/dev-server.d.ts.map +1 -1
  41. package/dist/plugin/dev-server.js.map +1 -1
  42. package/dist/plugin/dts-generator.d.ts.map +1 -1
  43. package/dist/plugin/dts-generator.js +50 -8
  44. package/dist/plugin/dts-generator.js.map +1 -1
  45. package/dist/plugin/generated-dir.d.ts +2 -0
  46. package/dist/plugin/generated-dir.d.ts.map +1 -1
  47. package/dist/plugin/generated-dir.js +17 -6
  48. package/dist/plugin/generated-dir.js.map +1 -1
  49. package/dist/plugin/html-post-process.d.ts +35 -0
  50. package/dist/plugin/html-post-process.d.ts.map +1 -0
  51. package/dist/plugin/html-post-process.js +112 -0
  52. package/dist/plugin/html-post-process.js.map +1 -0
  53. package/dist/plugin/index.d.ts +9 -0
  54. package/dist/plugin/index.d.ts.map +1 -1
  55. package/dist/plugin/index.js +89 -14
  56. package/dist/plugin/index.js.map +1 -1
  57. package/dist/plugin/transforms/auto-import.d.ts.map +1 -1
  58. package/dist/plugin/transforms/auto-import.js +7 -0
  59. package/dist/plugin/transforms/auto-import.js.map +1 -1
  60. package/dist/plugin/transforms/prune-runtime-css.d.ts +8 -0
  61. package/dist/plugin/transforms/prune-runtime-css.d.ts.map +1 -0
  62. package/dist/plugin/transforms/prune-runtime-css.js +40 -0
  63. package/dist/plugin/transforms/prune-runtime-css.js.map +1 -0
  64. package/dist/runtime/app-template.d.ts +1 -4
  65. package/dist/runtime/app-template.d.ts.map +1 -1
  66. package/dist/runtime/app-template.js +211 -40
  67. package/dist/runtime/app-template.js.map +1 -1
  68. package/dist/runtime/composables/index.d.ts +4 -0
  69. package/dist/runtime/composables/index.d.ts.map +1 -1
  70. package/dist/runtime/composables/index.js +2 -0
  71. package/dist/runtime/composables/index.js.map +1 -1
  72. package/dist/runtime/composables/use-active-headings.d.ts +24 -0
  73. package/dist/runtime/composables/use-active-headings.d.ts.map +1 -0
  74. package/dist/runtime/composables/use-active-headings.js +112 -0
  75. package/dist/runtime/composables/use-active-headings.js.map +1 -0
  76. package/dist/runtime/composables/use-content-page.d.ts +45 -0
  77. package/dist/runtime/composables/use-content-page.d.ts.map +1 -0
  78. package/dist/runtime/composables/use-content-page.js +179 -0
  79. package/dist/runtime/composables/use-content-page.js.map +1 -0
  80. package/dist/runtime/composables/use-content-search.d.ts.map +1 -1
  81. package/dist/runtime/composables/use-content-search.js +1 -5
  82. package/dist/runtime/composables/use-content-search.js.map +1 -1
  83. package/dist/runtime/composables/use-fetch.d.ts +2 -1
  84. package/dist/runtime/composables/use-fetch.d.ts.map +1 -1
  85. package/dist/runtime/composables/use-fetch.js +112 -43
  86. package/dist/runtime/composables/use-fetch.js.map +1 -1
  87. package/dist/runtime/composables/use-head.d.ts.map +1 -1
  88. package/dist/runtime/composables/use-head.js +30 -6
  89. package/dist/runtime/composables/use-head.js.map +1 -1
  90. package/dist/runtime/composables/use-route.d.ts.map +1 -1
  91. package/dist/runtime/composables/use-route.js +39 -11
  92. package/dist/runtime/composables/use-route.js.map +1 -1
  93. package/dist/runtime/content/client.js +2 -2
  94. package/dist/runtime/content/client.js.map +1 -1
  95. package/dist/runtime/entry-server-template.d.ts +16 -1
  96. package/dist/runtime/entry-server-template.d.ts.map +1 -1
  97. package/dist/runtime/entry-server-template.js +120 -13
  98. package/dist/runtime/entry-server-template.js.map +1 -1
  99. package/dist/types/config.d.ts +53 -4
  100. package/dist/types/config.d.ts.map +1 -1
  101. package/dist/types/config.js.map +1 -1
  102. package/dist/types/middleware.d.ts +2 -2
  103. package/dist/types/middleware.d.ts.map +1 -1
  104. package/package.json +22 -19
  105. package/.github/copilot-instructions.md +0 -169
  106. package/.github/workflows/publish.yml +0 -257
  107. package/.nvmrc +0 -1
  108. package/CHANGELOG.md +0 -232
  109. package/CLAUDE.md +0 -113
  110. package/commits.txt +0 -1
  111. package/cypress.config.ts +0 -16
  112. package/docs/authentication.md +0 -285
  113. package/docs/cli.md +0 -324
  114. package/docs/components.md +0 -237
  115. package/docs/composables.md +0 -907
  116. package/docs/configuration.md +0 -667
  117. package/docs/content.md +0 -570
  118. package/docs/data-loading.md +0 -336
  119. package/docs/getting-started.md +0 -237
  120. package/docs/head-management.md +0 -212
  121. package/docs/i18n.md +0 -159
  122. package/docs/layouts.md +0 -224
  123. package/docs/middleware.md +0 -234
  124. package/docs/plugins.md +0 -170
  125. package/docs/rendering-modes.md +0 -377
  126. package/docs/routing.md +0 -485
  127. package/docs/server-api.md +0 -253
  128. package/docs/testing.md +0 -455
  129. package/docs/use-fetch.md +0 -183
  130. package/e2e/cypress/e2e/api.cy.ts +0 -123
  131. package/e2e/cypress/e2e/async-component.cy.ts +0 -27
  132. package/e2e/cypress/e2e/component-splitting.cy.ts +0 -50
  133. package/e2e/cypress/e2e/content.cy.ts +0 -425
  134. package/e2e/cypress/e2e/cookie.cy.ts +0 -85
  135. package/e2e/cypress/e2e/data.cy.ts +0 -158
  136. package/e2e/cypress/e2e/error-boundary.cy.ts +0 -88
  137. package/e2e/cypress/e2e/fouc.cy.ts +0 -254
  138. package/e2e/cypress/e2e/group-meta.cy.ts +0 -36
  139. package/e2e/cypress/e2e/head.cy.ts +0 -89
  140. package/e2e/cypress/e2e/i18n.cy.ts +0 -79
  141. package/e2e/cypress/e2e/interactive.cy.ts +0 -137
  142. package/e2e/cypress/e2e/isr-nested-runtime.cy.ts +0 -102
  143. package/e2e/cypress/e2e/jit-css-custom-colors.cy.ts +0 -43
  144. package/e2e/cypress/e2e/middleware-chain.cy.ts +0 -89
  145. package/e2e/cypress/e2e/middleware-status.cy.ts +0 -30
  146. package/e2e/cypress/e2e/middleware.cy.ts +0 -45
  147. package/e2e/cypress/e2e/navigate.cy.ts +0 -39
  148. package/e2e/cypress/e2e/observability.cy.ts +0 -77
  149. package/e2e/cypress/e2e/per-route-error.cy.ts +0 -42
  150. package/e2e/cypress/e2e/per-route-render.cy.ts +0 -70
  151. package/e2e/cypress/e2e/preview-hardening.cy.ts +0 -88
  152. package/e2e/cypress/e2e/routes.cy.ts +0 -128
  153. package/e2e/cypress/e2e/seo-meta.cy.ts +0 -108
  154. package/e2e/cypress/e2e/server-middleware.cy.ts +0 -46
  155. package/e2e/cypress/e2e/session-rotation.cy.ts +0 -25
  156. package/e2e/cypress/e2e/session.cy.ts +0 -73
  157. package/e2e/cypress/e2e/ssr-render-error.cy.ts +0 -68
  158. package/e2e/cypress/e2e/synthetic-404.cy.ts +0 -45
  159. package/e2e/cypress/e2e/use-page-data.cy.ts +0 -122
  160. package/e2e/cypress/e2e/use-state.cy.ts +0 -138
  161. package/e2e/cypress/support/commands.ts +0 -120
  162. package/e2e/cypress/support/e2e.ts +0 -10
  163. package/e2e/cypress/tsconfig.json +0 -14
  164. package/e2e/kitchen-sink/app/components/ks-badge.ts +0 -8
  165. package/e2e/kitchen-sink/app/composables/useKsCounter.ts +0 -9
  166. package/e2e/kitchen-sink/app/error.ts +0 -18
  167. package/e2e/kitchen-sink/app/layouts/admin.ts +0 -13
  168. package/e2e/kitchen-sink/app/layouts/default.ts +0 -25
  169. package/e2e/kitchen-sink/app/layouts/group.ts +0 -9
  170. package/e2e/kitchen-sink/app/layouts/minimal.ts +0 -7
  171. package/e2e/kitchen-sink/app/loading.ts +0 -9
  172. package/e2e/kitchen-sink/app/middleware/auth.ts +0 -9
  173. package/e2e/kitchen-sink/app/middleware/custom-log.ts +0 -4
  174. package/e2e/kitchen-sink/app/middleware/group-auth.ts +0 -7
  175. package/e2e/kitchen-sink/app/middleware/logger.ts +0 -14
  176. package/e2e/kitchen-sink/app/pages/(auth)/login.ts +0 -13
  177. package/e2e/kitchen-sink/app/pages/(auth)/protected.ts +0 -16
  178. package/e2e/kitchen-sink/app/pages/404.ts +0 -9
  179. package/e2e/kitchen-sink/app/pages/about.ts +0 -17
  180. package/e2e/kitchen-sink/app/pages/admin/_layout.ts +0 -1
  181. package/e2e/kitchen-sink/app/pages/admin/dashboard.ts +0 -11
  182. package/e2e/kitchen-sink/app/pages/async-component-error-test.ts +0 -18
  183. package/e2e/kitchen-sink/app/pages/async-component-test.ts +0 -18
  184. package/e2e/kitchen-sink/app/pages/blog/[slug].ts +0 -59
  185. package/e2e/kitchen-sink/app/pages/blog/index.ts +0 -51
  186. package/e2e/kitchen-sink/app/pages/content-blog.ts +0 -37
  187. package/e2e/kitchen-sink/app/pages/content-doc.ts +0 -42
  188. package/e2e/kitchen-sink/app/pages/content-fallback.ts +0 -36
  189. package/e2e/kitchen-sink/app/pages/content-guides.ts +0 -35
  190. package/e2e/kitchen-sink/app/pages/content-index.ts +0 -39
  191. package/e2e/kitchen-sink/app/pages/content-search.ts +0 -36
  192. package/e2e/kitchen-sink/app/pages/cookie-test.ts +0 -22
  193. package/e2e/kitchen-sink/app/pages/counter.ts +0 -17
  194. package/e2e/kitchen-sink/app/pages/group-auth-blocked.ts +0 -9
  195. package/e2e/kitchen-sink/app/pages/group-meta-test/_layout.ts +0 -6
  196. package/e2e/kitchen-sink/app/pages/group-meta-test/custom-mw.ts +0 -14
  197. package/e2e/kitchen-sink/app/pages/group-meta-test/page.ts +0 -9
  198. package/e2e/kitchen-sink/app/pages/group-meta-test/protected.ts +0 -8
  199. package/e2e/kitchen-sink/app/pages/head.ts +0 -20
  200. package/e2e/kitchen-sink/app/pages/i18n-test.ts +0 -14
  201. package/e2e/kitchen-sink/app/pages/index.ts +0 -27
  202. package/e2e/kitchen-sink/app/pages/isr-test.ts +0 -17
  203. package/e2e/kitchen-sink/app/pages/items/[id].ts +0 -20
  204. package/e2e/kitchen-sink/app/pages/jit-css-custom-colors-test.ts +0 -14
  205. package/e2e/kitchen-sink/app/pages/loader-error-test.ts +0 -13
  206. package/e2e/kitchen-sink/app/pages/loader-props-test.ts +0 -19
  207. package/e2e/kitchen-sink/app/pages/loader-response-error-test.ts +0 -13
  208. package/e2e/kitchen-sink/app/pages/middleware-chain-test.ts +0 -12
  209. package/e2e/kitchen-sink/app/pages/middleware-status-test.ts +0 -9
  210. package/e2e/kitchen-sink/app/pages/navigate-test.ts +0 -16
  211. package/e2e/kitchen-sink/app/pages/observability-test.ts +0 -25
  212. package/e2e/kitchen-sink/app/pages/per-route-error-test.error.ts +0 -13
  213. package/e2e/kitchen-sink/app/pages/per-route-error-test.ts +0 -15
  214. package/e2e/kitchen-sink/app/pages/plugin-dsd-test.ts +0 -10
  215. package/e2e/kitchen-sink/app/pages/render-error-test.ts +0 -12
  216. package/e2e/kitchen-sink/app/pages/render-server-test.ts +0 -12
  217. package/e2e/kitchen-sink/app/pages/render-spa-test.ts +0 -12
  218. package/e2e/kitchen-sink/app/pages/route-info.ts +0 -14
  219. package/e2e/kitchen-sink/app/pages/seo-test.ts +0 -23
  220. package/e2e/kitchen-sink/app/pages/session-rotation-test.ts +0 -25
  221. package/e2e/kitchen-sink/app/pages/use-state-test.ts +0 -37
  222. package/e2e/kitchen-sink/app/plugins/01.setup.ts +0 -7
  223. package/e2e/kitchen-sink/app/plugins/02.ks-plugin-components.ts +0 -27
  224. package/e2e/kitchen-sink/cer-auto-imports.d.ts +0 -51
  225. package/e2e/kitchen-sink/cer-env.d.ts +0 -35
  226. package/e2e/kitchen-sink/cer-tsconfig.json +0 -30
  227. package/e2e/kitchen-sink/cer.config.ts +0 -43
  228. package/e2e/kitchen-sink/content/01.guides/01.index.md +0 -8
  229. package/e2e/kitchen-sink/content/01.guides/02.intro.md +0 -8
  230. package/e2e/kitchen-sink/content/01.guides/10.advanced.md +0 -8
  231. package/e2e/kitchen-sink/content/blog/2026-04-01-hello.md +0 -26
  232. package/e2e/kitchen-sink/content/blog/2026-04-02-draft.md +0 -10
  233. package/e2e/kitchen-sink/content/blog/index.md +0 -8
  234. package/e2e/kitchen-sink/content/blog/no-frontmatter.md +0 -7
  235. package/e2e/kitchen-sink/content/docs/getting-started.md +0 -48
  236. package/e2e/kitchen-sink/content/index.md +0 -16
  237. package/e2e/kitchen-sink/server/api/echo.ts +0 -12
  238. package/e2e/kitchen-sink/server/api/health.ts +0 -3
  239. package/e2e/kitchen-sink/server/api/posts/[slug].ts +0 -11
  240. package/e2e/kitchen-sink/server/api/posts/index.ts +0 -5
  241. package/e2e/kitchen-sink/server/api/session.ts +0 -23
  242. package/e2e/kitchen-sink/server/data/posts.ts +0 -21
  243. package/e2e/kitchen-sink/server/middleware/01-headers.ts +0 -6
  244. package/e2e/kitchen-sink/server/middleware/02-status-test.ts +0 -10
  245. package/e2e/kitchen-sink/tsconfig.json +0 -3
  246. package/e2e/scripts/clean.mjs +0 -14
  247. package/eslint.config.ts +0 -22
  248. package/src/__tests__/cli/adapters/cloudflare-worker.integration.test.ts +0 -132
  249. package/src/__tests__/cli/adapters/cloudflare.test.ts +0 -332
  250. package/src/__tests__/cli/adapters/netlify-bridge.integration.test.ts +0 -139
  251. package/src/__tests__/cli/adapters/netlify.test.ts +0 -286
  252. package/src/__tests__/cli/adapters/vercel-launcher.integration.test.ts +0 -129
  253. package/src/__tests__/cli/adapters/vercel.test.ts +0 -263
  254. package/src/__tests__/cli/preview-hardening.test.ts +0 -265
  255. package/src/__tests__/cli/preview-isr.test.ts +0 -320
  256. package/src/__tests__/index.test.ts +0 -21
  257. package/src/__tests__/plugin/app-template.test.ts +0 -112
  258. package/src/__tests__/plugin/build-ssg-render.test.ts +0 -155
  259. package/src/__tests__/plugin/build-ssg.test.ts +0 -598
  260. package/src/__tests__/plugin/build-ssr.test.ts +0 -192
  261. package/src/__tests__/plugin/cer-app-plugin.test.ts +0 -552
  262. package/src/__tests__/plugin/content/emitter.test.ts +0 -117
  263. package/src/__tests__/plugin/content/loader.test.ts +0 -154
  264. package/src/__tests__/plugin/content/parser.test.ts +0 -381
  265. package/src/__tests__/plugin/content/path-utils.test.ts +0 -69
  266. package/src/__tests__/plugin/content/search.test.ts +0 -119
  267. package/src/__tests__/plugin/dev-server.test.ts +0 -813
  268. package/src/__tests__/plugin/dts-generator.test.ts +0 -394
  269. package/src/__tests__/plugin/entry-server-template.test.ts +0 -385
  270. package/src/__tests__/plugin/generated-dir.test.ts +0 -144
  271. package/src/__tests__/plugin/path-utils.test.ts +0 -411
  272. package/src/__tests__/plugin/resolve-config.test.ts +0 -200
  273. package/src/__tests__/plugin/scanner.test.ts +0 -186
  274. package/src/__tests__/plugin/transforms/auto-import.test.ts +0 -510
  275. package/src/__tests__/plugin/transforms/head-inject.test.ts +0 -178
  276. package/src/__tests__/plugin/virtual/composables.test.ts +0 -57
  277. package/src/__tests__/plugin/virtual/content-components.test.ts +0 -66
  278. package/src/__tests__/plugin/virtual/error.test.ts +0 -71
  279. package/src/__tests__/plugin/virtual/layouts.test.ts +0 -70
  280. package/src/__tests__/plugin/virtual/loading.test.ts +0 -72
  281. package/src/__tests__/plugin/virtual/middleware.test.ts +0 -83
  282. package/src/__tests__/plugin/virtual/plugins.test.ts +0 -129
  283. package/src/__tests__/plugin/virtual/routes.test.ts +0 -884
  284. package/src/__tests__/plugin/virtual/server-api.test.ts +0 -164
  285. package/src/__tests__/plugin/virtual/server-middleware.test.ts +0 -102
  286. package/src/__tests__/runtime/app-template.test.ts +0 -198
  287. package/src/__tests__/runtime/define-middleware.test.ts +0 -64
  288. package/src/__tests__/runtime/define-server-middleware.test.ts +0 -54
  289. package/src/__tests__/runtime/entry-client-template.test.ts +0 -61
  290. package/src/__tests__/runtime/isr-handler.test.ts +0 -338
  291. package/src/__tests__/runtime/oauth/handler.test.ts +0 -358
  292. package/src/__tests__/runtime/oauth/providers.test.ts +0 -47
  293. package/src/__tests__/runtime/oauth-index.test.ts +0 -43
  294. package/src/__tests__/runtime/use-auth.test.ts +0 -169
  295. package/src/__tests__/runtime/use-content-search-composable.test.ts +0 -405
  296. package/src/__tests__/runtime/use-content-search.test.ts +0 -163
  297. package/src/__tests__/runtime/use-content.test.ts +0 -226
  298. package/src/__tests__/runtime/use-cookie.test.ts +0 -277
  299. package/src/__tests__/runtime/use-fetch-component.test.ts +0 -214
  300. package/src/__tests__/runtime/use-fetch.test.ts +0 -377
  301. package/src/__tests__/runtime/use-head.test.ts +0 -266
  302. package/src/__tests__/runtime/use-inject-client.test.ts +0 -67
  303. package/src/__tests__/runtime/use-inject.test.ts +0 -66
  304. package/src/__tests__/runtime/use-locale.test.ts +0 -152
  305. package/src/__tests__/runtime/use-navigate.test.ts +0 -121
  306. package/src/__tests__/runtime/use-page-data.test.ts +0 -298
  307. package/src/__tests__/runtime/use-route.test.ts +0 -156
  308. package/src/__tests__/runtime/use-runtime-config.test.ts +0 -182
  309. package/src/__tests__/runtime/use-seo-meta.test.ts +0 -109
  310. package/src/__tests__/runtime/use-session.test.ts +0 -320
  311. package/src/__tests__/runtime/use-state.test.ts +0 -340
  312. package/src/__tests__/types/config.test.ts +0 -18
  313. package/src/cli/adapters/cloudflare.ts +0 -335
  314. package/src/cli/adapters/netlify.ts +0 -326
  315. package/src/cli/adapters/vercel.ts +0 -311
  316. package/src/cli/commands/adapt.ts +0 -84
  317. package/src/cli/commands/build.ts +0 -165
  318. package/src/cli/commands/dev.ts +0 -125
  319. package/src/cli/commands/generate.ts +0 -91
  320. package/src/cli/commands/preview-isr.ts +0 -172
  321. package/src/cli/commands/preview.ts +0 -489
  322. package/src/cli/create/index.ts +0 -275
  323. package/src/cli/create/templates/shared/.gitignore.tpl +0 -25
  324. package/src/cli/create/templates/shared/app/layouts/default.ts.tpl +0 -15
  325. package/src/cli/create/templates/shared/app/pages/index.ts.tpl +0 -8
  326. package/src/cli/create/templates/shared/index.html.tpl +0 -12
  327. package/src/cli/create/templates/shared/tsconfig.json.tpl +0 -6
  328. package/src/cli/create/templates/spa/cer.config.ts.tpl +0 -6
  329. package/src/cli/create/templates/spa/package.json.tpl +0 -18
  330. package/src/cli/create/templates/ssg/cer.config.ts.tpl +0 -10
  331. package/src/cli/create/templates/ssg/package.json.tpl +0 -19
  332. package/src/cli/create/templates/ssr/cer.config.ts.tpl +0 -6
  333. package/src/cli/create/templates/ssr/package.json.tpl +0 -18
  334. package/src/cli/index.ts +0 -22
  335. package/src/index.ts +0 -20
  336. package/src/plugin/build-ssg.ts +0 -336
  337. package/src/plugin/build-ssr.ts +0 -134
  338. package/src/plugin/content/emitter.ts +0 -50
  339. package/src/plugin/content/index.ts +0 -233
  340. package/src/plugin/content/parser.ts +0 -259
  341. package/src/plugin/content/path-utils.ts +0 -55
  342. package/src/plugin/content/scanner.ts +0 -26
  343. package/src/plugin/content/search.ts +0 -28
  344. package/src/plugin/dev-server.ts +0 -377
  345. package/src/plugin/dts-generator.ts +0 -273
  346. package/src/plugin/generated-dir.ts +0 -121
  347. package/src/plugin/index.ts +0 -553
  348. package/src/plugin/path-utils.ts +0 -186
  349. package/src/plugin/scanner.ts +0 -65
  350. package/src/plugin/transforms/auto-import.ts +0 -206
  351. package/src/plugin/transforms/head-inject.ts +0 -161
  352. package/src/plugin/virtual/composables.ts +0 -28
  353. package/src/plugin/virtual/content-components.ts +0 -83
  354. package/src/plugin/virtual/error.ts +0 -34
  355. package/src/plugin/virtual/layouts.ts +0 -41
  356. package/src/plugin/virtual/loading.ts +0 -32
  357. package/src/plugin/virtual/middleware.ts +0 -45
  358. package/src/plugin/virtual/plugins.ts +0 -46
  359. package/src/plugin/virtual/routes.ts +0 -514
  360. package/src/plugin/virtual/server-api.ts +0 -85
  361. package/src/plugin/virtual/server-middleware.ts +0 -44
  362. package/src/runtime/app-template.ts +0 -380
  363. package/src/runtime/composables/define-middleware.ts +0 -17
  364. package/src/runtime/composables/define-server-middleware.ts +0 -18
  365. package/src/runtime/composables/index.ts +0 -27
  366. package/src/runtime/composables/use-auth.ts +0 -125
  367. package/src/runtime/composables/use-content-search.ts +0 -205
  368. package/src/runtime/composables/use-content.ts +0 -146
  369. package/src/runtime/composables/use-cookie.ts +0 -135
  370. package/src/runtime/composables/use-fetch.ts +0 -438
  371. package/src/runtime/composables/use-head.ts +0 -212
  372. package/src/runtime/composables/use-inject.ts +0 -49
  373. package/src/runtime/composables/use-locale.ts +0 -109
  374. package/src/runtime/composables/use-navigate.ts +0 -58
  375. package/src/runtime/composables/use-page-data.ts +0 -93
  376. package/src/runtime/composables/use-route.ts +0 -71
  377. package/src/runtime/composables/use-runtime-config.ts +0 -123
  378. package/src/runtime/composables/use-seo-meta.ts +0 -80
  379. package/src/runtime/composables/use-session.ts +0 -186
  380. package/src/runtime/composables/use-state.ts +0 -92
  381. package/src/runtime/content/client.ts +0 -168
  382. package/src/runtime/entry-client-template.ts +0 -39
  383. package/src/runtime/entry-server-template.ts +0 -493
  384. package/src/runtime/isr-handler.ts +0 -184
  385. package/src/runtime/oauth/handler.ts +0 -407
  386. package/src/runtime/oauth/index.ts +0 -49
  387. package/src/runtime/oauth/providers.ts +0 -38
  388. package/src/types/api.ts +0 -40
  389. package/src/types/config.ts +0 -371
  390. package/src/types/content.ts +0 -66
  391. package/src/types/index.ts +0 -7
  392. package/src/types/middleware.ts +0 -63
  393. package/src/types/page.ts +0 -117
  394. package/src/types/plugin.ts +0 -34
  395. package/tsconfig.build.json +0 -10
  396. package/tsconfig.json +0 -19
  397. package/vitest.config.ts +0 -33
@@ -1,385 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { readFileSync } from 'node:fs'
3
- import { resolve } from 'pathe'
4
-
5
- const src = readFileSync(
6
- resolve(import.meta.dirname, '../../runtime/entry-server-template.ts'),
7
- 'utf-8',
8
- )
9
-
10
- describe('entry-server-template (ENTRY_SERVER_TEMPLATE content)', () => {
11
- it('does not import virtual:cer-components (components injected per-file by cerComponentImports)', () => {
12
- expect(src).not.toContain('virtual:cer-components')
13
- })
14
-
15
- it('imports virtual:cer-routes', () => {
16
- expect(src).toContain('virtual:cer-routes')
17
- })
18
-
19
- it('imports virtual:cer-layouts', () => {
20
- expect(src).toContain('virtual:cer-layouts')
21
- })
22
-
23
- it('imports virtual:cer-plugins', () => {
24
- expect(src).toContain('virtual:cer-plugins')
25
- })
26
-
27
- it('imports virtual:cer-server-api', () => {
28
- expect(src).toContain('virtual:cer-server-api')
29
- })
30
-
31
- it('imports virtual:cer-content-components for markdown-backed custom elements', () => {
32
- expect(src).toContain('virtual:cer-content-components')
33
- })
34
-
35
- it('imports registerBuiltinComponents from custom-elements-runtime', () => {
36
- expect(src).toContain('registerBuiltinComponents')
37
- expect(src).toContain('setDevMode')
38
- expect(src).toContain('@jasonshimmy/custom-elements-runtime')
39
- })
40
-
41
- it('enables runtime dev logging from the downstream server env', () => {
42
- expect(src).toContain('const _cerRuntimeDev')
43
- expect(src).toContain('import.meta.env?.DEV')
44
- expect(src).toContain('_cerProcess?.env')
45
- expect(src).toContain('(globalThis).__CE_RUNTIME_DEV__ = _cerRuntimeDev')
46
- expect(src).toContain('setDevMode(_cerRuntimeDev)')
47
- })
48
-
49
- it('imports renderToStreamWithJITCSSDSD and DSD_POLYFILL_SCRIPT from ssr subpath', () => {
50
- expect(src).toContain('renderToStreamWithJITCSSDSD')
51
- expect(src).toContain('DSD_POLYFILL_SCRIPT')
52
- expect(src).toContain('custom-elements-runtime/ssr')
53
- })
54
-
55
- it('imports initRouter from router subpath', () => {
56
- expect(src).toContain('initRouter')
57
- expect(src).toContain('custom-elements-runtime/router')
58
- })
59
-
60
- it('imports beginHeadCollection, endHeadCollection, serializeHeadTags from composables', () => {
61
- expect(src).toContain('beginHeadCollection')
62
- expect(src).toContain('endHeadCollection')
63
- expect(src).toContain('serializeHeadTags')
64
- expect(src).toContain('vite-plugin-cer-app/composables')
65
- })
66
-
67
- it('uses AsyncLocalStorage for request-scoped data isolation', () => {
68
- expect(src).toContain('AsyncLocalStorage')
69
- expect(src).toContain('node:async_hooks')
70
- expect(src).toContain('_cerDataStore')
71
- expect(src).toContain('__CER_DATA_STORE__')
72
- })
73
-
74
- it('scopes each request in _cerDataStore.run()', () => {
75
- expect(src).toContain('_cerDataStore.run(')
76
- })
77
-
78
- it('scopes loader data in _cerDataStore.run(loaderData) for rendering', () => {
79
- // enterWith() does not propagate across await boundaries to a parent
80
- // async continuation; run() is used instead so usePageData() in
81
- // renderToStreamWithJITCSSDSD sees the correct store value.
82
- expect(src).toContain('_cerDataStore.run(loaderData')
83
- expect(src).toContain('loaderData = data')
84
- expect(src).not.toContain('_cerDataStore.enterWith(data)')
85
- })
86
-
87
- it('initializes plugins and sets globalThis.__cerPluginProvides', () => {
88
- expect(src).toContain('__cerPluginProvides')
89
- expect(src).toContain('_pluginProvides')
90
- expect(src).toContain('_pluginsReady')
91
- })
92
-
93
- it('awaits _pluginsReady before handling each request', () => {
94
- expect(src).toContain('await _pluginsReady')
95
- })
96
-
97
- it('calls registerEntityMap with entities.json', () => {
98
- expect(src).toContain('registerEntityMap(entitiesJson)')
99
- expect(src).toContain('entities.json')
100
- })
101
-
102
- it('loads client index.html for merging', () => {
103
- expect(src).toContain('_clientTemplate')
104
- expect(src).toContain('../client/index.html')
105
- })
106
-
107
- it('defines _mergeWithClientTemplate helper', () => {
108
- expect(src).toContain('_mergeWithClientTemplate')
109
- })
110
-
111
- it('defines _prepareRequest async function', () => {
112
- expect(src).toContain('_prepareRequest')
113
- })
114
-
115
- it('calls endHeadCollection() synchronously before any await to avoid race conditions', () => {
116
- expect(src).toContain('beginHeadCollection()')
117
- expect(src).toContain('endHeadCollection()')
118
- // endHeadCollection must come before reader.read() so concurrent requests
119
- // (SSG concurrency > 1) cannot reset the shared globalThis collector between
120
- // beginHeadCollection and endHeadCollection.
121
- const endIdx = src.indexOf('endHeadCollection()')
122
- const readIdx = src.indexOf('reader.read()')
123
- expect(endIdx).toBeGreaterThan(-1)
124
- expect(readIdx).toBeGreaterThan(-1)
125
- expect(endIdx).toBeLessThan(readIdx)
126
- })
127
-
128
- it('passes dsdPolyfill: false to suppress inline polyfill', () => {
129
- expect(src).toContain('dsdPolyfill: false')
130
- })
131
-
132
- it('injects DSD_POLYFILL_SCRIPT before </body>', () => {
133
- expect(src).toContain("lastIndexOf('</body>')")
134
- expect(src).toContain('DSD_POLYFILL_SCRIPT + fromBodyClose')
135
- })
136
-
137
- it('merges SSR html with client template when available', () => {
138
- // Dev mode: per-request global takes precedence over module-level _clientTemplate
139
- expect(src).toContain('_resolvedClientTemplate')
140
- expect(src).toContain('(globalThis).__CER_CLIENT_TEMPLATE__ ?? _clientTemplate')
141
- expect(src).toContain('_mergeWithClientTemplate(ssrHtml, _resolvedClientTemplate)')
142
- })
143
-
144
- it('exports handler as both named and default export', () => {
145
- expect(src).toContain('export const handler')
146
- expect(src).toContain('export default handler')
147
- })
148
-
149
- it('exports apiRoutes, plugins, layouts, and routes', () => {
150
- expect(src).toContain('export { apiRoutes, plugins, layouts, routes, serverMiddleware }')
151
- })
152
-
153
- it('exports runServerMiddleware for adapter use', () => {
154
- expect(src).toContain('export async function runServerMiddleware(req, res)')
155
- })
156
-
157
- it('exports runWithRequestContext for wrapping API handlers in request context', () => {
158
- expect(src).toContain('export function runWithRequestContext(req, res, fn)')
159
- expect(src).toContain('_cerReqStore.run({ req, res }, fn)')
160
- })
161
-
162
- it('sets Content-Type header on response', () => {
163
- expect(src).toContain('text/html; charset=utf-8')
164
- })
165
-
166
- it('sets Transfer-Encoding: chunked header for streaming', () => {
167
- expect(src).toContain('Transfer-Encoding')
168
- expect(src).toContain('chunked')
169
- })
170
-
171
- it('reads the stream using a reader loop', () => {
172
- expect(src).toContain('stream.getReader()')
173
- expect(src).toContain('reader.read()')
174
- })
175
-
176
- // ─── Error boundary ──────────────────────────────────────────────────────────
177
-
178
- it('imports errorTag from virtual:cer-error', () => {
179
- expect(src).toContain('errorTag')
180
- expect(src).toContain('virtual:cer-error')
181
- })
182
-
183
- it('catches loader errors in _prepareRequest', () => {
184
- expect(src).toContain('catch (err)')
185
- // The catch block must exist inside _prepareRequest (after the function definition)
186
- const prepareIdx = src.indexOf('const _prepareRequest')
187
- const catchIdx = src.indexOf('catch (err)', prepareIdx)
188
- expect(prepareIdx).toBeGreaterThan(-1)
189
- expect(catchIdx).toBeGreaterThan(prepareIdx)
190
- })
191
-
192
- it('extracts .status from the thrown error for HTTP status code', () => {
193
- expect(src).toContain("'status' in err")
194
- expect(src).toContain('err.status')
195
- })
196
-
197
- it('guards err.status with typeof === "number" so Response-like thrown values work', () => {
198
- // `new Response("...", { status: 404 })` has a numeric `.status` property.
199
- // The typeof guard ensures that non-numeric status values (e.g. a string "404")
200
- // do not pass through — only genuine numbers are accepted.
201
- expect(src).toContain("typeof err.status === 'number'")
202
- })
203
-
204
- it('defaults to status 500 when thrown error has no .status', () => {
205
- expect(src).toContain(': 500')
206
- })
207
-
208
- it('renders error component when loader throws and an error tag is available', () => {
209
- // P2-2: effectiveErrorTag (route-level or global) is used as the tag
210
- expect(src).toContain('tag: effectiveErrorTag')
211
- })
212
-
213
- it('logs to console.error when loader throws and no error tag is defined', () => {
214
- expect(src).toContain('console.error')
215
- expect(src).toContain('!effectiveErrorTag')
216
- })
217
-
218
- it('propagates status to res.statusCode', () => {
219
- expect(src).toContain('res.statusCode = status')
220
- })
221
-
222
- it('returns status: null on the happy path when the route is not marked as not-found', () => {
223
- expect(src).toContain('isNotFoundRoute ? 404 : null')
224
- })
225
-
226
- it('sets status 404 only when the matched route is marked as framework not-found', () => {
227
- expect(src).toContain('route?.meta?._cerNotFound === true')
228
- })
229
-
230
- // ─── Render error handling (P0-1) ────────────────────────────────────────────
231
- // Note: the custom-elements runtime catches *component-level* render errors
232
- // internally (see ssr-context.ts runComponentSSRRender). The try/catch here
233
- // guards against *infrastructure-level* failures that escape the runtime.
234
-
235
- it('wraps the render + stream loop in a try/catch block', () => {
236
- expect(src).toContain('} catch (_renderErr) {')
237
- })
238
-
239
- it('calls endHeadCollection() in the catch block to prevent collector leaks', () => {
240
- const catchIdx = src.indexOf('} catch (_renderErr) {')
241
- const endCollectorInCatch = src.indexOf('endHeadCollection()', catchIdx)
242
- expect(catchIdx).toBeGreaterThan(-1)
243
- expect(endCollectorInCatch).toBeGreaterThan(catchIdx)
244
- })
245
-
246
- it('sends a 500 response when an infrastructure error occurs before headers are sent', () => {
247
- expect(src).toContain('res.headersSent')
248
- expect(src).toContain('res.statusCode = 500')
249
- })
250
-
251
- it('closes the connection with res.end() when headers were already sent during streaming', () => {
252
- const catchIdx = src.indexOf('} catch (_renderErr) {')
253
- const elseEndIdx = src.indexOf('res.end()', catchIdx)
254
- expect(elseEndIdx).toBeGreaterThan(catchIdx)
255
- })
256
-
257
- it('includes an HTML error page body in the 500 infrastructure-error response', () => {
258
- expect(src).toContain('500 Internal Server Error')
259
- })
260
-
261
- // ─── ISR production export ───────────────────────────────────────────────────
262
-
263
- it('imports createIsrHandler from the isr subpath', () => {
264
- expect(src).toContain('createIsrHandler')
265
- expect(src).toContain('vite-plugin-cer-app/isr')
266
- })
267
-
268
- it('exports isrHandler wrapping handler with ISR caching', () => {
269
- expect(src).toContain('export const isrHandler')
270
- expect(src).toContain('createIsrHandler(routes, handler)')
271
- })
272
-
273
- // ─── useCookie req/res store ──────────────────────────────────────────────────
274
-
275
- it('creates _cerReqStore AsyncLocalStorage for request-scoped cookie access', () => {
276
- expect(src).toContain('_cerReqStore')
277
- expect(src).toContain('__CER_REQ_STORE__')
278
- })
279
-
280
- it('exposes _cerReqStore on globalThis as __CER_REQ_STORE__', () => {
281
- expect(src).toContain('__CER_REQ_STORE__ = _cerReqStore')
282
- })
283
-
284
- it('wraps handler body in _cerReqStore.run({ req, res }, ...) so useCookie can access req/res', () => {
285
- expect(src).toContain('_cerReqStore.run({ req, res }')
286
- // req/res store wraps the data store — it must appear before _cerDataStore.run
287
- const reqStoreIdx = src.indexOf('_cerReqStore.run(')
288
- const dataStoreIdx = src.indexOf('_cerDataStore.run(')
289
- expect(reqStoreIdx).toBeGreaterThan(-1)
290
- expect(dataStoreIdx).toBeGreaterThan(-1)
291
- expect(reqStoreIdx).toBeLessThan(dataStoreIdx)
292
- })
293
-
294
- // ─── P1-1: Synthetic 404 from null pageTag ───────────────────────────────────
295
-
296
- it('handles null pageTag from the synthetic catch-all route (returns 404 status)', () => {
297
- // The synthetic catch-all resolves to { default: null }; _prepareRequest must
298
- // check for this and return 404 rather than crashing.
299
- expect(src).toContain('!pageTag')
300
- // Should return status: 404 for null pageTag
301
- expect(src).toContain('status: 404')
302
- })
303
-
304
- it('uses the per-route errorTag for 404 display when available', () => {
305
- // If the synthetic 404 route has an errorTag, it should be used as the 404 vnode tag
306
- expect(src).toContain('routeErrorTag')
307
- // Falls back to global errorTag when no per-route error component exists
308
- const routeErrIdx = src.indexOf('routeErrorTag')
309
- const globalErrIdx = src.indexOf('errorTag')
310
- expect(routeErrIdx).toBeGreaterThan(-1)
311
- expect(globalErrIdx).toBeGreaterThan(-1)
312
- })
313
-
314
- // ─── P1-2: runServerMiddleware status code extraction ──────────────────────
315
-
316
- it('runServerMiddleware reads err.status to pick the response status code', () => {
317
- // The catch block should extract err.status before defaulting to 500
318
- expect(src).toContain('err.status')
319
- // isNaN guard ensures non-numeric status values default to 500
320
- expect(src).toContain('isNaN')
321
- })
322
-
323
- it('runServerMiddleware defaults to 500 when err has no .status property', () => {
324
- expect(src).toContain(': 500')
325
- })
326
-
327
- // ─── P2-2: Per-route error component ────────────────────────────────────────
328
-
329
- it('uses route.meta.errorTag over the global errorTag when available', () => {
330
- // The error catch inside _prepareRequest should prefer the per-route error tag
331
- expect(src).toContain('route?.meta?.errorTag')
332
- // Fallback to global errorTag
333
- expect(src).toContain('?? errorTag')
334
- })
335
-
336
- // ─── Observability hooks ─────────────────────────────────────────────────────
337
-
338
- it('imports _hooks from virtual:cer-app-config', () => {
339
- expect(src).toContain('_hooks')
340
- expect(src).toContain('virtual:cer-app-config')
341
- })
342
-
343
- it('fires onRequest at the start of the handler with path, method, and req', () => {
344
- expect(src).toContain('_hooks?.onRequest')
345
- expect(src).toContain('_requestPath')
346
- expect(src).toContain('_requestStart')
347
- })
348
-
349
- it('fires onError in the middleware catch with type: middleware', () => {
350
- expect(src).toContain("type: 'middleware'")
351
- // onError fires inside runServerMiddleware catch
352
- const mwIdx = src.indexOf('runServerMiddleware')
353
- const middlewareErrIdx = src.indexOf("type: 'middleware'", mwIdx)
354
- expect(middlewareErrIdx).toBeGreaterThan(mwIdx)
355
- })
356
-
357
- it('fires onError in the loader catch with type: loader', () => {
358
- expect(src).toContain("type: 'loader'")
359
- })
360
-
361
- it('fires onError in the render catch with type: render', () => {
362
- expect(src).toContain("type: 'render'")
363
- const catchIdx = src.indexOf('} catch (_renderErr) {')
364
- const renderErrIdx = src.indexOf("type: 'render'", catchIdx)
365
- expect(renderErrIdx).toBeGreaterThan(catchIdx)
366
- })
367
-
368
- it('fires onResponse after the success res.end()', () => {
369
- expect(src).toContain('_hooks?.onResponse')
370
- // onResponse must appear after DSD_POLYFILL_SCRIPT + fromBodyClose
371
- const endIdx = src.indexOf('DSD_POLYFILL_SCRIPT + fromBodyClose')
372
- const responseIdx = src.indexOf('_hooks?.onResponse', endIdx)
373
- expect(responseIdx).toBeGreaterThan(endIdx)
374
- })
375
-
376
- it('fires onResponse in the render error catch so it fires on both success and error paths', () => {
377
- const catchIdx = src.indexOf('} catch (_renderErr) {')
378
- const responseInCatchIdx = src.indexOf('_hooks?.onResponse', catchIdx)
379
- expect(responseInCatchIdx).toBeGreaterThan(catchIdx)
380
- })
381
-
382
- it('swallows exceptions thrown by onError so hooks cannot crash the handler', () => {
383
- expect(src).toContain('/* hooks must not crash the handler */')
384
- })
385
- })
@@ -1,144 +0,0 @@
1
- import { vi, describe, it, expect, beforeEach } from 'vitest'
2
-
3
- vi.mock('node:fs', async (importOriginal) => {
4
- const actual = await importOriginal<typeof import('node:fs')>()
5
- return {
6
- ...actual,
7
- existsSync: vi.fn().mockReturnValue(false),
8
- writeFileSync: vi.fn(),
9
- mkdirSync: vi.fn(),
10
- readFileSync: vi.fn().mockReturnValue(''),
11
- appendFileSync: vi.fn(),
12
- }
13
- })
14
- vi.mock('../../runtime/app-template.js', () => ({ generateAppEntryTemplate: vi.fn().mockReturnValue('// app template') }))
15
-
16
- import { existsSync, writeFileSync, mkdirSync, readFileSync, appendFileSync } from 'node:fs'
17
- import {
18
- GENERATED_DIR_NAME,
19
- getGeneratedDir,
20
- resolveHtmlEntry,
21
- generateDefaultHtml,
22
- writeGeneratedDir,
23
- } from '../../plugin/generated-dir.js'
24
-
25
- const ROOT = '/project'
26
- const mockConfig = {
27
- root: ROOT,
28
- srcDir: `${ROOT}/app`,
29
- jitCss: { content: [], extendedColors: false },
30
- } as Parameters<typeof writeGeneratedDir>[0]
31
-
32
- beforeEach(() => {
33
- vi.mocked(existsSync).mockReturnValue(false)
34
- vi.mocked(writeFileSync).mockClear()
35
- vi.mocked(mkdirSync).mockClear()
36
- vi.mocked(readFileSync).mockReturnValue('')
37
- vi.mocked(appendFileSync).mockClear()
38
- })
39
-
40
- describe('GENERATED_DIR_NAME', () => {
41
- it('is .cer', () => {
42
- expect(GENERATED_DIR_NAME).toBe('.cer')
43
- })
44
- })
45
-
46
- describe('getGeneratedDir', () => {
47
- it('returns <root>/.cer', () => {
48
- expect(getGeneratedDir(ROOT)).toBe(`${ROOT}/.cer`)
49
- })
50
- })
51
-
52
- describe('resolveHtmlEntry', () => {
53
- it('returns user index.html when it exists', () => {
54
- vi.mocked(existsSync).mockReturnValue(true)
55
- expect(resolveHtmlEntry(mockConfig)).toBe(`${ROOT}/index.html`)
56
- })
57
-
58
- it('returns .cer/index.html when user index.html is absent', () => {
59
- vi.mocked(existsSync).mockReturnValue(false)
60
- expect(resolveHtmlEntry(mockConfig)).toBe(`${ROOT}/.cer/index.html`)
61
- })
62
- })
63
-
64
- describe('generateDefaultHtml', () => {
65
- it('always references /@cer/app.ts', () => {
66
- const html = generateDefaultHtml()
67
- expect(html).toContain('/@cer/app.ts')
68
- expect(html).not.toContain('/app/app.ts')
69
- })
70
-
71
- it('includes <cer-layout-view> mount point', () => {
72
- const html = generateDefaultHtml()
73
- expect(html).toContain('<cer-layout-view>')
74
- })
75
-
76
- it('is valid HTML with doctype', () => {
77
- const html = generateDefaultHtml()
78
- expect(html).toContain('<!DOCTYPE html>')
79
- })
80
- })
81
-
82
- describe('writeGeneratedDir', () => {
83
- it('creates the .cer directory when absent', () => {
84
- // existsSync returns false for everything → dir is created
85
- writeGeneratedDir(mockConfig)
86
- expect(mkdirSync).toHaveBeenCalledWith(`${ROOT}/.cer`, { recursive: true })
87
- })
88
-
89
- it('does not re-create the directory when it already exists', () => {
90
- // existsSync returns true → dir already present
91
- vi.mocked(existsSync).mockReturnValue(true)
92
- writeGeneratedDir(mockConfig)
93
- expect(mkdirSync).not.toHaveBeenCalled()
94
- })
95
-
96
- it('always writes .cer/app.ts', () => {
97
- writeGeneratedDir(mockConfig)
98
- const paths = vi.mocked(writeFileSync).mock.calls.map(([p]) => String(p))
99
- expect(paths.some(p => p.endsWith('/.cer/app.ts'))).toBe(true)
100
- })
101
-
102
- it('always writes .cer/app.ts even when .cer/ dir already exists', () => {
103
- vi.mocked(existsSync).mockReturnValue(true)
104
- writeGeneratedDir(mockConfig)
105
- const paths = vi.mocked(writeFileSync).mock.calls.map(([p]) => String(p))
106
- expect(paths.some(p => p.endsWith('/.cer/app.ts'))).toBe(true)
107
- })
108
-
109
- it('always writes .cer/entry-server.ts', () => {
110
- writeGeneratedDir(mockConfig)
111
- const paths = vi.mocked(writeFileSync).mock.calls.map(([p]) => String(p))
112
- expect(paths.some(p => p.endsWith('/.cer/entry-server.ts'))).toBe(true)
113
- })
114
-
115
- it('always writes .cer/index.html', () => {
116
- writeGeneratedDir(mockConfig)
117
- const paths = vi.mocked(writeFileSync).mock.calls.map(([p]) => String(p))
118
- expect(paths.some(p => p.endsWith('/.cer/index.html'))).toBe(true)
119
- })
120
-
121
- it('creates .gitignore when absent', () => {
122
- // existsSync returns false → .cer/ dir created, app.ts written, .gitignore created
123
- writeGeneratedDir(mockConfig)
124
- const paths = vi.mocked(writeFileSync).mock.calls.map(([p]) => String(p))
125
- expect(paths.some(p => p.endsWith('/.gitignore'))).toBe(true)
126
- })
127
-
128
- it('appends .cer/ to existing .gitignore that does not contain it', () => {
129
- // .gitignore exists (readFileSync returns '' — no .cer/ entry)
130
- vi.mocked(existsSync).mockImplementation((p) => String(p).endsWith('.gitignore'))
131
- vi.mocked(readFileSync).mockReturnValue('node_modules/\ndist/\n')
132
- writeGeneratedDir(mockConfig)
133
- expect(appendFileSync).toHaveBeenCalled()
134
- const appendArg = vi.mocked(appendFileSync).mock.calls[0][1] as string
135
- expect(appendArg).toContain('.cer/')
136
- })
137
-
138
- it('does not append to .gitignore when .cer/ is already present', () => {
139
- vi.mocked(existsSync).mockImplementation((p) => String(p).endsWith('.gitignore'))
140
- vi.mocked(readFileSync).mockReturnValue('node_modules/\n.cer/\ndist/\n')
141
- writeGeneratedDir(mockConfig)
142
- expect(appendFileSync).not.toHaveBeenCalled()
143
- })
144
- })