@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,122 +0,0 @@
1
- /**
2
- * usePageData() timing regression tests — proves the queueMicrotask fix.
3
- *
4
- * Background:
5
- * _doHydrate() runs _loadPageForPath (sets __CER_DATA__) then _replace(),
6
- * which causes cer-layout-view to create a NEW page element via a queued
7
- * microtask. That new element's setup() calls usePageData() to read __CER_DATA__.
8
- *
9
- * Pre-fix: delete __CER_DATA__ was synchronous → ran before the queued render
10
- * → usePageData() saw undefined → returned null.
11
- * Post-fix: queueMicrotask(() => delete __CER_DATA__) → delete is queued AFTER
12
- * the render microtask → usePageData() reads the data correctly.
13
- *
14
- * Proof mechanism:
15
- * Each blog page component captures `ssrData ? 'ssr' : 'client'` once, at the
16
- * moment the element is created during hydration. In SSR/SSG/dev modes this
17
- * value must always be 'ssr'. If it is 'client' the timing bug has regressed.
18
- */
19
-
20
- export {}
21
-
22
- const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg' | 'dev'
23
-
24
- // ─── Blog list — hard refresh ─────────────────────────────────────────────
25
-
26
- describe('usePageData() — blog list hard refresh', () => {
27
- if (mode !== 'spa') {
28
- it('server response embeds __CER_DATA__ with both post titles', () => {
29
- cy.request('/blog').then((res) => {
30
- expect(res.body).to.include('__CER_DATA__')
31
- expect(res.body).to.include('First Post')
32
- expect(res.body).to.include('Second Post')
33
- })
34
- })
35
-
36
- it('usePageData() is non-null during hydration re-render (data-source = "ssr")', () => {
37
- cy.visit('/blog')
38
- // Scope to the live shadow DOM (not the DSD pre-render copy) so the assertion
39
- // targets the element created during hydration where usePageData() was called.
40
- // 'ssr' proves queueMicrotask deferred the delete until after the render ran.
41
- cy.get('cer-layout-view').shadow().find('page-blog').shadow()
42
- .find('[data-cy=blog-data-source]').should('have.text', 'ssr')
43
- })
44
- }
45
-
46
- // In SSR and dev modes the /api/posts route exists on the server.
47
- // If usePageData() is non-null, the blog page's useOnConnected guard
48
- // (`if (ssrData) return`) skips the fetch entirely.
49
- if (mode === 'ssr' || mode === 'dev') {
50
- it('no /api/posts network request is made — usePageData() skips client fetch', () => {
51
- cy.intercept('GET', '/api/posts').as('apiFetch')
52
- cy.visit('/blog')
53
- // Wait for the page component to fully hydrate before asserting no requests.
54
- cy.get('cer-layout-view').shadow().find('page-blog').shadow()
55
- .find('[data-cy=blog-list]').should('exist')
56
- cy.get('@apiFetch.all').should('have.length', 0)
57
- })
58
- }
59
-
60
- it('blog posts are visible after hydration (all modes)', () => {
61
- cy.visit('/blog')
62
- cy.get('[data-cy=blog-item]', { timeout: 8000 }).should('have.length.at.least', 2)
63
- })
64
- })
65
-
66
- // ─── Blog detail — hard refresh ───────────────────────────────────────────
67
-
68
- describe('usePageData() — blog detail hard refresh', () => {
69
- if (mode !== 'spa') {
70
- it('server response embeds __CER_DATA__ with post detail', () => {
71
- cy.request('/blog/first-post').then((res) => {
72
- expect(res.body).to.include('__CER_DATA__')
73
- expect(res.body).to.include('First Post')
74
- })
75
- })
76
-
77
- it('usePageData() is non-null during hydration re-render on detail page', () => {
78
- cy.visit('/blog/first-post')
79
- cy.get('cer-layout-view').shadow().find('page-blog-slug').shadow()
80
- .find('[data-cy=blog-detail-data-source]').should('have.text', 'ssr')
81
- })
82
- }
83
-
84
- if (mode === 'ssr' || mode === 'dev') {
85
- it('no /api/posts/:slug network request is made — usePageData() skips client fetch', () => {
86
- cy.intercept('GET', '/api/posts/*').as('apiPostDetail')
87
- cy.visit('/blog/first-post')
88
- cy.get('cer-layout-view').shadow().find('page-blog-slug').shadow()
89
- .find('[data-cy=post-title]').should('exist')
90
- cy.get('@apiPostDetail.all').should('have.length', 0)
91
- })
92
- }
93
-
94
- it('"First Post" title renders on hard refresh (all modes)', () => {
95
- cy.visit('/blog/first-post')
96
- cy.get('[data-cy=post-title]', { timeout: 8000 }).should('contain', 'First Post')
97
- })
98
-
99
- it('"Second Post" title renders on hard refresh (all modes)', () => {
100
- cy.visit('/blog/second-post')
101
- cy.get('[data-cy=post-title]', { timeout: 8000 }).should('contain', 'Second Post')
102
- })
103
- })
104
-
105
- // ─── Client-side navigation (post-hydration data loading) ─────────────────
106
-
107
- describe('usePageData() — client-side navigation', () => {
108
- it('navigating to blog from home shows posts', () => {
109
- cy.visit('/')
110
- cy.get('[data-cy=page-nav]').find('a[href="/blog"]').first().click({ force: true })
111
- cy.get('[data-cy=blog-item]', { timeout: 8000 }).should('have.length.at.least', 2)
112
- })
113
-
114
- it('navigating between blog posts loads correct data each time', () => {
115
- cy.visit('/blog/first-post')
116
- cy.get('[data-cy=post-title]', { timeout: 8000 }).should('contain', 'First Post')
117
- cy.get('[data-cy=post-back]').first().click({ force: true })
118
- cy.url().should('include', '/blog')
119
- cy.get('[data-cy=blog-link-second-post]', { timeout: 8000 }).first().click({ force: true })
120
- cy.get('[data-cy=post-title]', { timeout: 8000 }).should('contain', 'Second Post')
121
- })
122
- })
@@ -1,138 +0,0 @@
1
- /**
2
- * useState() e2e tests — verifies globally-keyed reactive state works correctly
3
- * in all rendering modes (SPA, SSR, SSG).
4
- *
5
- * Scenarios covered:
6
- * - Layout shows the default useState title on pages that don't set it
7
- * - Layout reacts to pageTitle set by the use-state-test page (client-side)
8
- * - Mutating useState in the page re-renders the layout reactively
9
- * - Navigating away from the page resets to the default title
10
- * - SSR: initial HTML already contains the title set by the loader
11
- * - SSR: window.__CER_STATE_INIT__ is injected and parsed by the browser
12
- * - SSR: __CER_STATE_INIT__ JSON structure contains the correct key/value
13
- *
14
- * False-positive prevention:
15
- * The kitchen-sink page uses 'useState Page Title' as its reactive title value.
16
- * This string does NOT appear anywhere hardcoded in the page template — all
17
- * occurrences are driven through ${pageTitle.value}. The 'Title Updated!' value
18
- * used by changeTitle() is similarly unique. This means any assertion on these
19
- * strings can only pass if the useState mechanism is actually working.
20
- */
21
-
22
- export {}
23
-
24
- const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
25
-
26
- // Helper: find inside the layout-default shadow DOM (post-hydration).
27
- const layout = () => cy.get('cer-layout-view').shadow().find('layout-default').shadow()
28
- // Helper: find inside the page-use-state-test shadow DOM (post-hydration).
29
- const statePage = () => cy.get('cer-layout-view').shadow().find('page-use-state-test').shadow()
30
-
31
- describe('useState() — default title in layout', () => {
32
- it('shows the default "Kitchen Sink" title on the home page', () => {
33
- cy.visit('/')
34
- cy.get('[data-cy=layout-page-title]').first().should('contain', 'Kitchen Sink')
35
- })
36
- })
37
-
38
- describe('useState() — page sets layout title', () => {
39
- beforeEach(() => {
40
- cy.visit('/use-state-test')
41
- statePage().find('[data-cy=use-state-heading]').should('exist')
42
- })
43
-
44
- it('layout shows the title set by the use-state-test page', () => {
45
- layout().find('[data-cy=layout-page-title]').should('contain', 'useState Page Title')
46
- })
47
-
48
- it('page heading is driven by the pageTitle ref', () => {
49
- statePage().find('[data-cy=use-state-heading]').should('contain', 'useState Page Title')
50
- })
51
-
52
- it('page-title-display shows the pageTitle ref value', () => {
53
- statePage().find('[data-cy=page-title-display]').should('contain', 'useState Page Title')
54
- })
55
-
56
- it('clicking "Change Title" updates the layout title reactively', () => {
57
- statePage().find('[data-cy=change-title]').click({ force: true })
58
- layout().find('[data-cy=layout-page-title]').should('contain', 'Title Updated!')
59
- })
60
-
61
- it('clicking "Change Title" also updates the page heading and in-page display', () => {
62
- statePage().find('[data-cy=change-title]').click({ force: true })
63
- statePage().find('[data-cy=use-state-heading]').should('contain', 'Title Updated!')
64
- statePage().find('[data-cy=page-title-display]').should('contain', 'Title Updated!')
65
- })
66
-
67
- it('clicking "Reset Title" restores the title in layout and page', () => {
68
- statePage().find('[data-cy=change-title]').click({ force: true })
69
- layout().find('[data-cy=layout-page-title]').should('contain', 'Title Updated!')
70
- statePage().find('[data-cy=reset-title]').click({ force: true })
71
- layout().find('[data-cy=layout-page-title]').should('contain', 'useState Page Title')
72
- statePage().find('[data-cy=page-title-display]').should('contain', 'useState Page Title')
73
- })
74
- })
75
-
76
- describe('useState() — title resets to default when navigating away', () => {
77
- it('layout shows default title after navigating from use-state-test to home', () => {
78
- cy.visit('/use-state-test')
79
- statePage().find('[data-cy=use-state-heading]').should('exist')
80
- layout().find('[data-cy=layout-page-title]').should('contain', 'useState Page Title')
81
-
82
- // Navigate to a page that does not set pageTitle
83
- cy.get('[data-cy=nav-home]').first().click({ force: true })
84
- cy.url().should('eq', Cypress.config('baseUrl') + '/')
85
-
86
- // The layout default kicks in for the home page
87
- layout().find('[data-cy=layout-page-title]').should('contain', 'Kitchen Sink')
88
- })
89
- })
90
-
91
- // SSR/SSG only: verify the initial server-rendered HTML already contains
92
- // the page title set by the loader — no JS required.
93
- // 'useState Page Title' only appears in the rendered output via useState;
94
- // it is not hardcoded anywhere in the template, so this check cannot pass
95
- // unless the loader correctly wrote to useState before the layout rendered.
96
- if (mode !== 'spa') {
97
- describe('useState() — SSR: loader sets title before rendering', () => {
98
- it('initial HTML from the server already contains the loader-set title', () => {
99
- cy.request('/use-state-test').then((resp) => {
100
- expect(resp.body).to.include('useState Page Title')
101
- })
102
- })
103
-
104
- it('server injects __CER_STATE_INIT__ script with the loader-set state', () => {
105
- cy.request('/use-state-test').then((resp) => {
106
- expect(resp.body).to.include('__CER_STATE_INIT__')
107
- expect(resp.body).to.include('useState Page Title')
108
- })
109
- })
110
-
111
- it('__CER_STATE_INIT__ JSON contains the pageTitle key with the correct value', () => {
112
- cy.request('/use-state-test').then((resp) => {
113
- // Extract the __CER_STATE_INIT__ assignment from the HTML
114
- const match = resp.body.match(/window\.__CER_STATE_INIT__\s*=\s*(\{[^<]+\})/)
115
- expect(match, '__CER_STATE_INIT__ assignment found in HTML').to.not.be.null
116
- const stateInit = JSON.parse(match![1])
117
- expect(stateInit).to.have.property('pageTitle', 'useState Page Title')
118
- })
119
- })
120
-
121
- it('window.__CER_STATE_INIT__ is present on the browser window after page load', () => {
122
- cy.visit('/use-state-test')
123
- statePage().find('[data-cy=use-state-heading]').should('exist')
124
- cy.window().should('have.property', '__CER_STATE_INIT__')
125
- cy.window().its('__CER_STATE_INIT__').should('have.property', 'pageTitle', 'useState Page Title')
126
- })
127
-
128
- it('layout title is visible in the SSR-rendered light DOM before JS hydrates', () => {
129
- cy.visit('/use-state-test', {
130
- onBeforeLoad(win) {
131
- // Disable custom elements upgrade so we can inspect the pre-rendered light DOM
132
- ;(win as Window & { __CER_HYDRATE_DISABLED__?: boolean }).__CER_HYDRATE_DISABLED__ = true
133
- },
134
- })
135
- cy.get('[data-cy=layout-page-title]').should('contain', 'useState Page Title')
136
- })
137
- })
138
- }
@@ -1,120 +0,0 @@
1
- /**
2
- * Custom Cypress commands for the kitchen sink e2e suite.
3
- */
4
-
5
- /**
6
- * Assert that the raw HTML for a route has correct Declarative Shadow DOM structure:
7
- * - Contains <template shadowrootmode="open"> elements (value must be "open")
8
- * - Each shadow template has embedded <style> (JIT CSS not stripped to <head>)
9
- * - No bare (unnamed) <style> blocks in <head>
10
- * - No loading indicator in the pre-rendered HTML
11
- * - cer-layout-view has pre-rendered content (not empty)
12
- */
13
- Cypress.Commands.add('assertDSDStructure', (path: string) => {
14
- cy.request(path).then((response) => {
15
- const html: string = response.body
16
-
17
- // Must have DSD templates with value "open" (not "closed", not missing)
18
- expect(html, `${path}: should contain <template shadowrootmode="open">`).to.include(
19
- 'shadowrootmode="open"',
20
- )
21
-
22
- // Each shadow template must have its own <style> block (not hoisted to <head>)
23
- const templateMatches = [
24
- ...html.matchAll(/<template shadowrootmode="open"[^>]*>([\s\S]*?)<\/template>/g),
25
- ]
26
- expect(
27
- templateMatches.length,
28
- `${path}: should have at least 1 shadow template with shadowrootmode="open"`,
29
- ).to.be.greaterThan(0)
30
-
31
- templateMatches.forEach(([, content], i) => {
32
- expect(content, `${path}: template[${i}] must contain its own <style> block`).to.include(
33
- '<style',
34
- )
35
- })
36
-
37
- // The <head> must NOT contain raw unnamed <style> blocks (only id'd global ones are OK)
38
- const headMatch = html.match(/<head>([\s\S]*?)<\/head>/)
39
- if (headMatch) {
40
- const bareStyles = headMatch[1].match(/<style(?!\s+id)[^>]*>/g) ?? []
41
- expect(
42
- bareStyles.length,
43
- `${path}: <head> must not contain un-named <style> blocks`,
44
- ).to.equal(0)
45
- }
46
-
47
- // Loading indicator must NOT appear in the initial server-rendered HTML
48
- expect(html, `${path}: loading indicator must not be in initial HTML`).not.to.include(
49
- 'data-cy="loading-indicator"',
50
- )
51
-
52
- // cer-layout-view must have pre-rendered content (not an empty tag)
53
- const layoutViewMatch = html.match(/<cer-layout-view>([\s\S]*?)<\/cer-layout-view>/)
54
- if (layoutViewMatch) {
55
- expect(
56
- layoutViewMatch[1].trim(),
57
- `${path}: cer-layout-view must have pre-rendered content`,
58
- ).not.to.be.empty
59
- }
60
- })
61
- })
62
-
63
- /**
64
- * Assert that the raw HTML for a route contains specific text inside a shadow template.
65
- * Use this to verify that DSD actually rendered the component's content — not just
66
- * that templates exist.
67
- *
68
- * Since shadow templates can be nested (a component's shadow template may contain
69
- * child custom elements with their own shadow templates), we verify that the expected
70
- * text appears anywhere in the raw HTML. assertDSDStructure already confirms that
71
- * the content is wrapped in <template shadowrootmode="open"> — if templates exist
72
- * and the attribute/text is in the HTML, it lives inside those templates.
73
- */
74
- Cypress.Commands.add('assertDSDContains', (path: string, expectedText: string) => {
75
- cy.request(path).then((response) => {
76
- const html: string = response.body
77
-
78
- // Confirm we're in DSD territory first
79
- expect(html, `${path}: page must have DSD templates before checking content`).to.include(
80
- 'shadowrootmode="open"',
81
- )
82
-
83
- expect(html, `${path}: shadow templates should contain "${expectedText}"`).to.include(
84
- expectedText,
85
- )
86
- })
87
- })
88
-
89
- /**
90
- * Assert that after JS hydration, a custom element has a live shadow root.
91
- * This confirms that DSD was processed by the browser and the element was upgraded.
92
- */
93
- Cypress.Commands.add('assertShadowRootLive', (selector: string) => {
94
- cy.window().then((win) => {
95
- const el = win.document.querySelector(selector)
96
- expect(el, `${selector}: element should exist in the DOM`).to.not.be.null
97
- expect(
98
- (el as Element & { shadowRoot: ShadowRoot | null }).shadowRoot,
99
- `${selector}: should have a live shadow root after hydration`,
100
- ).to.not.be.null
101
- })
102
- })
103
-
104
- /**
105
- * Wait for a shadow DOM element to appear (handles lazy rendering).
106
- */
107
- Cypress.Commands.add('getShadow', (selector: string) => {
108
- return cy.get(selector, { includeShadowDom: true })
109
- })
110
-
111
- declare global {
112
- namespace Cypress {
113
- interface Chainable {
114
- assertDSDStructure(path: string): Chainable<void>
115
- assertDSDContains(path: string, expectedText: string): Chainable<void>
116
- assertShadowRootLive(selector: string): Chainable<void>
117
- getShadow(selector: string): Chainable<JQuery<HTMLElement>>
118
- }
119
- }
120
- }
@@ -1,10 +0,0 @@
1
- import './commands'
2
-
3
- // Fail tests on uncaught exceptions only if they're from the app (not network errors)
4
- Cypress.on('uncaught:exception', (err) => {
5
- // Ignore fetch errors (expected in SSG mode where API routes don't exist)
6
- if (err.message.includes('Failed to fetch') || err.message.includes('NetworkError')) {
7
- return false
8
- }
9
- return true
10
- })
@@ -1,14 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "lib": ["ES2022", "DOM"],
5
- "types": ["cypress"],
6
- "strict": true,
7
- "esModuleInterop": true,
8
- "skipLibCheck": true,
9
- "moduleResolution": "bundler",
10
- "module": "ESNext",
11
- "noEmit": true,
12
- },
13
- "include": ["**/*.cy.ts", "support/**/*.ts"]
14
- }
@@ -1,8 +0,0 @@
1
- component('ks-badge', () => {
2
- const slots = useSlots()
3
- return html`
4
- <span data-cy="ks-badge" style="display:inline-block;background:#e0f2fe;color:#0369a1;padding:2px 8px;border-radius:4px;font-size:0.85em;font-weight:600">
5
- ${slots.default ?? 'badge'}
6
- </span>
7
- `
8
- })
@@ -1,9 +0,0 @@
1
- import { ref } from '@jasonshimmy/custom-elements-runtime'
2
-
3
- export function useKsCounter(initial = 0) {
4
- const count = ref(initial)
5
- const increment = () => { count.value++ }
6
- const decrement = () => { count.value-- }
7
- const reset = () => { count.value = 0 }
8
- return { count, increment, decrement, reset }
9
- }
@@ -1,18 +0,0 @@
1
- component('page-error', () => {
2
- const props = useProps<{ error: string; status: string }>({
3
- error: 'An unexpected error occurred.',
4
- status: '500',
5
- })
6
-
7
- return html`
8
- <div data-cy="error-boundary" style="padding:2rem;font-family:sans-serif">
9
- <h2 data-cy="error-heading" style="color:#c00;margin-top:0">
10
- Error ${props.status}
11
- </h2>
12
- <pre data-cy="error-message" style="background:#fff0f0;border:1px solid #fcc;padding:1rem;border-radius:4px">${props.error}</pre>
13
- <button data-cy="error-retry" @click="${() => (globalThis as any).resetError?.()}">
14
- Try again
15
- </button>
16
- </div>
17
- `
18
- })
@@ -1,13 +0,0 @@
1
- component('layout-admin', () => {
2
- return html`
3
- <div data-cy="admin-layout">
4
- <aside data-cy="admin-sidebar">
5
- <p>Admin Panel</p>
6
- <a href="/admin/dashboard" data-cy="admin-nav-dashboard">Dashboard</a>
7
- </aside>
8
- <section data-cy="admin-content">
9
- <slot></slot>
10
- </section>
11
- </div>
12
- `
13
- })
@@ -1,25 +0,0 @@
1
- component('layout-default', () => {
2
- const pageTitle = useState('pageTitle', 'Kitchen Sink')
3
-
4
- return html`
5
- <div>
6
- <header data-cy="site-header">
7
- <span data-cy="layout-page-title">${pageTitle.value}</span>
8
- <nav data-cy="site-nav">
9
- <a data-cy="nav-home" href="/">Home</a>
10
- <a data-cy="nav-about" href="/about">About</a>
11
- <a data-cy="nav-counter" href="/counter">Counter</a>
12
- <a data-cy="nav-blog" href="/blog">Blog</a>
13
- <a data-cy="nav-protected" href="/protected">Protected</a>
14
- <a data-cy="nav-use-state-test" href="/use-state-test">useState Test</a>
15
- </nav>
16
- </header>
17
- <main data-cy="site-main">
18
- <slot></slot>
19
- </main>
20
- <footer data-cy="site-footer">
21
- <p>Kitchen Sink — testing every framework capability</p>
22
- </footer>
23
- </div>
24
- `
25
- })
@@ -1,9 +0,0 @@
1
- // P2-1: Group layout — wraps all pages in the group-meta-test directory.
2
- component('layout-group', () => {
3
- return html`
4
- <div data-cy="group-layout">
5
- <header>Group Layout</header>
6
- <main><slot></slot></main>
7
- </div>
8
- `
9
- })
@@ -1,7 +0,0 @@
1
- component('layout-minimal', () => {
2
- return html`
3
- <div data-cy="minimal-layout">
4
- <slot></slot>
5
- </div>
6
- `
7
- })
@@ -1,9 +0,0 @@
1
- component('page-loading', () => {
2
- return html`
3
- <div data-cy="loading-indicator" style="display:flex;align-items:center;gap:8px;padding:1rem;font-family:sans-serif;color:#888">
4
- <span style="display:inline-block;width:14px;height:14px;border:2px solid #ccc;border-top-color:#555;border-radius:50%;animation:spin 0.7s linear infinite"></span>
5
- Loading…
6
- <style>@keyframes spin { to { transform: rotate(360deg) } }</style>
7
- </div>
8
- `
9
- })
@@ -1,9 +0,0 @@
1
- // Route middleware — redirects to /login if not authenticated.
2
- // Set localStorage.setItem('ks-token', '1') to simulate login.
3
- export default defineMiddleware((_to, _from) => {
4
- const isLoggedIn = typeof localStorage !== 'undefined'
5
- ? !!localStorage.getItem('ks-token')
6
- : false
7
-
8
- return isLoggedIn ? true : '/login'
9
- })
@@ -1,4 +0,0 @@
1
- // P2-1: A no-op middleware used to verify page-level override of group middleware.
2
- export default defineMiddleware((_to, _from, next) => {
3
- next()
4
- })
@@ -1,7 +0,0 @@
1
- // P2-1: Group auth middleware — redirects unauthorized users.
2
- // Adds a visible guard marker so e2e tests can detect it was applied.
3
- export default defineMiddleware(() => {
4
- // Returning a string path redirects to that route.
5
- // In a real app this would check auth state first.
6
- return '/group-auth-blocked'
7
- })
@@ -1,14 +0,0 @@
1
- // Wrapper middleware that uses next() to run code before and after the rest
2
- // of the middleware chain. Stores a breadcrumb in sessionStorage so e2e tests
3
- // can verify that next() was called in the correct order.
4
- export default defineMiddleware(async (_to, _from, next) => {
5
- if (typeof sessionStorage !== 'undefined') {
6
- const prev = sessionStorage.getItem('mw-log') ?? ''
7
- sessionStorage.setItem('mw-log', `${prev}before:`)
8
- }
9
- await next()
10
- if (typeof sessionStorage !== 'undefined') {
11
- const prev = sessionStorage.getItem('mw-log') ?? ''
12
- sessionStorage.setItem('mw-log', `${prev}after`)
13
- }
14
- })
@@ -1,13 +0,0 @@
1
- component('page-login', () => {
2
- return html`
3
- <div>
4
- <h1 data-cy="login-heading">Login</h1>
5
- <p data-cy="login-description">This page uses the <strong>minimal</strong> layout.</p>
6
- <button data-cy="login-btn" @click="${() => { localStorage.setItem('ks-token', '1'); location.href = '/protected' }}">
7
- Simulate Login
8
- </button>
9
- </div>
10
- `
11
- })
12
-
13
- export const meta = { layout: 'minimal' }
@@ -1,16 +0,0 @@
1
- component('page-protected', () => {
2
- const greeting = useInject<string>('ks-greeting', 'No greeting')
3
-
4
- return html`
5
- <div>
6
- <h1 data-cy="protected-heading">Protected Page</h1>
7
- <p data-cy="protected-note">You are authenticated! This page requires the <code>auth</code> middleware.</p>
8
- <p data-cy="plugin-greeting">Plugin says: <strong>${greeting}</strong></p>
9
- <button data-cy="logout-btn" @click="${() => { localStorage.removeItem('ks-token'); location.href = '/protected' }}">
10
- Log out and reload
11
- </button>
12
- </div>
13
- `
14
- })
15
-
16
- export const meta = { middleware: ['auth'] }
@@ -1,9 +0,0 @@
1
- component('page-404', () => {
2
- return html`
3
- <div>
4
- <h1 data-cy="not-found-heading">404 — Not Found</h1>
5
- <p data-cy="not-found-description">The page you are looking for does not exist.</p>
6
- <p><a href="/" data-cy="not-found-home">← Back home</a></p>
7
- </div>
8
- `
9
- })
@@ -1,17 +0,0 @@
1
- component('page-about', () => {
2
- useHead({
3
- title: 'About — Kitchen Sink',
4
- meta: [{ name: 'description', content: 'About the kitchen sink test app.' }],
5
- })
6
-
7
- return html`
8
- <div>
9
- <h1 data-cy="about-heading">About</h1>
10
- <p data-cy="about-description">This page uses the <strong>minimal</strong> layout.</p>
11
- <p data-cy="about-layout-note">It also calls <code>useHead()</code> to set title and meta tags.</p>
12
- <p><a href="/" data-cy="about-back">← Back home</a></p>
13
- </div>
14
- `
15
- })
16
-
17
- export const meta = { layout: 'minimal' }
@@ -1 +0,0 @@
1
- export default 'admin'
@@ -1,11 +0,0 @@
1
- component('page-admin-dashboard', () => {
2
- const config = useRuntimeConfig()
3
- const appName = config.public?.appName ?? 'Kitchen Sink'
4
-
5
- return html`
6
- <div>
7
- <h1 data-cy="admin-dashboard-heading">Admin Dashboard</h1>
8
- <p data-cy="admin-app-name">App: ${appName}</p>
9
- </div>
10
- `
11
- })
@@ -1,18 +0,0 @@
1
- // P2-4: Page that uses defineAsyncComponent with a failing loader.
2
- defineAsyncComponent(
3
- 'ks-async-fail',
4
- () => Promise.reject(new Error('Async component load failed')),
5
- {
6
- loading: () => html`<p>Loading…</p>`,
7
- error: () => html`<p data-cy="async-component-error">Failed to load async component</p>`,
8
- },
9
- )
10
-
11
- component('page-async-component-error-test', () => {
12
- return html`
13
- <div>
14
- <h1 data-cy="async-error-page-heading">Async Component Error Test</h1>
15
- <ks-async-fail></ks-async-fail>
16
- </div>
17
- `
18
- })