@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,70 +0,0 @@
1
- /**
2
- * Tests for per-route render strategy (meta.render).
3
- *
4
- * render: 'server' — route is always SSR'd, skipped during SSG pre-rendering.
5
- * render: 'spa' — route is served as SPA shell in SSR mode, skipped in SSG.
6
- * render: 'static' — serve pre-rendered HTML from disk; fall back to SSR.
7
- */
8
-
9
- const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
10
-
11
- // ─── render: 'server' ─────────────────────────────────────────────────────────
12
-
13
- describe('render: server — always SSR', () => {
14
- it('renders the page in SSR mode', () => {
15
- if (mode !== 'ssr') return
16
- cy.visit('/render-server-test')
17
- cy.get('[data-cy=render-server-heading]').should('contain', 'Render Server Test')
18
- })
19
-
20
- it('renders the page in SPA mode (client-side navigation)', () => {
21
- if (mode !== 'spa') return
22
- cy.visit('/render-server-test')
23
- cy.get('[data-cy=render-server-heading]').should('contain', 'Render Server Test')
24
- })
25
-
26
- if (mode === 'ssr') {
27
- it('pre-renders the page in the initial HTML (SSR)', () => {
28
- cy.request('/render-server-test').then((response) => {
29
- expect(response.body).to.include('render-server-heading')
30
- expect(response.body).to.include('Render Server Test')
31
- })
32
- })
33
- }
34
-
35
- if (mode === 'ssg') {
36
- it('route with render:server is not pre-rendered — not found in ssg dist', () => {
37
- // The route was skipped during SSG. The static preview falls back to
38
- // dist/index.html (SPA shell) rather than a pre-rendered page, so the
39
- // server-rendered heading is absent from the raw HTML response.
40
- cy.request('/render-server-test').then((response) => {
41
- expect(response.body).not.to.include('render-server-heading')
42
- })
43
- })
44
- }
45
- })
46
-
47
- // ─── render: 'spa' ────────────────────────────────────────────────────────────
48
-
49
- describe('render: spa — client-only', () => {
50
- it('renders the page heading after JS boots', () => {
51
- cy.visit('/render-spa-test')
52
- cy.get('[data-cy=render-spa-heading]').should('contain', 'Render SPA Test')
53
- })
54
-
55
- if (mode === 'ssr') {
56
- it('raw HTML response is the SPA shell (no SSR content)', () => {
57
- cy.request('/render-spa-test').then((response) => {
58
- expect(response.body).not.to.include('render-spa-heading')
59
- })
60
- })
61
- }
62
-
63
- if (mode === 'ssg') {
64
- it('route with render:spa is not pre-rendered — not found in ssg dist', () => {
65
- cy.request('/render-spa-test').then((response) => {
66
- expect(response.body).not.to.include('render-spa-heading')
67
- })
68
- })
69
- }
70
- })
@@ -1,88 +0,0 @@
1
- /**
2
- * Preview server hardening e2e tests — verifies security headers,
3
- * Cache-Control values, and graceful shutdown behaviour.
4
- *
5
- * Security headers and Cache-Control are server-level concerns, so these
6
- * tests only run in SSR and SSG modes (both use `cer-app preview`).
7
- * SPA mode also runs through the preview server, so the tests apply there too.
8
- * Dev mode uses the Vite dev server which does not set these headers.
9
- */
10
-
11
- const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg' | 'dev'
12
-
13
- // Security headers and Cache-Control are only set by the production preview server.
14
- // Skip these tests in dev mode (Vite dev server does not set them).
15
- if (mode !== 'dev') {
16
- describe('Preview server — security headers', () => {
17
- it('responds with X-Content-Type-Options: nosniff', () => {
18
- cy.request('/').then((response) => {
19
- expect(response.headers['x-content-type-options']).to.eq('nosniff')
20
- })
21
- })
22
-
23
- it('responds with X-Frame-Options: DENY', () => {
24
- cy.request('/').then((response) => {
25
- expect(response.headers['x-frame-options']).to.eq('DENY')
26
- })
27
- })
28
-
29
- it('responds with Referrer-Policy: strict-origin-when-cross-origin', () => {
30
- cy.request('/').then((response) => {
31
- expect(response.headers['referrer-policy']).to.eq('strict-origin-when-cross-origin')
32
- })
33
- })
34
-
35
- it('includes security headers on 404 responses', () => {
36
- cy.request({ url: '/definitely-not-a-real-page-xyz', failOnStatusCode: false }).then((response) => {
37
- expect(response.headers['x-content-type-options']).to.eq('nosniff')
38
- })
39
- })
40
- })
41
- }
42
-
43
- describe('Preview server — path traversal protection', () => {
44
- // HTTP clients (including Cypress/got) normalize `..` segments before sending,
45
- // so a raw traversal like `/../../../../etc/passwd` arrives at the server as
46
- // `/etc/passwd`. The `isPathBounded` guard is exercised via unit tests
47
- // (src/__tests__/cli/preview-isr.test.ts). Here we verify the observable
48
- // guarantee: files that do not exist inside dist/ are never served.
49
- it('does not serve a file that does not exist inside dist/', () => {
50
- cy.request({ url: '/etc/passwd', failOnStatusCode: false }).then((response) => {
51
- // Either 404 (static) or 200 (SSR SPA fallback) — never a served file from
52
- // outside the dist directory. Critically, the response body must NOT contain
53
- // typical /etc/passwd content.
54
- expect(response.body).not.to.include('root:x:')
55
- expect(response.body).not.to.include('/bin/bash')
56
- })
57
- })
58
-
59
- // NOTE: HTTP clients (including Cypress/got) normalize `..` segments before
60
- // sending, so raw traversal sequences never arrive at the server unchanged.
61
- // The isPathBounded() guard is exhaustively covered at the unit level in
62
- // src/__tests__/cli/preview-isr.test.ts. No additional e2e assertion is needed.
63
- })
64
-
65
- if (mode !== 'dev') {
66
- describe('Preview server — Cache-Control', () => {
67
- it('serves HTML with Cache-Control: no-cache', () => {
68
- cy.request('/').then((response) => {
69
- expect(response.headers['cache-control']).to.include('no-cache')
70
- })
71
- })
72
-
73
- it('serves content-hashed assets with immutable Cache-Control', () => {
74
- // Get the page to discover an actual asset URL (Vite hashes asset filenames)
75
- cy.request('/').then((htmlResponse) => {
76
- const assetMatch = htmlResponse.body.match(/\/assets\/[^"'\s]+\.js/)
77
- if (!assetMatch) return // no JS asset found in this page, skip
78
-
79
- const assetUrl = assetMatch[0]
80
- cy.request(assetUrl).then((assetResponse) => {
81
- const cc = assetResponse.headers['cache-control'] as string
82
- expect(cc).to.include('max-age=31536000')
83
- expect(cc).to.include('immutable')
84
- })
85
- })
86
- })
87
- })
88
- }
@@ -1,128 +0,0 @@
1
- /**
2
- * Routes test — verifies every route renders correct content in all build modes.
3
- */
4
-
5
- const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
6
-
7
- describe('Route rendering', () => {
8
- context('Home page (/)', () => {
9
- it('renders the home heading', () => {
10
- cy.visit('/')
11
- cy.get('[data-cy=home-heading]').should('contain', 'Kitchen Sink')
12
- })
13
-
14
- it('renders the ks-badge component', () => {
15
- cy.visit('/')
16
- cy.get('[data-cy=ks-badge]').should('exist')
17
- })
18
-
19
- it('renders the default layout with nav', () => {
20
- cy.visit('/')
21
- cy.get('[data-cy=site-nav]').should('exist')
22
- cy.get('[data-cy=site-header]').should('exist')
23
- cy.get('[data-cy=site-footer]').should('exist')
24
- })
25
-
26
- it('renders all nav links', () => {
27
- cy.visit('/')
28
- cy.get('[data-cy=nav-home]').should('exist')
29
- cy.get('[data-cy=nav-about]').should('exist')
30
- cy.get('[data-cy=nav-counter]').should('exist')
31
- cy.get('[data-cy=nav-blog]').should('exist')
32
- })
33
- })
34
-
35
- context('About page (/about) — minimal layout + useHead', () => {
36
- it('renders the about heading', () => {
37
- cy.visit('/about')
38
- cy.get('[data-cy=about-heading]').should('contain', 'About')
39
- })
40
-
41
- it('uses the minimal layout (no site-nav)', () => {
42
- cy.visit('/about')
43
- cy.get('[data-cy=minimal-layout]').should('exist')
44
- cy.get('[data-cy=site-nav]').should('not.exist')
45
- })
46
- })
47
-
48
- context('Counter page (/counter)', () => {
49
- it('renders the counter heading', () => {
50
- cy.visit('/counter')
51
- cy.get('[data-cy=counter-heading]').should('contain', 'Counter')
52
- })
53
-
54
- it('renders the counter widget with initial count of 0', () => {
55
- cy.visit('/counter')
56
- cy.get('[data-cy=count]').should('contain', '0')
57
- })
58
-
59
- it('renders increment, decrement, and reset buttons', () => {
60
- cy.visit('/counter')
61
- cy.get('[data-cy=increment]').should('exist')
62
- cy.get('[data-cy=decrement]').should('exist')
63
- cy.get('[data-cy=reset]').should('exist')
64
- })
65
- })
66
-
67
- context('Head page (/head) — useHead', () => {
68
- it('renders the head-test heading', () => {
69
- cy.visit('/head')
70
- cy.get('[data-cy=head-heading]').should('contain', 'Head Test')
71
- })
72
- })
73
-
74
- context('Blog list page (/blog)', () => {
75
- it('renders the blog heading', () => {
76
- cy.visit('/blog')
77
- cy.get('[data-cy=blog-heading]').should('contain', 'Blog')
78
- })
79
- })
80
-
81
- context('Blog detail page (/blog/first-post) — dynamic route', () => {
82
- it('renders the post title', () => {
83
- cy.visit('/blog/first-post')
84
- cy.get('[data-cy=post-title]').should('contain', 'First Post')
85
- })
86
-
87
- it('renders the post slug', () => {
88
- cy.visit('/blog/first-post')
89
- cy.get('[data-cy=post-slug]').should('contain', 'first-post')
90
- })
91
- })
92
-
93
- context('Item page (/items/1) — route params via useProps', () => {
94
- it('renders the item heading', () => {
95
- cy.visit('/items/1')
96
- cy.get('[data-cy=item-heading]').should('contain', 'Item Detail')
97
- })
98
-
99
- it('shows the correct item ID from route params', () => {
100
- cy.visit('/items/1')
101
- cy.get('[data-cy=item-id]').should('contain', '1')
102
- })
103
-
104
- it('shows a different ID for /items/2', () => {
105
- cy.visit('/items/2')
106
- cy.get('[data-cy=item-id]').should('contain', '2')
107
- })
108
- })
109
-
110
- context('Login page (/login) — route group, minimal layout', () => {
111
- it('renders the login heading', () => {
112
- cy.visit('/login')
113
- cy.get('[data-cy=login-heading]').should('contain', 'Login')
114
- })
115
-
116
- it('uses the minimal layout', () => {
117
- cy.visit('/login')
118
- cy.get('[data-cy=minimal-layout]').should('exist')
119
- })
120
- })
121
-
122
- context('404 page — catch-all route', () => {
123
- it('renders the 404 heading for an unknown path', () => {
124
- cy.visit('/this-page-does-not-exist-at-all', { failOnStatusCode: false })
125
- cy.get('[data-cy=not-found-heading]').should('contain', '404')
126
- })
127
- })
128
- })
@@ -1,108 +0,0 @@
1
- /**
2
- * useSeoMeta() e2e tests — verifies Open Graph, Twitter Card, canonical, and
3
- * title/description tags are injected correctly in all modes.
4
- *
5
- * In SSR/SSG: tags must be present in the initial server-rendered HTML.
6
- * In all modes: tags must be present after client hydration.
7
- */
8
-
9
- const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
10
-
11
- describe('useSeoMeta() — title and description', () => {
12
- it('sets document title', () => {
13
- cy.visit('/seo-test')
14
- cy.title().should('eq', 'SEO Test — Kitchen Sink')
15
- })
16
-
17
- it('sets meta description', () => {
18
- cy.visit('/seo-test')
19
- cy.get('meta[name="description"]').should('have.attr', 'content', 'A test page for useSeoMeta().')
20
- })
21
- })
22
-
23
- describe('useSeoMeta() — Open Graph tags', () => {
24
- it('sets og:title', () => {
25
- cy.visit('/seo-test')
26
- cy.get('meta[property="og:title"]').should('have.attr', 'content', 'SEO Test OG Title')
27
- })
28
-
29
- it('sets og:description', () => {
30
- cy.visit('/seo-test')
31
- cy.get('meta[property="og:description"]').should('have.attr', 'content', 'SEO Test OG description.')
32
- })
33
-
34
- it('sets og:image', () => {
35
- cy.visit('/seo-test')
36
- cy.get('meta[property="og:image"]').should('have.attr', 'content', 'https://example.com/og/seo-test.png')
37
- })
38
-
39
- it('sets og:url', () => {
40
- cy.visit('/seo-test')
41
- cy.get('meta[property="og:url"]').should('have.attr', 'content', 'https://example.com/seo-test')
42
- })
43
-
44
- it('sets og:type', () => {
45
- cy.visit('/seo-test')
46
- cy.get('meta[property="og:type"]').should('have.attr', 'content', 'website')
47
- })
48
-
49
- it('sets og:site_name', () => {
50
- cy.visit('/seo-test')
51
- cy.get('meta[property="og:site_name"]').should('have.attr', 'content', 'Kitchen Sink')
52
- })
53
- })
54
-
55
- describe('useSeoMeta() — Twitter Card tags', () => {
56
- it('sets twitter:card', () => {
57
- cy.visit('/seo-test')
58
- cy.get('meta[name="twitter:card"]').should('have.attr', 'content', 'summary_large_image')
59
- })
60
-
61
- it('sets twitter:title', () => {
62
- cy.visit('/seo-test')
63
- cy.get('meta[name="twitter:title"]').should('have.attr', 'content', 'SEO Test Twitter Title')
64
- })
65
-
66
- it('sets twitter:site', () => {
67
- cy.visit('/seo-test')
68
- cy.get('meta[name="twitter:site"]').should('have.attr', 'content', '@ks')
69
- })
70
- })
71
-
72
- describe('useSeoMeta() — canonical link', () => {
73
- it('sets canonical link element', () => {
74
- cy.visit('/seo-test')
75
- cy.get('link[rel="canonical"]').should('have.attr', 'href', 'https://example.com/seo-test')
76
- })
77
- })
78
-
79
- if (mode !== 'spa') {
80
- describe('useSeoMeta() — server-side injection (SSR/SSG)', () => {
81
- it('title is in the initial HTML', () => {
82
- cy.request('/seo-test').then((response) => {
83
- expect(response.body).to.include('<title>SEO Test — Kitchen Sink</title>')
84
- })
85
- })
86
-
87
- it('og:title meta is in the initial HTML', () => {
88
- cy.request('/seo-test').then((response) => {
89
- expect(response.body).to.include('og:title')
90
- expect(response.body).to.include('SEO Test OG Title')
91
- })
92
- })
93
-
94
- it('twitter:card meta is in the initial HTML', () => {
95
- cy.request('/seo-test').then((response) => {
96
- expect(response.body).to.include('twitter:card')
97
- expect(response.body).to.include('summary_large_image')
98
- })
99
- })
100
-
101
- it('canonical link is in the initial HTML', () => {
102
- cy.request('/seo-test').then((response) => {
103
- expect(response.body).to.include('canonical')
104
- expect(response.body).to.include('https://example.com/seo-test')
105
- })
106
- })
107
- })
108
- }
@@ -1,46 +0,0 @@
1
- /**
2
- * Server middleware e2e tests — verifies that files in server/middleware/ run
3
- * on every HTTP request before API routes and SSR rendering.
4
- *
5
- * The kitchen-sink includes `server/middleware/01-headers.ts` which sets
6
- * `X-CER-Middleware: active` on every response. These tests confirm that
7
- * header is present, proving the middleware chain executed.
8
- *
9
- * Server middleware runs in SSR mode (production) and dev mode. It does NOT
10
- * run in SPA or SSG static-file serving modes, so tests are gated accordingly.
11
- */
12
-
13
- const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
14
-
15
- // Server middleware only runs when there is a live server processing requests.
16
- // In dev mode the Vite middleware chain applies it; in SSR preview it is called
17
- // by runServerMiddleware(). SPA and SSG preview servers serve static files and
18
- // do not execute server middleware.
19
- if (mode === 'ssr') {
20
- describe('Server middleware — header injection (SSR)', () => {
21
- it('adds X-CER-Middleware header to HTML responses', () => {
22
- cy.request('/').then((response) => {
23
- expect(response.headers['x-cer-middleware']).to.eq('active')
24
- })
25
- })
26
-
27
- it('adds X-CER-Middleware header to API responses', () => {
28
- cy.request('/api/health').then((response) => {
29
- expect(response.headers['x-cer-middleware']).to.eq('active')
30
- })
31
- })
32
-
33
- it('adds X-CER-Middleware header to 404 responses', () => {
34
- cy.request({ url: '/this-path-does-not-exist', failOnStatusCode: false }).then((response) => {
35
- expect(response.headers['x-cer-middleware']).to.eq('active')
36
- })
37
- })
38
-
39
- it('middleware runs before API route handlers (header present on /api/posts)', () => {
40
- cy.request('/api/posts').then((response) => {
41
- expect(response.status).to.eq(200)
42
- expect(response.headers['x-cer-middleware']).to.eq('active')
43
- })
44
- })
45
- })
46
- }
@@ -1,25 +0,0 @@
1
- /**
2
- * P1-3: Session secret rotation.
3
- *
4
- * Tests that useSession() supports multiple secrets for key rotation:
5
- * - New sessions are signed with the first (active) secret.
6
- * - Old sessions signed with a secondary secret are still readable.
7
- */
8
-
9
- const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
10
-
11
- if (mode === 'ssr') {
12
- describe('Session secret rotation (P1-3)', () => {
13
- it('writes and reads back a session when sessionSecret is an array', () => {
14
- // The kitchen-sink /session-rotation-test page sets a session and reads it back
15
- cy.visit('/session-rotation-test')
16
- cy.get('[data-cy=session-read]', { timeout: 5000 }).should('contain', 'rotation-user')
17
- })
18
-
19
- it('session is stored as an httpOnly cookie', () => {
20
- cy.visit('/session-rotation-test')
21
- // After visiting the page that sets a session, the cookie should be present
22
- cy.getCookie('session').should('exist')
23
- })
24
- })
25
- }
@@ -1,73 +0,0 @@
1
- /**
2
- * useSession() e2e tests — verifies that HMAC-signed cookie sessions
3
- * round-trip correctly across requests via the /api/session endpoint.
4
- *
5
- * The kitchen-sink exposes:
6
- * GET /api/session → { userId: string | null }
7
- * POST /api/session → creates session with userId = 'test-user'
8
- * DELETE /api/session → clears the session
9
- *
10
- * Sessions require a server-side signing key, so these tests only run in
11
- * SSR mode where the session secret is available.
12
- */
13
-
14
- const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
15
-
16
- if (mode === 'ssr') {
17
- describe('useSession() — session create / read / clear (SSR)', () => {
18
- beforeEach(() => {
19
- cy.clearCookies()
20
- })
21
-
22
- it('GET /api/session returns null userId when no session cookie is set', () => {
23
- cy.request('/api/session').then((response) => {
24
- expect(response.status).to.eq(200)
25
- expect(response.body.userId).to.be.null
26
- })
27
- })
28
-
29
- it('POST /api/session creates a session cookie', () => {
30
- cy.request({ method: 'POST', url: '/api/session' }).then((response) => {
31
- expect(response.status).to.eq(200)
32
- expect(response.body.ok).to.be.true
33
- })
34
- // Cookie should now be present
35
- cy.getCookie('session').should('exist')
36
- })
37
-
38
- it('GET /api/session returns userId after session is created', () => {
39
- // Create session
40
- cy.request({ method: 'POST', url: '/api/session' })
41
- // Read session — Cypress automatically forwards the cookie
42
- cy.request('/api/session').then((response) => {
43
- expect(response.body.userId).to.eq('test-user')
44
- })
45
- })
46
-
47
- it('DELETE /api/session clears the session', () => {
48
- // Create then clear
49
- cy.request({ method: 'POST', url: '/api/session' })
50
- cy.request({ method: 'DELETE', url: '/api/session' })
51
- // Reading again should return null
52
- cy.request('/api/session').then((response) => {
53
- expect(response.body.userId).to.be.null
54
- })
55
- })
56
-
57
- it('session persists across multiple requests in the same Cypress session', () => {
58
- cy.request({ method: 'POST', url: '/api/session' })
59
- // Make several read requests — all should see the same userId
60
- cy.request('/api/session').its('body.userId').should('eq', 'test-user')
61
- cy.request('/api/session').its('body.userId').should('eq', 'test-user')
62
- })
63
-
64
- it('tampered session cookie causes GET to return null userId', () => {
65
- cy.request({ method: 'POST', url: '/api/session' })
66
- // Overwrite the cookie with garbage
67
- cy.setCookie('session', 'tampered.invalidsig')
68
- cy.request('/api/session').then((response) => {
69
- expect(response.body.userId).to.be.null
70
- })
71
- })
72
- })
73
- }
@@ -1,68 +0,0 @@
1
- /**
2
- * E2E tests for SSR render error resilience (P0-1).
3
- *
4
- * When a page component throws during the SSR render pass, the custom-elements
5
- * runtime catches the error internally (logs a warning, emits an empty DSD
6
- * placeholder) and continues rendering — so the server returns 200 with a valid
7
- * HTML document. The entry-server-template's try/catch protects against
8
- * *infrastructure-level* errors that escape the runtime's own protection (e.g.
9
- * a catastrophic failure in the SSR helpers themselves).
10
- *
11
- * Observable behaviour for a component-level throw:
12
- * - HTTP 200 (runtime handles it gracefully)
13
- * - Valid HTML body with the page skeleton
14
- * - Server remains operational for subsequent requests
15
- *
16
- * Only meaningful in SSR mode where the server renders pages on-request.
17
- */
18
-
19
- const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
20
-
21
- if (mode === 'ssr') {
22
- describe('SSR render error resilience — P0-1', () => {
23
- it('returns HTTP 200 when a page component throws during render (runtime handles gracefully)', () => {
24
- cy.request({ url: '/render-error-test', failOnStatusCode: false }).then((response) => {
25
- expect(response.status).to.eq(200)
26
- })
27
- })
28
-
29
- it('returns a non-empty HTML body even when a component throws', () => {
30
- cy.request({ url: '/render-error-test', failOnStatusCode: false }).then((response) => {
31
- expect(response.body).to.be.a('string')
32
- expect(response.body.length).to.be.greaterThan(0)
33
- expect(response.body).to.include('<!DOCTYPE html>')
34
- })
35
- })
36
-
37
- it('serves a Content-Type: text/html header', () => {
38
- cy.request({ url: '/render-error-test', failOnStatusCode: false }).then((response) => {
39
- expect(response.headers['content-type']).to.include('text/html')
40
- })
41
- })
42
-
43
- it('the broken component renders as an empty DSD placeholder (graceful degradation)', () => {
44
- cy.request({ url: '/render-error-test', failOnStatusCode: false }).then((response) => {
45
- // The runtime emits <page-render-error-test><template shadowrootmode="open"></template>...
46
- // or the component tag is present with an empty shadow root.
47
- expect(response.body).to.include('page-render-error-test')
48
- })
49
- })
50
-
51
- it('server responds normally to other routes after a component render error', () => {
52
- // First hit the broken route.
53
- cy.request({ url: '/render-error-test', failOnStatusCode: false })
54
- // Verify the server hasn't crashed and can still serve other routes.
55
- cy.request('/about').then((response) => {
56
- expect(response.status).to.eq(200)
57
- })
58
- })
59
-
60
- it('does not leave the server hanging after a component render error', () => {
61
- // If the server hung, cy.request() would time out (30s default).
62
- // A response (any status) within timeout confirms no hang.
63
- cy.request({ url: '/render-error-test', failOnStatusCode: false }).then((response) => {
64
- expect(response.status).to.be.a('number')
65
- })
66
- })
67
- })
68
- }
@@ -1,45 +0,0 @@
1
- /**
2
- * P1-1: Synthetic 404 catch-all fallback.
3
- *
4
- * When no user-defined catch-all page exists the framework injects a synthetic
5
- * /:all* route that returns `default: null`. The server must return HTTP 404
6
- * (not 500) and render the global error component if defined.
7
- */
8
-
9
- const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
10
-
11
- describe('Synthetic 404 fallback (P1-1)', () => {
12
- context('visiting a completely unknown route', () => {
13
- it('navigating client-side to an unknown route does not crash the app', () => {
14
- cy.visit('/')
15
- cy.window().then((win) => {
16
- // @ts-expect-error cerRouter is a private global
17
- win.__cerRouter?.push('/this-route-does-not-exist-at-all')
18
- })
19
- // Page should still be functional — no JS error thrown
20
- cy.get('body').should('exist')
21
- })
22
- })
23
-
24
- if (mode === 'ssr') {
25
- context('SSR — unknown route returns 404', () => {
26
- it('returns HTTP 404 for an unknown path', () => {
27
- cy.request({
28
- url: '/completely-unknown-route-xyz',
29
- failOnStatusCode: false,
30
- }).then((response) => {
31
- expect(response.status).to.eq(404)
32
- })
33
- })
34
-
35
- it('does not return 500 for an unknown path', () => {
36
- cy.request({
37
- url: '/another-unknown-path-abc',
38
- failOnStatusCode: false,
39
- }).then((response) => {
40
- expect(response.status).to.not.eq(500)
41
- })
42
- })
43
- })
44
- }
45
- })