@jasonshimmy/vite-plugin-cer-app 0.23.2 → 0.24.0

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