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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (397) hide show
  1. package/dist/cli/checks/lighthouse.d.ts +26 -0
  2. package/dist/cli/checks/lighthouse.d.ts.map +1 -0
  3. package/dist/cli/checks/lighthouse.js +121 -0
  4. package/dist/cli/checks/lighthouse.js.map +1 -0
  5. package/dist/cli/checks/links.d.ts +12 -0
  6. package/dist/cli/checks/links.d.ts.map +1 -0
  7. package/dist/cli/checks/links.js +89 -0
  8. package/dist/cli/checks/links.js.map +1 -0
  9. package/dist/cli/checks/performance.d.ts +17 -0
  10. package/dist/cli/checks/performance.d.ts.map +1 -0
  11. package/dist/cli/checks/performance.js +61 -0
  12. package/dist/cli/checks/performance.js.map +1 -0
  13. package/dist/cli/commands/check.d.ts +3 -0
  14. package/dist/cli/commands/check.d.ts.map +1 -0
  15. package/dist/cli/commands/check.js +85 -0
  16. package/dist/cli/commands/check.js.map +1 -0
  17. package/dist/cli/commands/preview.d.ts.map +1 -1
  18. package/dist/cli/commands/preview.js +37 -4
  19. package/dist/cli/commands/preview.js.map +1 -1
  20. package/dist/cli/create/index.d.ts +11 -1
  21. package/dist/cli/create/index.d.ts.map +1 -1
  22. package/dist/cli/create/index.js +135 -65
  23. package/dist/cli/create/index.js.map +1 -1
  24. package/dist/cli/create/templates/spa/package.json.tpl +5 -3
  25. package/dist/cli/create/templates/ssg/cer.config.ts.tpl +2 -0
  26. package/dist/cli/create/templates/ssg/package.json.tpl +5 -3
  27. package/dist/cli/create/templates/ssr/package.json.tpl +5 -3
  28. package/dist/cli/index.js +2 -0
  29. package/dist/cli/index.js.map +1 -1
  30. package/dist/index.d.ts +3 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/plugin/build-ssg.d.ts +22 -4
  33. package/dist/plugin/build-ssg.d.ts.map +1 -1
  34. package/dist/plugin/build-ssg.js +273 -13
  35. package/dist/plugin/build-ssg.js.map +1 -1
  36. package/dist/plugin/content/parser.d.ts.map +1 -1
  37. package/dist/plugin/content/parser.js +54 -10
  38. package/dist/plugin/content/parser.js.map +1 -1
  39. package/dist/plugin/dev-server.d.ts +6 -1
  40. package/dist/plugin/dev-server.d.ts.map +1 -1
  41. package/dist/plugin/dev-server.js.map +1 -1
  42. package/dist/plugin/dts-generator.d.ts.map +1 -1
  43. package/dist/plugin/dts-generator.js +50 -8
  44. package/dist/plugin/dts-generator.js.map +1 -1
  45. package/dist/plugin/generated-dir.d.ts +2 -0
  46. package/dist/plugin/generated-dir.d.ts.map +1 -1
  47. package/dist/plugin/generated-dir.js +17 -6
  48. package/dist/plugin/generated-dir.js.map +1 -1
  49. package/dist/plugin/html-post-process.d.ts +35 -0
  50. package/dist/plugin/html-post-process.d.ts.map +1 -0
  51. package/dist/plugin/html-post-process.js +112 -0
  52. package/dist/plugin/html-post-process.js.map +1 -0
  53. package/dist/plugin/index.d.ts +9 -0
  54. package/dist/plugin/index.d.ts.map +1 -1
  55. package/dist/plugin/index.js +89 -14
  56. package/dist/plugin/index.js.map +1 -1
  57. package/dist/plugin/transforms/auto-import.d.ts.map +1 -1
  58. package/dist/plugin/transforms/auto-import.js +7 -0
  59. package/dist/plugin/transforms/auto-import.js.map +1 -1
  60. package/dist/plugin/transforms/prune-runtime-css.d.ts +8 -0
  61. package/dist/plugin/transforms/prune-runtime-css.d.ts.map +1 -0
  62. package/dist/plugin/transforms/prune-runtime-css.js +40 -0
  63. package/dist/plugin/transforms/prune-runtime-css.js.map +1 -0
  64. package/dist/runtime/app-template.d.ts +1 -4
  65. package/dist/runtime/app-template.d.ts.map +1 -1
  66. package/dist/runtime/app-template.js +211 -40
  67. package/dist/runtime/app-template.js.map +1 -1
  68. package/dist/runtime/composables/index.d.ts +4 -0
  69. package/dist/runtime/composables/index.d.ts.map +1 -1
  70. package/dist/runtime/composables/index.js +2 -0
  71. package/dist/runtime/composables/index.js.map +1 -1
  72. package/dist/runtime/composables/use-active-headings.d.ts +24 -0
  73. package/dist/runtime/composables/use-active-headings.d.ts.map +1 -0
  74. package/dist/runtime/composables/use-active-headings.js +112 -0
  75. package/dist/runtime/composables/use-active-headings.js.map +1 -0
  76. package/dist/runtime/composables/use-content-page.d.ts +45 -0
  77. package/dist/runtime/composables/use-content-page.d.ts.map +1 -0
  78. package/dist/runtime/composables/use-content-page.js +179 -0
  79. package/dist/runtime/composables/use-content-page.js.map +1 -0
  80. package/dist/runtime/composables/use-content-search.d.ts.map +1 -1
  81. package/dist/runtime/composables/use-content-search.js +1 -5
  82. package/dist/runtime/composables/use-content-search.js.map +1 -1
  83. package/dist/runtime/composables/use-fetch.d.ts +2 -1
  84. package/dist/runtime/composables/use-fetch.d.ts.map +1 -1
  85. package/dist/runtime/composables/use-fetch.js +112 -43
  86. package/dist/runtime/composables/use-fetch.js.map +1 -1
  87. package/dist/runtime/composables/use-head.d.ts.map +1 -1
  88. package/dist/runtime/composables/use-head.js +30 -6
  89. package/dist/runtime/composables/use-head.js.map +1 -1
  90. package/dist/runtime/composables/use-route.d.ts.map +1 -1
  91. package/dist/runtime/composables/use-route.js +39 -11
  92. package/dist/runtime/composables/use-route.js.map +1 -1
  93. package/dist/runtime/content/client.js +2 -2
  94. package/dist/runtime/content/client.js.map +1 -1
  95. package/dist/runtime/entry-server-template.d.ts +16 -1
  96. package/dist/runtime/entry-server-template.d.ts.map +1 -1
  97. package/dist/runtime/entry-server-template.js +120 -13
  98. package/dist/runtime/entry-server-template.js.map +1 -1
  99. package/dist/types/config.d.ts +53 -4
  100. package/dist/types/config.d.ts.map +1 -1
  101. package/dist/types/config.js.map +1 -1
  102. package/dist/types/middleware.d.ts +2 -2
  103. package/dist/types/middleware.d.ts.map +1 -1
  104. package/package.json +22 -19
  105. package/.github/copilot-instructions.md +0 -169
  106. package/.github/workflows/publish.yml +0 -257
  107. package/.nvmrc +0 -1
  108. package/CHANGELOG.md +0 -232
  109. package/CLAUDE.md +0 -113
  110. package/commits.txt +0 -1
  111. package/cypress.config.ts +0 -16
  112. package/docs/authentication.md +0 -285
  113. package/docs/cli.md +0 -324
  114. package/docs/components.md +0 -237
  115. package/docs/composables.md +0 -907
  116. package/docs/configuration.md +0 -667
  117. package/docs/content.md +0 -570
  118. package/docs/data-loading.md +0 -336
  119. package/docs/getting-started.md +0 -237
  120. package/docs/head-management.md +0 -212
  121. package/docs/i18n.md +0 -159
  122. package/docs/layouts.md +0 -224
  123. package/docs/middleware.md +0 -234
  124. package/docs/plugins.md +0 -170
  125. package/docs/rendering-modes.md +0 -377
  126. package/docs/routing.md +0 -485
  127. package/docs/server-api.md +0 -253
  128. package/docs/testing.md +0 -455
  129. package/docs/use-fetch.md +0 -183
  130. package/e2e/cypress/e2e/api.cy.ts +0 -123
  131. package/e2e/cypress/e2e/async-component.cy.ts +0 -27
  132. package/e2e/cypress/e2e/component-splitting.cy.ts +0 -50
  133. package/e2e/cypress/e2e/content.cy.ts +0 -425
  134. package/e2e/cypress/e2e/cookie.cy.ts +0 -85
  135. package/e2e/cypress/e2e/data.cy.ts +0 -158
  136. package/e2e/cypress/e2e/error-boundary.cy.ts +0 -88
  137. package/e2e/cypress/e2e/fouc.cy.ts +0 -254
  138. package/e2e/cypress/e2e/group-meta.cy.ts +0 -36
  139. package/e2e/cypress/e2e/head.cy.ts +0 -89
  140. package/e2e/cypress/e2e/i18n.cy.ts +0 -79
  141. package/e2e/cypress/e2e/interactive.cy.ts +0 -137
  142. package/e2e/cypress/e2e/isr-nested-runtime.cy.ts +0 -102
  143. package/e2e/cypress/e2e/jit-css-custom-colors.cy.ts +0 -43
  144. package/e2e/cypress/e2e/middleware-chain.cy.ts +0 -89
  145. package/e2e/cypress/e2e/middleware-status.cy.ts +0 -30
  146. package/e2e/cypress/e2e/middleware.cy.ts +0 -45
  147. package/e2e/cypress/e2e/navigate.cy.ts +0 -39
  148. package/e2e/cypress/e2e/observability.cy.ts +0 -77
  149. package/e2e/cypress/e2e/per-route-error.cy.ts +0 -42
  150. package/e2e/cypress/e2e/per-route-render.cy.ts +0 -70
  151. package/e2e/cypress/e2e/preview-hardening.cy.ts +0 -88
  152. package/e2e/cypress/e2e/routes.cy.ts +0 -128
  153. package/e2e/cypress/e2e/seo-meta.cy.ts +0 -108
  154. package/e2e/cypress/e2e/server-middleware.cy.ts +0 -46
  155. package/e2e/cypress/e2e/session-rotation.cy.ts +0 -25
  156. package/e2e/cypress/e2e/session.cy.ts +0 -73
  157. package/e2e/cypress/e2e/ssr-render-error.cy.ts +0 -68
  158. package/e2e/cypress/e2e/synthetic-404.cy.ts +0 -45
  159. package/e2e/cypress/e2e/use-page-data.cy.ts +0 -122
  160. package/e2e/cypress/e2e/use-state.cy.ts +0 -138
  161. package/e2e/cypress/support/commands.ts +0 -120
  162. package/e2e/cypress/support/e2e.ts +0 -10
  163. package/e2e/cypress/tsconfig.json +0 -14
  164. package/e2e/kitchen-sink/app/components/ks-badge.ts +0 -8
  165. package/e2e/kitchen-sink/app/composables/useKsCounter.ts +0 -9
  166. package/e2e/kitchen-sink/app/error.ts +0 -18
  167. package/e2e/kitchen-sink/app/layouts/admin.ts +0 -13
  168. package/e2e/kitchen-sink/app/layouts/default.ts +0 -25
  169. package/e2e/kitchen-sink/app/layouts/group.ts +0 -9
  170. package/e2e/kitchen-sink/app/layouts/minimal.ts +0 -7
  171. package/e2e/kitchen-sink/app/loading.ts +0 -9
  172. package/e2e/kitchen-sink/app/middleware/auth.ts +0 -9
  173. package/e2e/kitchen-sink/app/middleware/custom-log.ts +0 -4
  174. package/e2e/kitchen-sink/app/middleware/group-auth.ts +0 -7
  175. package/e2e/kitchen-sink/app/middleware/logger.ts +0 -14
  176. package/e2e/kitchen-sink/app/pages/(auth)/login.ts +0 -13
  177. package/e2e/kitchen-sink/app/pages/(auth)/protected.ts +0 -16
  178. package/e2e/kitchen-sink/app/pages/404.ts +0 -9
  179. package/e2e/kitchen-sink/app/pages/about.ts +0 -17
  180. package/e2e/kitchen-sink/app/pages/admin/_layout.ts +0 -1
  181. package/e2e/kitchen-sink/app/pages/admin/dashboard.ts +0 -11
  182. package/e2e/kitchen-sink/app/pages/async-component-error-test.ts +0 -18
  183. package/e2e/kitchen-sink/app/pages/async-component-test.ts +0 -18
  184. package/e2e/kitchen-sink/app/pages/blog/[slug].ts +0 -59
  185. package/e2e/kitchen-sink/app/pages/blog/index.ts +0 -51
  186. package/e2e/kitchen-sink/app/pages/content-blog.ts +0 -37
  187. package/e2e/kitchen-sink/app/pages/content-doc.ts +0 -42
  188. package/e2e/kitchen-sink/app/pages/content-fallback.ts +0 -36
  189. package/e2e/kitchen-sink/app/pages/content-guides.ts +0 -35
  190. package/e2e/kitchen-sink/app/pages/content-index.ts +0 -39
  191. package/e2e/kitchen-sink/app/pages/content-search.ts +0 -36
  192. package/e2e/kitchen-sink/app/pages/cookie-test.ts +0 -22
  193. package/e2e/kitchen-sink/app/pages/counter.ts +0 -17
  194. package/e2e/kitchen-sink/app/pages/group-auth-blocked.ts +0 -9
  195. package/e2e/kitchen-sink/app/pages/group-meta-test/_layout.ts +0 -6
  196. package/e2e/kitchen-sink/app/pages/group-meta-test/custom-mw.ts +0 -14
  197. package/e2e/kitchen-sink/app/pages/group-meta-test/page.ts +0 -9
  198. package/e2e/kitchen-sink/app/pages/group-meta-test/protected.ts +0 -8
  199. package/e2e/kitchen-sink/app/pages/head.ts +0 -20
  200. package/e2e/kitchen-sink/app/pages/i18n-test.ts +0 -14
  201. package/e2e/kitchen-sink/app/pages/index.ts +0 -27
  202. package/e2e/kitchen-sink/app/pages/isr-test.ts +0 -17
  203. package/e2e/kitchen-sink/app/pages/items/[id].ts +0 -20
  204. package/e2e/kitchen-sink/app/pages/jit-css-custom-colors-test.ts +0 -14
  205. package/e2e/kitchen-sink/app/pages/loader-error-test.ts +0 -13
  206. package/e2e/kitchen-sink/app/pages/loader-props-test.ts +0 -19
  207. package/e2e/kitchen-sink/app/pages/loader-response-error-test.ts +0 -13
  208. package/e2e/kitchen-sink/app/pages/middleware-chain-test.ts +0 -12
  209. package/e2e/kitchen-sink/app/pages/middleware-status-test.ts +0 -9
  210. package/e2e/kitchen-sink/app/pages/navigate-test.ts +0 -16
  211. package/e2e/kitchen-sink/app/pages/observability-test.ts +0 -25
  212. package/e2e/kitchen-sink/app/pages/per-route-error-test.error.ts +0 -13
  213. package/e2e/kitchen-sink/app/pages/per-route-error-test.ts +0 -15
  214. package/e2e/kitchen-sink/app/pages/plugin-dsd-test.ts +0 -10
  215. package/e2e/kitchen-sink/app/pages/render-error-test.ts +0 -12
  216. package/e2e/kitchen-sink/app/pages/render-server-test.ts +0 -12
  217. package/e2e/kitchen-sink/app/pages/render-spa-test.ts +0 -12
  218. package/e2e/kitchen-sink/app/pages/route-info.ts +0 -14
  219. package/e2e/kitchen-sink/app/pages/seo-test.ts +0 -23
  220. package/e2e/kitchen-sink/app/pages/session-rotation-test.ts +0 -25
  221. package/e2e/kitchen-sink/app/pages/use-state-test.ts +0 -37
  222. package/e2e/kitchen-sink/app/plugins/01.setup.ts +0 -7
  223. package/e2e/kitchen-sink/app/plugins/02.ks-plugin-components.ts +0 -27
  224. package/e2e/kitchen-sink/cer-auto-imports.d.ts +0 -51
  225. package/e2e/kitchen-sink/cer-env.d.ts +0 -35
  226. package/e2e/kitchen-sink/cer-tsconfig.json +0 -30
  227. package/e2e/kitchen-sink/cer.config.ts +0 -43
  228. package/e2e/kitchen-sink/content/01.guides/01.index.md +0 -8
  229. package/e2e/kitchen-sink/content/01.guides/02.intro.md +0 -8
  230. package/e2e/kitchen-sink/content/01.guides/10.advanced.md +0 -8
  231. package/e2e/kitchen-sink/content/blog/2026-04-01-hello.md +0 -26
  232. package/e2e/kitchen-sink/content/blog/2026-04-02-draft.md +0 -10
  233. package/e2e/kitchen-sink/content/blog/index.md +0 -8
  234. package/e2e/kitchen-sink/content/blog/no-frontmatter.md +0 -7
  235. package/e2e/kitchen-sink/content/docs/getting-started.md +0 -48
  236. package/e2e/kitchen-sink/content/index.md +0 -16
  237. package/e2e/kitchen-sink/server/api/echo.ts +0 -12
  238. package/e2e/kitchen-sink/server/api/health.ts +0 -3
  239. package/e2e/kitchen-sink/server/api/posts/[slug].ts +0 -11
  240. package/e2e/kitchen-sink/server/api/posts/index.ts +0 -5
  241. package/e2e/kitchen-sink/server/api/session.ts +0 -23
  242. package/e2e/kitchen-sink/server/data/posts.ts +0 -21
  243. package/e2e/kitchen-sink/server/middleware/01-headers.ts +0 -6
  244. package/e2e/kitchen-sink/server/middleware/02-status-test.ts +0 -10
  245. package/e2e/kitchen-sink/tsconfig.json +0 -3
  246. package/e2e/scripts/clean.mjs +0 -14
  247. package/eslint.config.ts +0 -22
  248. package/src/__tests__/cli/adapters/cloudflare-worker.integration.test.ts +0 -132
  249. package/src/__tests__/cli/adapters/cloudflare.test.ts +0 -332
  250. package/src/__tests__/cli/adapters/netlify-bridge.integration.test.ts +0 -139
  251. package/src/__tests__/cli/adapters/netlify.test.ts +0 -286
  252. package/src/__tests__/cli/adapters/vercel-launcher.integration.test.ts +0 -129
  253. package/src/__tests__/cli/adapters/vercel.test.ts +0 -263
  254. package/src/__tests__/cli/preview-hardening.test.ts +0 -265
  255. package/src/__tests__/cli/preview-isr.test.ts +0 -320
  256. package/src/__tests__/index.test.ts +0 -21
  257. package/src/__tests__/plugin/app-template.test.ts +0 -112
  258. package/src/__tests__/plugin/build-ssg-render.test.ts +0 -155
  259. package/src/__tests__/plugin/build-ssg.test.ts +0 -598
  260. package/src/__tests__/plugin/build-ssr.test.ts +0 -192
  261. package/src/__tests__/plugin/cer-app-plugin.test.ts +0 -552
  262. package/src/__tests__/plugin/content/emitter.test.ts +0 -117
  263. package/src/__tests__/plugin/content/loader.test.ts +0 -154
  264. package/src/__tests__/plugin/content/parser.test.ts +0 -381
  265. package/src/__tests__/plugin/content/path-utils.test.ts +0 -69
  266. package/src/__tests__/plugin/content/search.test.ts +0 -119
  267. package/src/__tests__/plugin/dev-server.test.ts +0 -813
  268. package/src/__tests__/plugin/dts-generator.test.ts +0 -394
  269. package/src/__tests__/plugin/entry-server-template.test.ts +0 -385
  270. package/src/__tests__/plugin/generated-dir.test.ts +0 -144
  271. package/src/__tests__/plugin/path-utils.test.ts +0 -411
  272. package/src/__tests__/plugin/resolve-config.test.ts +0 -200
  273. package/src/__tests__/plugin/scanner.test.ts +0 -186
  274. package/src/__tests__/plugin/transforms/auto-import.test.ts +0 -510
  275. package/src/__tests__/plugin/transforms/head-inject.test.ts +0 -178
  276. package/src/__tests__/plugin/virtual/composables.test.ts +0 -57
  277. package/src/__tests__/plugin/virtual/content-components.test.ts +0 -66
  278. package/src/__tests__/plugin/virtual/error.test.ts +0 -71
  279. package/src/__tests__/plugin/virtual/layouts.test.ts +0 -70
  280. package/src/__tests__/plugin/virtual/loading.test.ts +0 -72
  281. package/src/__tests__/plugin/virtual/middleware.test.ts +0 -83
  282. package/src/__tests__/plugin/virtual/plugins.test.ts +0 -129
  283. package/src/__tests__/plugin/virtual/routes.test.ts +0 -884
  284. package/src/__tests__/plugin/virtual/server-api.test.ts +0 -164
  285. package/src/__tests__/plugin/virtual/server-middleware.test.ts +0 -102
  286. package/src/__tests__/runtime/app-template.test.ts +0 -198
  287. package/src/__tests__/runtime/define-middleware.test.ts +0 -64
  288. package/src/__tests__/runtime/define-server-middleware.test.ts +0 -54
  289. package/src/__tests__/runtime/entry-client-template.test.ts +0 -61
  290. package/src/__tests__/runtime/isr-handler.test.ts +0 -338
  291. package/src/__tests__/runtime/oauth/handler.test.ts +0 -358
  292. package/src/__tests__/runtime/oauth/providers.test.ts +0 -47
  293. package/src/__tests__/runtime/oauth-index.test.ts +0 -43
  294. package/src/__tests__/runtime/use-auth.test.ts +0 -169
  295. package/src/__tests__/runtime/use-content-search-composable.test.ts +0 -405
  296. package/src/__tests__/runtime/use-content-search.test.ts +0 -163
  297. package/src/__tests__/runtime/use-content.test.ts +0 -226
  298. package/src/__tests__/runtime/use-cookie.test.ts +0 -277
  299. package/src/__tests__/runtime/use-fetch-component.test.ts +0 -214
  300. package/src/__tests__/runtime/use-fetch.test.ts +0 -377
  301. package/src/__tests__/runtime/use-head.test.ts +0 -266
  302. package/src/__tests__/runtime/use-inject-client.test.ts +0 -67
  303. package/src/__tests__/runtime/use-inject.test.ts +0 -66
  304. package/src/__tests__/runtime/use-locale.test.ts +0 -152
  305. package/src/__tests__/runtime/use-navigate.test.ts +0 -121
  306. package/src/__tests__/runtime/use-page-data.test.ts +0 -298
  307. package/src/__tests__/runtime/use-route.test.ts +0 -156
  308. package/src/__tests__/runtime/use-runtime-config.test.ts +0 -182
  309. package/src/__tests__/runtime/use-seo-meta.test.ts +0 -109
  310. package/src/__tests__/runtime/use-session.test.ts +0 -320
  311. package/src/__tests__/runtime/use-state.test.ts +0 -340
  312. package/src/__tests__/types/config.test.ts +0 -18
  313. package/src/cli/adapters/cloudflare.ts +0 -335
  314. package/src/cli/adapters/netlify.ts +0 -326
  315. package/src/cli/adapters/vercel.ts +0 -311
  316. package/src/cli/commands/adapt.ts +0 -84
  317. package/src/cli/commands/build.ts +0 -165
  318. package/src/cli/commands/dev.ts +0 -125
  319. package/src/cli/commands/generate.ts +0 -91
  320. package/src/cli/commands/preview-isr.ts +0 -172
  321. package/src/cli/commands/preview.ts +0 -489
  322. package/src/cli/create/index.ts +0 -275
  323. package/src/cli/create/templates/shared/.gitignore.tpl +0 -25
  324. package/src/cli/create/templates/shared/app/layouts/default.ts.tpl +0 -15
  325. package/src/cli/create/templates/shared/app/pages/index.ts.tpl +0 -8
  326. package/src/cli/create/templates/shared/index.html.tpl +0 -12
  327. package/src/cli/create/templates/shared/tsconfig.json.tpl +0 -6
  328. package/src/cli/create/templates/spa/cer.config.ts.tpl +0 -6
  329. package/src/cli/create/templates/spa/package.json.tpl +0 -18
  330. package/src/cli/create/templates/ssg/cer.config.ts.tpl +0 -10
  331. package/src/cli/create/templates/ssg/package.json.tpl +0 -19
  332. package/src/cli/create/templates/ssr/cer.config.ts.tpl +0 -6
  333. package/src/cli/create/templates/ssr/package.json.tpl +0 -18
  334. package/src/cli/index.ts +0 -22
  335. package/src/index.ts +0 -20
  336. package/src/plugin/build-ssg.ts +0 -336
  337. package/src/plugin/build-ssr.ts +0 -134
  338. package/src/plugin/content/emitter.ts +0 -50
  339. package/src/plugin/content/index.ts +0 -233
  340. package/src/plugin/content/parser.ts +0 -259
  341. package/src/plugin/content/path-utils.ts +0 -55
  342. package/src/plugin/content/scanner.ts +0 -26
  343. package/src/plugin/content/search.ts +0 -28
  344. package/src/plugin/dev-server.ts +0 -377
  345. package/src/plugin/dts-generator.ts +0 -273
  346. package/src/plugin/generated-dir.ts +0 -121
  347. package/src/plugin/index.ts +0 -553
  348. package/src/plugin/path-utils.ts +0 -186
  349. package/src/plugin/scanner.ts +0 -65
  350. package/src/plugin/transforms/auto-import.ts +0 -206
  351. package/src/plugin/transforms/head-inject.ts +0 -161
  352. package/src/plugin/virtual/composables.ts +0 -28
  353. package/src/plugin/virtual/content-components.ts +0 -83
  354. package/src/plugin/virtual/error.ts +0 -34
  355. package/src/plugin/virtual/layouts.ts +0 -41
  356. package/src/plugin/virtual/loading.ts +0 -32
  357. package/src/plugin/virtual/middleware.ts +0 -45
  358. package/src/plugin/virtual/plugins.ts +0 -46
  359. package/src/plugin/virtual/routes.ts +0 -514
  360. package/src/plugin/virtual/server-api.ts +0 -85
  361. package/src/plugin/virtual/server-middleware.ts +0 -44
  362. package/src/runtime/app-template.ts +0 -380
  363. package/src/runtime/composables/define-middleware.ts +0 -17
  364. package/src/runtime/composables/define-server-middleware.ts +0 -18
  365. package/src/runtime/composables/index.ts +0 -27
  366. package/src/runtime/composables/use-auth.ts +0 -125
  367. package/src/runtime/composables/use-content-search.ts +0 -205
  368. package/src/runtime/composables/use-content.ts +0 -146
  369. package/src/runtime/composables/use-cookie.ts +0 -135
  370. package/src/runtime/composables/use-fetch.ts +0 -438
  371. package/src/runtime/composables/use-head.ts +0 -212
  372. package/src/runtime/composables/use-inject.ts +0 -49
  373. package/src/runtime/composables/use-locale.ts +0 -109
  374. package/src/runtime/composables/use-navigate.ts +0 -58
  375. package/src/runtime/composables/use-page-data.ts +0 -93
  376. package/src/runtime/composables/use-route.ts +0 -71
  377. package/src/runtime/composables/use-runtime-config.ts +0 -123
  378. package/src/runtime/composables/use-seo-meta.ts +0 -80
  379. package/src/runtime/composables/use-session.ts +0 -186
  380. package/src/runtime/composables/use-state.ts +0 -92
  381. package/src/runtime/content/client.ts +0 -168
  382. package/src/runtime/entry-client-template.ts +0 -39
  383. package/src/runtime/entry-server-template.ts +0 -493
  384. package/src/runtime/isr-handler.ts +0 -184
  385. package/src/runtime/oauth/handler.ts +0 -407
  386. package/src/runtime/oauth/index.ts +0 -49
  387. package/src/runtime/oauth/providers.ts +0 -38
  388. package/src/types/api.ts +0 -40
  389. package/src/types/config.ts +0 -371
  390. package/src/types/content.ts +0 -66
  391. package/src/types/index.ts +0 -7
  392. package/src/types/middleware.ts +0 -63
  393. package/src/types/page.ts +0 -117
  394. package/src/types/plugin.ts +0 -34
  395. package/tsconfig.build.json +0 -10
  396. package/tsconfig.json +0 -19
  397. package/vitest.config.ts +0 -33
@@ -1,109 +0,0 @@
1
- import type { IncomingMessage } from 'node:http'
2
-
3
- /** Return value of `useLocale()`. Exposes the active locale and helpers for locale-aware navigation. */
4
- export interface LocaleComposable {
5
- /** The active locale code for the current request / page. */
6
- readonly locale: string
7
- /** All configured locale codes. */
8
- readonly locales: string[]
9
- /** The default locale code. */
10
- readonly defaultLocale: string
11
- /**
12
- * Returns the localised version of `path` for `targetLocale`.
13
- *
14
- * @example
15
- * switchLocalePath('fr', '/about') // → '/fr/about'
16
- * switchLocalePath('en', '/fr/about') // → '/about' (when en is default + prefix_except_default)
17
- */
18
- switchLocalePath(targetLocale: string, path?: string): string
19
- }
20
-
21
- interface I18nVirtualConfig {
22
- locales: string[]
23
- defaultLocale: string
24
- strategy: 'prefix' | 'prefix_except_default' | 'no_prefix'
25
- }
26
-
27
- // ─── Internal helpers ─────────────────────────────────────────────────────────
28
-
29
- function _extractLocaleFromPath(pathname: string, locales: string[]): string | null {
30
- const first = pathname.split('/')[1]
31
- return locales.includes(first) ? first : null
32
- }
33
-
34
- function _stripLocalePrefix(pathname: string, locale: string): string {
35
- const prefix = `/${locale}`
36
- if (pathname === prefix) return '/'
37
- if (pathname.startsWith(`${prefix}/`)) return pathname.slice(prefix.length)
38
- return pathname
39
- }
40
-
41
- function _buildLocalePath(
42
- pathname: string,
43
- targetLocale: string,
44
- currentLocale: string,
45
- config: I18nVirtualConfig,
46
- ): string {
47
- // Strip the current locale prefix (if any) to get the bare path
48
- const bare = _stripLocalePrefix(pathname, currentLocale)
49
- if (config.strategy === 'no_prefix') return bare
50
- if (config.strategy === 'prefix_except_default' && targetLocale === config.defaultLocale) return bare
51
- return `/${targetLocale}${bare === '/' ? '' : bare}`
52
- }
53
-
54
- // ─── Composable ───────────────────────────────────────────────────────────────
55
-
56
- /**
57
- * Internationalisation composable. Returns the active locale and helpers for
58
- * building locale-aware URLs. Requires `i18n` to be configured in `cer.config.ts`.
59
- *
60
- * Works isomorphically: on the server it reads the URL path via AsyncLocalStorage;
61
- * on the client it reads `window.location.pathname`.
62
- *
63
- * When `i18n` is not configured, `locale` equals `'default'` and `locales` is `['default']`.
64
- *
65
- * @example
66
- * ```ts
67
- * const { locale, switchLocalePath } = useLocale()
68
- * console.log(locale) // 'fr'
69
- * console.log(switchLocalePath('en', '/fr/about')) // '/about'
70
- * ```
71
- */
72
- export function useLocale(): LocaleComposable {
73
- // Read i18n config from the virtual module at runtime.
74
- // The virtual module is replaced by the bundler at build time.
75
- const g = globalThis as Record<string, unknown>
76
- const i18nConfig = g['__CER_I18N_CONFIG__'] as I18nVirtualConfig | null | undefined
77
-
78
- const locales = i18nConfig?.locales ?? ['default']
79
- const defaultLocale = i18nConfig?.defaultLocale ?? 'default'
80
- const strategy = i18nConfig?.strategy ?? 'no_prefix'
81
-
82
- // Resolve the current pathname from the server request context or window.
83
- let pathname = '/'
84
- const reqStore = g['__CER_REQ_STORE__'] as
85
- | { getStore(): { req: IncomingMessage } | null }
86
- | undefined
87
- if (reqStore) {
88
- const ctx = reqStore.getStore()
89
- if (ctx?.req.url) {
90
- try { pathname = new URL(ctx.req.url, 'http://x').pathname } catch { /* ignore */ }
91
- }
92
- } else if (typeof window !== 'undefined') {
93
- pathname = window.location.pathname
94
- }
95
-
96
- const detectedLocale = strategy !== 'no_prefix'
97
- ? (_extractLocaleFromPath(pathname, locales) ?? defaultLocale)
98
- : defaultLocale
99
-
100
- return {
101
- get locale() { return detectedLocale },
102
- get locales() { return locales },
103
- get defaultLocale() { return defaultLocale },
104
- switchLocalePath(targetLocale: string, path?: string): string {
105
- const base = path ?? pathname
106
- return _buildLocalePath(base, targetLocale, detectedLocale, { locales, defaultLocale, strategy })
107
- },
108
- }
109
- }
@@ -1,58 +0,0 @@
1
- /**
2
- * navigateTo — programmatic navigation.
3
- *
4
- * Works isomorphically:
5
- * - **Server context** (inside a loader or middleware): sends a 302 redirect
6
- * immediately by writing to the current request's `res` object via
7
- * `AsyncLocalStorage`. The response is ended and the function returns.
8
- * - **Client context**: delegates to the framework router so the SPA
9
- * navigation pipeline (middleware, loaders, isNavigating) runs normally.
10
- * Falls back to `window.location.href` if the router is not available.
11
- *
12
- * @example
13
- * ```ts
14
- * // app/middleware/require-auth.ts
15
- * export default defineMiddleware(() => {
16
- * const { loggedIn } = useAuth()
17
- * if (!loggedIn) return navigateTo('/login')
18
- * })
19
- * ```
20
- *
21
- * @example
22
- * ```ts
23
- * // app/pages/dashboard.ts
24
- * component('page-dashboard', () => {
25
- * useOnConnected(() => {
26
- * if (someCondition) navigateTo('/home')
27
- * })
28
- * })
29
- * ```
30
- */
31
-
32
- export function navigateTo(path: string): void | Promise<void> {
33
- const g = globalThis as Record<string, unknown>
34
-
35
- // Server: redirect via the request-scoped req/res store.
36
- const reqStore = g['__CER_REQ_STORE__'] as {
37
- getStore(): { res: { statusCode: number; setHeader(k: string, v: string): void; end(): void; writableEnded?: boolean } } | null
38
- } | undefined
39
-
40
- if (reqStore) {
41
- const store = reqStore.getStore()
42
- if (store?.res && !store.res.writableEnded) {
43
- store.res.statusCode = 302
44
- store.res.setHeader('Location', path)
45
- store.res.end()
46
- return
47
- }
48
- }
49
-
50
- // Client: use the framework router so the full navigation pipeline runs.
51
- const router = g['__cerRouter'] as { push(path: string): Promise<void> } | undefined
52
- if (router) return router.push(path)
53
-
54
- // Fallback: hard redirect.
55
- if (typeof window !== 'undefined') {
56
- window.location.href = path
57
- }
58
- }
@@ -1,93 +0,0 @@
1
- /**
2
- * usePageData — reads SSR-injected loader data for the current page.
3
- *
4
- * During SSR/SSG the server calls the matched route's `loader()` function
5
- * and makes the result available in two ways:
6
- *
7
- * 1. **Server render pass** — the data is stored in a per-request
8
- * `AsyncLocalStorage` context (set via `_cerDataStore.run(data, ...)` in the
9
- * entry-server template). `usePageData()` reads this store so the component
10
- * renders with real data in the initial SSR/SSG HTML.
11
- *
12
- * 2. **Client hydration** — the server also serializes the data as
13
- * `window.__CER_DATA__` in the page `<head>`. On first component render
14
- * `usePageData()` returns that value, caches it on the component context, and
15
- * returns the same cached value on all subsequent re-renders of that component
16
- * instance. The data remains available for the initial hydrated route until
17
- * the next client-side navigation clears it before loading new page data.
18
- *
19
- * **Why caching is necessary**: the render function passed to `component()` is
20
- * called on every re-render (it is the render function, not a setup function).
21
- * Without caching, `usePageData()` could return `null` on later re-renders if a
22
- * browser upgrades or re-renders the hydrated page after the initial read,
23
- * flip the `ssrData` guard from truthy → null, and re-trigger client-side fetches.
24
- *
25
- * @returns The serialized loader result, or `null` if no SSR data is present.
26
- *
27
- * @example
28
- * ```ts
29
- * component('page-blog-slug', () => {
30
- * const ssrData = usePageData<{ title: string; body: string }>()
31
- * const title = ref(ssrData?.title ?? '')
32
- * const body = ref(ssrData?.body ?? '')
33
- *
34
- * useOnConnected(() => {
35
- * if (ssrData) return // already hydrated from SSR — skip fetch
36
- * fetch(`/api/posts/${props.slug}`).then(r => r.json()).then(post => {
37
- * title.value = post.title
38
- * body.value = post.body
39
- * })
40
- * })
41
- * })
42
- * ```
43
- */
44
- import { getCurrentComponentContext } from '@jasonshimmy/custom-elements-runtime'
45
-
46
- // Key used to cache the page data on the component context object across re-renders.
47
- const _PAGE_DATA_KEY = '_cerPageData'
48
-
49
- export function usePageData<T = unknown>(): T | null {
50
- const g = globalThis as Record<string, unknown>
51
-
52
- // Server-side: read from the per-request AsyncLocalStorage context.
53
- // __CER_DATA_STORE__ is set by the entry-server template and is only present
54
- // in Node.js, so this branch is tree-shaken out of the client bundle.
55
- const store = g['__CER_DATA_STORE__'] as { getStore(): unknown } | undefined
56
- if (store) {
57
- const ssrData = store.getStore() as T | null | undefined
58
- if (ssrData !== undefined && ssrData !== null) return ssrData
59
- }
60
-
61
- // Client-side: check the component context cache first.
62
- // getCurrentComponentContext() returns the context object for the component
63
- // whose renderFn is currently executing (set by the component() runtime
64
- // before calling renderFn). Caching on the context ensures the same value is
65
- // returned on every re-render of the same element instance even if the
66
- // browser performs a later hydration-time re-render.
67
- const ctx = getCurrentComponentContext() as Record<string, unknown> | null
68
- if (ctx) {
69
- if (_PAGE_DATA_KEY in ctx) {
70
- return ctx[_PAGE_DATA_KEY] as T | null
71
- }
72
- }
73
-
74
- // Read the raw value from the global set by the server-rendered <script> tag.
75
- const data = g['__CER_DATA__'] as T | undefined | null
76
- const result: T | null = (data === undefined || data === null) ? null : data
77
-
78
- // Cache on the component context so subsequent re-renders of this element
79
- // instance return the same value without reading __CER_DATA__ again.
80
- // Use Object.defineProperty to bypass the reactive Proxy set-trap on context,
81
- // which would otherwise schedule a spurious re-render (and risk an infinite loop)
82
- // every time we first cache the value.
83
- if (ctx) {
84
- Object.defineProperty(ctx, _PAGE_DATA_KEY, {
85
- value: result,
86
- writable: false,
87
- enumerable: false,
88
- configurable: true,
89
- })
90
- }
91
-
92
- return result
93
- }
@@ -1,71 +0,0 @@
1
- /**
2
- * useRoute — returns the current route's path, params, query, and meta.
3
- *
4
- * Works isomorphically:
5
- * - **Server render pass** — reads from `globalThis.__CER_ROUTE_STORE__`
6
- * (AsyncLocalStorage populated by the entry-server handler before rendering).
7
- * - **Client** — reads from the global router instance exposed by the app
8
- * entry (`globalThis.__cerRouter`).
9
- *
10
- * @example
11
- * ```ts
12
- * // app/layouts/default.ts
13
- * component('layout-default', () => {
14
- * const route = useRoute()
15
- * return html`
16
- * <nav>${route.meta?.title ?? 'My App'}</nav>
17
- * <slot></slot>
18
- * `
19
- * })
20
- * ```
21
- *
22
- * @example
23
- * ```ts
24
- * // app/pages/post.ts
25
- * component('page-post', () => {
26
- * const { params } = useRoute()
27
- * const { data: post } = useFetch(\`/api/posts/\${params.id}\`)
28
- * })
29
- * ```
30
- */
31
-
32
- export interface RouteInfo {
33
- /** Current URL path, e.g. `'/posts/42'`. */
34
- path: string
35
- /** Dynamic route params, e.g. `{ id: '42' }`. */
36
- params: Record<string, string>
37
- /** Parsed query string params, e.g. `{ page: '2' }`. */
38
- query: Record<string, string>
39
- /** Static route meta object exported by the matched page module. */
40
- meta: Record<string, unknown> | null
41
- }
42
-
43
- export function useRoute(): RouteInfo {
44
- const g = globalThis as Record<string, unknown>
45
-
46
- // Server: read from the per-request AsyncLocalStorage context.
47
- const routeStore = g['__CER_ROUTE_STORE__'] as { getStore(): unknown } | undefined
48
- if (routeStore) {
49
- const info = routeStore.getStore() as RouteInfo | null
50
- if (info) return info
51
- }
52
-
53
- // Client: read from the global router set by the app entry.
54
- const router = g['__cerRouter'] as {
55
- getCurrent(): { path: string; query?: Record<string, string> }
56
- matchRoute(path: string): { route?: { meta?: unknown }; params?: Record<string, string> } | null
57
- } | undefined
58
-
59
- if (router) {
60
- const current = router.getCurrent()
61
- const matched = router.matchRoute(current.path)
62
- return {
63
- path: current.path,
64
- params: (matched?.params ?? {}) as Record<string, string>,
65
- query: (current.query ?? {}) as Record<string, string>,
66
- meta: (matched?.route?.meta as Record<string, unknown>) ?? null,
67
- }
68
- }
69
-
70
- return { path: '/', params: {}, query: {}, meta: null }
71
- }
@@ -1,123 +0,0 @@
1
- /** Resolved public runtime config values. Available on both server and client. */
2
- export interface RuntimeConfigPublic {
3
- [key: string]: unknown
4
- }
5
-
6
- /** Resolved private runtime config values. Available on the server only — never present on the client. */
7
- export interface RuntimeConfigPrivate {
8
- [key: string]: string | string[]
9
- }
10
-
11
- /** Return value of `useRuntimeConfig()`. */
12
- export interface RuntimeConfigResult {
13
- public: RuntimeConfigPublic
14
- private?: RuntimeConfigPrivate
15
- }
16
-
17
- /**
18
- * Returns the runtime configuration set in `cer.config.ts`.
19
- *
20
- * - `public` — available on both server and client.
21
- * - `private` — available on the server only (resolved from `process.env` at
22
- * startup). Never present on the client.
23
- *
24
- * @example
25
- * // cer.config.ts
26
- * export default defineConfig({
27
- * runtimeConfig: {
28
- * public: { apiBase: process.env.VITE_API_BASE ?? '/api' },
29
- * private: { dbUrl: '', secretKey: '' },
30
- * },
31
- * })
32
- *
33
- * // app/pages/index.ts (loader — server-only)
34
- * const { private: priv } = useRuntimeConfig()
35
- * const rows = await db.query(priv.dbUrl)
36
- */
37
- export function useRuntimeConfig(): RuntimeConfigResult {
38
- // Dynamic import resolved at runtime — avoids a static circular dependency
39
- // between the composable and the virtual module.
40
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
- const mod = (globalThis as any).__cerRuntimeConfig
42
- const config: RuntimeConfigResult = mod ? (mod as RuntimeConfigResult) : { public: {} }
43
-
44
- // In browser contexts, wrap the result in a Proxy that throws a clear,
45
- // actionable error if any code attempts to read `runtimeConfig.private`.
46
- // Private values are server-only secrets and are never serialized into the
47
- // client bundle — accessing them client-side is always a bug.
48
- if (typeof window !== 'undefined') {
49
- return new Proxy(config, {
50
- get(target, prop) {
51
- if (prop === 'private') {
52
- throw new Error(
53
- '[cer-app] runtimeConfig.private is not available in the browser. ' +
54
- 'Move this access into a server-only loader, middleware, or API handler.',
55
- )
56
- }
57
- return Reflect.get(target, prop)
58
- },
59
- })
60
- }
61
-
62
- return config
63
- }
64
-
65
- /**
66
- * Called once during app bootstrap to store the resolved runtimeConfig on
67
- * globalThis so useRuntimeConfig() can access it synchronously in any context
68
- * (component render, composable, server handler).
69
- */
70
- export function initRuntimeConfig(config: RuntimeConfigResult): void {
71
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
- ;(globalThis as any).__cerRuntimeConfig = config
73
- }
74
-
75
- /**
76
- * Converts a camelCase or mixed key to UPPER_SNAKE_CASE for env var lookup.
77
- * Examples: `dbUrl` → `DB_URL`, `secretKey` → `SECRET_KEY`, `API_KEY` → `API_KEY`.
78
- */
79
- function toUpperSnakeCase(key: string): string {
80
- return key
81
- .replace(/([a-z])([A-Z])/g, '$1_$2')
82
- .toUpperCase()
83
- }
84
-
85
- /**
86
- * Resolves a private config object by looking up each key in the supplied
87
- * environment variable map, with the following precedence:
88
- *
89
- * 1. `env[key]` — exact case (e.g. `process.env.dbUrl`)
90
- * 2. `env[UPPER_SNAKE_CASE(key)]` — conventional env var form (e.g. `process.env.DB_URL`)
91
- * 3. `defaultValue` — the declared default from `cer.config.ts`
92
- *
93
- * Array values (e.g. `sessionSecret: [newSecret, oldSecret]`) are passed
94
- * through unchanged — they are already resolved by the caller at config time.
95
- *
96
- * Accepts an optional `env` parameter so the function is unit-testable
97
- * without mutating `process.env`.
98
- */
99
- export function resolvePrivateConfig(
100
- defaults: Record<string, string | string[]>,
101
- env: Record<string, string | undefined> = process.env as Record<string, string | undefined>,
102
- ): Record<string, string | string[]> {
103
- return Object.fromEntries(
104
- Object.entries(defaults).map(([key, defaultValue]) => {
105
- // Array values are already fully resolved at config build time — pass through.
106
- if (Array.isArray(defaultValue)) {
107
- return [key, defaultValue.filter(Boolean)]
108
- }
109
- const envKey = toUpperSnakeCase(key)
110
- const resolved = env[key] ?? env[envKey] ?? defaultValue
111
- // Warn when no env var was found and the declared default is an empty string.
112
- // An empty-string default is the conventional way to declare a required secret
113
- // (the key exists for typing purposes but has no safe default value).
114
- if (resolved === '' && env[key] === undefined && env[envKey] === undefined) {
115
- console.warn(
116
- `[cer-app] runtimeConfig.private: "${key}" is an empty string — ` +
117
- `set ${envKey} in the environment to provide a value.`,
118
- )
119
- }
120
- return [key, resolved]
121
- }),
122
- )
123
- }
@@ -1,80 +0,0 @@
1
- import { useHead } from './use-head.js'
2
-
3
- /**
4
- * Convenience input for common SEO meta tags.
5
- * Pass to `useSeoMeta()` — it maps each field to the correct `<meta>` or `<title>` tag automatically.
6
- * All fields are optional.
7
- */
8
- export interface SeoMetaInput {
9
- /** Sets the document title. */
10
- title?: string
11
- /** Sets the meta description. */
12
- description?: string
13
- // Open Graph
14
- ogTitle?: string
15
- ogDescription?: string
16
- ogImage?: string
17
- ogUrl?: string
18
- /** e.g. `'website'`, `'article'`. No tag is emitted when omitted. */
19
- ogType?: string
20
- ogSiteName?: string
21
- // Twitter / X
22
- /** e.g. `'summary'`, `'summary_large_image'`. No tag is emitted when omitted. */
23
- twitterCard?: string
24
- twitterTitle?: string
25
- twitterDescription?: string
26
- twitterImage?: string
27
- /** Twitter/X site handle, e.g. '@mysite'. */
28
- twitterSite?: string
29
- /** Canonical URL injected as <link rel="canonical">. */
30
- canonical?: string
31
- }
32
-
33
- /**
34
- * Thin wrapper over `useHead()` for common SEO tags.
35
- *
36
- * Sets the page title, meta description, Open Graph tags, Twitter Card tags,
37
- * and a canonical link element. Only tags with a non-undefined value are emitted.
38
- *
39
- * It is auto-imported, so you don't need to import it manually.
40
- *
41
- * @example
42
- * ```ts
43
- * useSeoMeta({
44
- * title: 'My page',
45
- * description: 'A great page.',
46
- * ogImage: 'https://example.com/og.png',
47
- * canonical: 'https://example.com/my-page',
48
- * })
49
- * ```
50
- */
51
- export function useSeoMeta(input: SeoMetaInput): void {
52
- const meta: Array<Record<string, string>> = []
53
- const link: Array<Record<string, string>> = []
54
-
55
- if (input.description !== undefined) meta.push({ name: 'description', content: input.description })
56
-
57
- // Open Graph
58
- if (input.ogTitle !== undefined) meta.push({ property: 'og:title', content: input.ogTitle })
59
- if (input.ogDescription !== undefined) meta.push({ property: 'og:description', content: input.ogDescription })
60
- if (input.ogImage !== undefined) meta.push({ property: 'og:image', content: input.ogImage })
61
- if (input.ogUrl !== undefined) meta.push({ property: 'og:url', content: input.ogUrl })
62
- if (input.ogType !== undefined) meta.push({ property: 'og:type', content: input.ogType })
63
- if (input.ogSiteName !== undefined) meta.push({ property: 'og:site_name', content: input.ogSiteName })
64
-
65
- // Twitter / X
66
- if (input.twitterCard !== undefined) meta.push({ name: 'twitter:card', content: input.twitterCard })
67
- if (input.twitterTitle !== undefined) meta.push({ name: 'twitter:title', content: input.twitterTitle })
68
- if (input.twitterDescription !== undefined) meta.push({ name: 'twitter:description', content: input.twitterDescription })
69
- if (input.twitterImage !== undefined) meta.push({ name: 'twitter:image', content: input.twitterImage })
70
- if (input.twitterSite !== undefined) meta.push({ name: 'twitter:site', content: input.twitterSite })
71
-
72
- // Canonical link
73
- if (input.canonical !== undefined) link.push({ rel: 'canonical', href: input.canonical })
74
-
75
- useHead({
76
- title: input.title,
77
- meta: meta.length > 0 ? meta : undefined,
78
- link: link.length > 0 ? link : undefined,
79
- })
80
- }