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

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