@velora-cms/server 0.11.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 (367) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +65 -0
  3. package/dist/admin-bundle/assets/__virtual_mf___mfe_internal__velora_admin__mf_owner__1__loadShare__react__loadShare__.js_commonjs-proxy-Ng0fOpdU.js +1 -0
  4. package/dist/admin-bundle/assets/__virtual_mf___mfe_internal__velora_admin__mf_owner__1__loadShare__react_mf_2_dom__loadShare__.js_commonjs-proxy-oc1i_iBU.js +9 -0
  5. package/dist/admin-bundle/assets/_virtual_mf-localSharedImportMap___mfe_internal__velora_admin__mf_owner__1-DOKdWYyj.js +1 -0
  6. package/dist/admin-bundle/assets/_virtual_mf___mfe_internal__velora_admin__mf_owner__1__loadShare___mf_0_velora_mf_2_cms_mf_1_plugin_mf_2_sdk__loadShare__.js-C1-ZAxwO.js +2 -0
  7. package/dist/admin-bundle/assets/_virtual_mf___mfe_internal__velora_admin__mf_owner__1__loadShare__react__loadShare__.js-BuUBskgj.js +9 -0
  8. package/dist/admin-bundle/assets/_virtual_mf___mfe_internal__velora_admin__mf_owner__1__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DMaku-HC.js +9 -0
  9. package/dist/admin-bundle/assets/_virtual_mf___mfe_internal__velora_admin__mf_owner__1__loadShare__react_mf_2_dom__loadShare__.js-DYfqn12F.js +1 -0
  10. package/dist/admin-bundle/assets/_virtual_mf___mfe_internal__velora_admin__mf_owner__1__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-BPoj3DC9.js +25 -0
  11. package/dist/admin-bundle/assets/content-trash.schema-DfXHkC-w.js +72 -0
  12. package/dist/admin-bundle/assets/hostInit--C4xK6nj.js +1 -0
  13. package/dist/admin-bundle/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2 +0 -0
  14. package/dist/admin-bundle/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff +0 -0
  15. package/dist/admin-bundle/assets/ibm-plex-mono-cyrillic-500-normal-Ael50iVv.woff +0 -0
  16. package/dist/admin-bundle/assets/ibm-plex-mono-cyrillic-500-normal-Bq9vWWag.woff2 +0 -0
  17. package/dist/admin-bundle/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff +0 -0
  18. package/dist/admin-bundle/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2 +0 -0
  19. package/dist/admin-bundle/assets/ibm-plex-mono-cyrillic-ext-500-normal-BIfNGwUT.woff +0 -0
  20. package/dist/admin-bundle/assets/ibm-plex-mono-cyrillic-ext-500-normal-BqneJy0T.woff2 +0 -0
  21. package/dist/admin-bundle/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  22. package/dist/admin-bundle/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  23. package/dist/admin-bundle/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  24. package/dist/admin-bundle/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  25. package/dist/admin-bundle/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
  26. package/dist/admin-bundle/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff +0 -0
  27. package/dist/admin-bundle/assets/ibm-plex-mono-latin-ext-500-normal-CAhNIIs5.woff2 +0 -0
  28. package/dist/admin-bundle/assets/ibm-plex-mono-latin-ext-500-normal-CZ70TYgx.woff +0 -0
  29. package/dist/admin-bundle/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2 +0 -0
  30. package/dist/admin-bundle/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff +0 -0
  31. package/dist/admin-bundle/assets/ibm-plex-mono-vietnamese-500-normal-C8zxqsMH.woff +0 -0
  32. package/dist/admin-bundle/assets/ibm-plex-mono-vietnamese-500-normal-DZ4AoWbu.woff2 +0 -0
  33. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-arabic-400-normal-CyU-ddYS.woff2 +0 -0
  34. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-arabic-400-normal-EA1o-u_Q.woff +0 -0
  35. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-arabic-500-normal-C4MQITzh.woff2 +0 -0
  36. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-arabic-500-normal-DPXcppbm.woff +0 -0
  37. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-arabic-600-normal-0pRdybE_.woff2 +0 -0
  38. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-arabic-600-normal-MJZ0liF5.woff +0 -0
  39. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-400-normal-Bo5KPYvw.woff2 +0 -0
  40. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-400-normal-CFZh1unN.woff +0 -0
  41. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-500-normal-BletK1Hp.woff +0 -0
  42. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-500-normal-Cd6jVIg7.woff2 +0 -0
  43. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-600-normal-Dk5eISD_.woff +0 -0
  44. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-600-normal-KrqB56Mw.woff2 +0 -0
  45. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-ext-400-normal-BeVLg08x.woff +0 -0
  46. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-ext-400-normal-BpLfq-63.woff2 +0 -0
  47. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-ext-500-normal-Ck_W4G78.woff2 +0 -0
  48. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-ext-500-normal-eJxPnL1P.woff +0 -0
  49. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-ext-600-normal-DT29Q8HW.woff +0 -0
  50. package/dist/admin-bundle/assets/ibm-plex-sans-arabic-latin-ext-600-normal-DjDAeNQD.woff2 +0 -0
  51. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-400-normal-BTotfTJu.woff +0 -0
  52. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-400-normal-DZqxrq2p.woff2 +0 -0
  53. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-500-normal-ByOcLdNv.woff +0 -0
  54. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-500-normal-CocWQlwt.woff2 +0 -0
  55. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-600-normal-71GNu3SW.woff2 +0 -0
  56. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-600-normal-BGq0mW3O.woff +0 -0
  57. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-ext-400-normal-Dsrv2Tcn.woff +0 -0
  58. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-ext-400-normal-g30qAdWV.woff2 +0 -0
  59. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-ext-500-normal-Cs5J6C77.woff2 +0 -0
  60. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-ext-500-normal-DB5PtV2g.woff +0 -0
  61. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-ext-600-normal-Bz0x94Yp.woff +0 -0
  62. package/dist/admin-bundle/assets/ibm-plex-sans-cyrillic-ext-600-normal-DUMzJB7m.woff2 +0 -0
  63. package/dist/admin-bundle/assets/ibm-plex-sans-greek-400-normal-D9ESIMu3.woff +0 -0
  64. package/dist/admin-bundle/assets/ibm-plex-sans-greek-400-normal-_efipK4i.woff2 +0 -0
  65. package/dist/admin-bundle/assets/ibm-plex-sans-greek-500-normal-CuWXN6rf.woff +0 -0
  66. package/dist/admin-bundle/assets/ibm-plex-sans-greek-500-normal-JMMifIXV.woff2 +0 -0
  67. package/dist/admin-bundle/assets/ibm-plex-sans-greek-600-normal-D-CqTdkO.woff +0 -0
  68. package/dist/admin-bundle/assets/ibm-plex-sans-greek-600-normal-DzTrcv_p.woff2 +0 -0
  69. package/dist/admin-bundle/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  70. package/dist/admin-bundle/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  71. package/dist/admin-bundle/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  72. package/dist/admin-bundle/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  73. package/dist/admin-bundle/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  74. package/dist/admin-bundle/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  75. package/dist/admin-bundle/assets/ibm-plex-sans-latin-ext-400-normal-C5H60-Va.woff2 +0 -0
  76. package/dist/admin-bundle/assets/ibm-plex-sans-latin-ext-400-normal-RBey6euL.woff +0 -0
  77. package/dist/admin-bundle/assets/ibm-plex-sans-latin-ext-500-normal-D0aIdm-b.woff +0 -0
  78. package/dist/admin-bundle/assets/ibm-plex-sans-latin-ext-500-normal-DakdToA3.woff2 +0 -0
  79. package/dist/admin-bundle/assets/ibm-plex-sans-latin-ext-600-normal-DIrixKbi.woff +0 -0
  80. package/dist/admin-bundle/assets/ibm-plex-sans-latin-ext-600-normal-DOrvGEcy.woff2 +0 -0
  81. package/dist/admin-bundle/assets/ibm-plex-sans-vietnamese-400-normal-DG4YqDda.woff2 +0 -0
  82. package/dist/admin-bundle/assets/ibm-plex-sans-vietnamese-400-normal-fK1oJ5dG.woff +0 -0
  83. package/dist/admin-bundle/assets/ibm-plex-sans-vietnamese-500-normal-BEb3_waV.woff +0 -0
  84. package/dist/admin-bundle/assets/ibm-plex-sans-vietnamese-500-normal-e4dixQRQ.woff2 +0 -0
  85. package/dist/admin-bundle/assets/ibm-plex-sans-vietnamese-600-normal-DgdngZtN.woff +0 -0
  86. package/dist/admin-bundle/assets/ibm-plex-sans-vietnamese-600-normal-DpPYBSTl.woff2 +0 -0
  87. package/dist/admin-bundle/assets/index-BIAF0ShP.js +542 -0
  88. package/dist/admin-bundle/assets/index-DhMY-0sC.js +148 -0
  89. package/dist/admin-bundle/assets/index-DnZV_gsg.css +1 -0
  90. package/dist/admin-bundle/assets/index-Do71v6NZ.js +7 -0
  91. package/dist/admin-bundle/assets/literata-cyrillic-ext-opsz-italic-5yUt4G_9.woff2 +0 -0
  92. package/dist/admin-bundle/assets/literata-cyrillic-ext-opsz-normal-C5tfwALZ.woff2 +0 -0
  93. package/dist/admin-bundle/assets/literata-cyrillic-opsz-italic-Bj0ndbyp.woff2 +0 -0
  94. package/dist/admin-bundle/assets/literata-cyrillic-opsz-normal-DgmypKXX.woff2 +0 -0
  95. package/dist/admin-bundle/assets/literata-greek-ext-opsz-italic-DFpO5j-Z.woff2 +0 -0
  96. package/dist/admin-bundle/assets/literata-greek-ext-opsz-normal-DGm64vGR.woff2 +0 -0
  97. package/dist/admin-bundle/assets/literata-greek-opsz-italic-CHERNRFq.woff2 +0 -0
  98. package/dist/admin-bundle/assets/literata-greek-opsz-normal-DFglUmAd.woff2 +0 -0
  99. package/dist/admin-bundle/assets/literata-latin-ext-opsz-italic-4y8iAqqs.woff2 +0 -0
  100. package/dist/admin-bundle/assets/literata-latin-ext-opsz-normal-STiTPs0F.woff2 +0 -0
  101. package/dist/admin-bundle/assets/literata-latin-opsz-italic-CJ93D38p.woff2 +0 -0
  102. package/dist/admin-bundle/assets/literata-latin-opsz-normal-BHZsWIlc.woff2 +0 -0
  103. package/dist/admin-bundle/assets/literata-vietnamese-opsz-italic-BdcrZMcO.woff2 +0 -0
  104. package/dist/admin-bundle/assets/literata-vietnamese-opsz-normal-Gqw5JQlq.woff2 +0 -0
  105. package/dist/admin-bundle/assets/mf-entry-bootstrap-0-aef015cd.js +41 -0
  106. package/dist/admin-bundle/assets/remoteEntry-CNyN68bc.js +14 -0
  107. package/dist/admin-bundle/assets/virtualExposes-BDCSo5OS.js +1 -0
  108. package/dist/admin-bundle/assets/vite-preload-helper-Cgledu0r.js +1 -0
  109. package/dist/admin-bundle/index.html +16 -0
  110. package/dist/app.d.ts +8 -0
  111. package/dist/app.js +252 -0
  112. package/dist/auth/api-content-author.d.ts +2 -0
  113. package/dist/auth/api-content-author.js +27 -0
  114. package/dist/auth/api-keys.d.ts +7 -0
  115. package/dist/auth/api-keys.js +85 -0
  116. package/dist/auth/jwt-payload.d.ts +16 -0
  117. package/dist/auth/jwt-payload.js +1 -0
  118. package/dist/auth/preview-tokens.d.ts +7 -0
  119. package/dist/auth/preview-tokens.js +76 -0
  120. package/dist/auth/rate-limit.d.ts +16 -0
  121. package/dist/auth/rate-limit.js +283 -0
  122. package/dist/auth/require-auth.d.ts +4 -0
  123. package/dist/auth/require-auth.js +28 -0
  124. package/dist/auth/route-rate-limits.d.ts +31 -0
  125. package/dist/auth/route-rate-limits.js +155 -0
  126. package/dist/auth/tokens.d.ts +15 -0
  127. package/dist/auth/tokens.js +38 -0
  128. package/dist/bin.d.ts +2 -0
  129. package/dist/bin.js +6 -0
  130. package/dist/boot/core-migration-gate.d.ts +12 -0
  131. package/dist/boot/core-migration-gate.js +52 -0
  132. package/dist/boot/resolve-boot-mode.d.ts +6 -0
  133. package/dist/boot/resolve-boot-mode.js +206 -0
  134. package/dist/bundled-templates/com.velora.blog/manifest.json +39 -0
  135. package/dist/bundled-templates/com.velora.blog/package.tar.gz +0 -0
  136. package/dist/bundled-templates/com.velora.blog/sample-content.json +14 -0
  137. package/dist/config/admin-ui.d.ts +1 -0
  138. package/dist/config/admin-ui.js +10 -0
  139. package/dist/config/cors.d.ts +7 -0
  140. package/dist/config/cors.js +53 -0
  141. package/dist/config/env-file-path.d.ts +2 -0
  142. package/dist/config/env-file-path.js +22 -0
  143. package/dist/config/graphql-limits.d.ts +2 -0
  144. package/dist/config/graphql-limits.js +26 -0
  145. package/dist/config/headless.d.ts +1 -0
  146. package/dist/config/headless.js +8 -0
  147. package/dist/config/license-revalidation.d.ts +2 -0
  148. package/dist/config/license-revalidation.js +16 -0
  149. package/dist/config/load-env.d.ts +1 -0
  150. package/dist/config/load-env.js +53 -0
  151. package/dist/config/marketplace.d.ts +11 -0
  152. package/dist/config/marketplace.js +19 -0
  153. package/dist/config/preview.d.ts +3 -0
  154. package/dist/config/preview.js +39 -0
  155. package/dist/config/public-docs.d.ts +1 -0
  156. package/dist/config/public-docs.js +9 -0
  157. package/dist/config/site.d.ts +7 -0
  158. package/dist/config/site.js +12 -0
  159. package/dist/config/trust-proxy.d.ts +2 -0
  160. package/dist/config/trust-proxy.js +42 -0
  161. package/dist/data-types/validate-data-type-settings.d.ts +1 -0
  162. package/dist/data-types/validate-data-type-settings.js +33 -0
  163. package/dist/db/content-db.d.ts +16 -0
  164. package/dist/db/content-db.js +109 -0
  165. package/dist/db/core-migrations/index.d.ts +14 -0
  166. package/dist/db/core-migrations/index.js +184 -0
  167. package/dist/db/core-migrations/steps.d.ts +4 -0
  168. package/dist/db/core-migrations/steps.js +66 -0
  169. package/dist/db/load-prisma-client.d.ts +2 -0
  170. package/dist/db/load-prisma-client.js +44 -0
  171. package/dist/db/prisma.d.ts +3 -0
  172. package/dist/db/prisma.js +67 -0
  173. package/dist/db/resolve-client-dir.d.ts +2 -0
  174. package/dist/db/resolve-client-dir.js +83 -0
  175. package/dist/docs/filter-public-api-spec.d.ts +2 -0
  176. package/dist/docs/filter-public-api-spec.js +52 -0
  177. package/dist/docs-bundle/404.html +41 -0
  178. package/dist/docs-bundle/_astro/MobileTableOfContents.astro_astro_type_script_index_0_lang.BcSo_yiZ.js +1 -0
  179. package/dist/docs-bundle/_astro/Search.astro_astro_type_script_index_0_lang.CavldbAs.js +1 -0
  180. package/dist/docs-bundle/_astro/TableOfContents.astro_astro_type_script_index_0_lang.Csloo1VZ.js +1 -0
  181. package/dist/docs-bundle/_astro/common.DTXA7sXM.css +3 -0
  182. package/dist/docs-bundle/_astro/ec.0vx5m.js +3 -0
  183. package/dist/docs-bundle/_astro/ec.w36nc.css +1 -0
  184. package/dist/docs-bundle/_astro/page.Dwipeu-R.js +1 -0
  185. package/dist/docs-bundle/_astro/print.ehPL0gv-.css +1 -0
  186. package/dist/docs-bundle/_astro/starlight-toc.CTCQXEge.js +1 -0
  187. package/dist/docs-bundle/_astro/ui-core.D-7Scnhs.js +2 -0
  188. package/dist/docs-bundle/favicon.svg +1 -0
  189. package/dist/docs-bundle/index.html +1 -0
  190. package/dist/docs-bundle/pagefind/fragment/en_18a36d7.pf_fragment +0 -0
  191. package/dist/docs-bundle/pagefind/fragment/en_1d9eb24.pf_fragment +0 -0
  192. package/dist/docs-bundle/pagefind/fragment/en_1ef320c.pf_fragment +0 -0
  193. package/dist/docs-bundle/pagefind/fragment/en_3099406.pf_fragment +0 -0
  194. package/dist/docs-bundle/pagefind/fragment/en_4a5b6fe.pf_fragment +0 -0
  195. package/dist/docs-bundle/pagefind/fragment/en_9aa652e.pf_fragment +0 -0
  196. package/dist/docs-bundle/pagefind/fragment/en_baccdf6.pf_fragment +0 -0
  197. package/dist/docs-bundle/pagefind/fragment/en_d81f3fe.pf_fragment +0 -0
  198. package/dist/docs-bundle/pagefind/fragment/en_d855550.pf_fragment +0 -0
  199. package/dist/docs-bundle/pagefind/fragment/en_e6d88d8.pf_fragment +0 -0
  200. package/dist/docs-bundle/pagefind/fragment/en_e9d3189.pf_fragment +0 -0
  201. package/dist/docs-bundle/pagefind/index/en_5feeed7.pf_index +0 -0
  202. package/dist/docs-bundle/pagefind/index/en_c6981f9.pf_index +0 -0
  203. package/dist/docs-bundle/pagefind/index/en_ce4f6bf.pf_index +0 -0
  204. package/dist/docs-bundle/pagefind/pagefind-component-ui.css +1509 -0
  205. package/dist/docs-bundle/pagefind/pagefind-component-ui.js +56 -0
  206. package/dist/docs-bundle/pagefind/pagefind-entry.json +1 -0
  207. package/dist/docs-bundle/pagefind/pagefind-highlight.js +1070 -0
  208. package/dist/docs-bundle/pagefind/pagefind-modular-ui.css +214 -0
  209. package/dist/docs-bundle/pagefind/pagefind-modular-ui.js +8 -0
  210. package/dist/docs-bundle/pagefind/pagefind-ui.css +1 -0
  211. package/dist/docs-bundle/pagefind/pagefind-ui.js +2 -0
  212. package/dist/docs-bundle/pagefind/pagefind-worker.js +6 -0
  213. package/dist/docs-bundle/pagefind/pagefind.en_1e94abd852.pf_meta +0 -0
  214. package/dist/docs-bundle/pagefind/pagefind.js +6 -0
  215. package/dist/docs-bundle/pagefind/wasm.en.pagefind +0 -0
  216. package/dist/docs-bundle/pagefind/wasm.unknown.pagefind +0 -0
  217. package/dist/docs-bundle/v1/index.html +86 -0
  218. package/dist/docs-bundle/v1/using-velora/build-a-headless-frontend/index.html +413 -0
  219. package/dist/docs-bundle/v1/using-velora/content-model/index.html +858 -0
  220. package/dist/docs-bundle/v1/using-velora/editing/index.html +748 -0
  221. package/dist/docs-bundle/v1/using-velora/getting-started/index.html +588 -0
  222. package/dist/docs-bundle/v1/using-velora/headless-api/index.html +1620 -0
  223. package/dist/docs-bundle/v1/using-velora/index.html +215 -0
  224. package/dist/docs-bundle/v1/using-velora/installation/index.html +886 -0
  225. package/dist/docs-bundle/v1/using-velora/installing-plugins/index.html +836 -0
  226. package/dist/docs-bundle/v1/using-velora/media/index.html +468 -0
  227. package/dist/docs-bundle/v1/using-velora/users-and-roles/index.html +561 -0
  228. package/dist/graphql/field-count-rule.d.ts +5 -0
  229. package/dist/graphql/field-count-rule.js +59 -0
  230. package/dist/graphql/schema.d.ts +12 -0
  231. package/dist/graphql/schema.js +330 -0
  232. package/dist/index.d.ts +1 -0
  233. package/dist/index.js +180 -0
  234. package/dist/lib.d.ts +2 -0
  235. package/dist/lib.js +39 -0
  236. package/dist/marketplace/install-bundle-members.d.ts +33 -0
  237. package/dist/marketplace/install-bundle-members.js +137 -0
  238. package/dist/marketplace/install-from-marketplace.d.ts +60 -0
  239. package/dist/marketplace/install-from-marketplace.js +581 -0
  240. package/dist/marketplace/license-revalidation-job.d.ts +38 -0
  241. package/dist/marketplace/license-revalidation-job.js +139 -0
  242. package/dist/marketplace/marketplace-client.d.ts +43 -0
  243. package/dist/marketplace/marketplace-client.js +228 -0
  244. package/dist/marketplace/revalidate-license.d.ts +39 -0
  245. package/dist/marketplace/revalidate-license.js +103 -0
  246. package/dist/media/media-service.d.ts +36 -0
  247. package/dist/media/media-service.js +162 -0
  248. package/dist/plugins/boot-plugin-loader.d.ts +32 -0
  249. package/dist/plugins/boot-plugin-loader.js +57 -0
  250. package/dist/plugins/hook-dispatcher.d.ts +13 -0
  251. package/dist/plugins/hook-dispatcher.js +68 -0
  252. package/dist/plugins/install-built-package.d.ts +36 -0
  253. package/dist/plugins/install-built-package.js +199 -0
  254. package/dist/plugins/install-package-tarball.d.ts +25 -0
  255. package/dist/plugins/install-package-tarball.js +73 -0
  256. package/dist/plugins/plugin-context.d.ts +5 -0
  257. package/dist/plugins/plugin-context.js +26 -0
  258. package/dist/plugins/plugin-package-store.d.ts +31 -0
  259. package/dist/plugins/plugin-package-store.js +64 -0
  260. package/dist/plugins/plugin-registry-service.d.ts +227 -0
  261. package/dist/plugins/plugin-registry-service.js +636 -0
  262. package/dist/plugins/seed-template-content.d.ts +23 -0
  263. package/dist/plugins/seed-template-content.js +198 -0
  264. package/dist/plugins/server-serializers.d.ts +3 -0
  265. package/dist/plugins/server-serializers.js +16 -0
  266. package/dist/plugins/simple-storage-api.d.ts +9 -0
  267. package/dist/plugins/simple-storage-api.js +26 -0
  268. package/dist/plugins/snapshot-groups.d.ts +16 -0
  269. package/dist/plugins/snapshot-groups.js +81 -0
  270. package/dist/plugins/structured-query-builder.d.ts +21 -0
  271. package/dist/plugins/structured-query-builder.js +60 -0
  272. package/dist/plugins/structured-snapshot-service.d.ts +16 -0
  273. package/dist/plugins/structured-snapshot-service.js +286 -0
  274. package/dist/plugins/structured-storage-api.d.ts +22 -0
  275. package/dist/plugins/structured-storage-api.js +91 -0
  276. package/dist/plugins/structured-storage-transaction.d.ts +22 -0
  277. package/dist/plugins/structured-storage-transaction.js +63 -0
  278. package/dist/plugins/structured-table-naming.d.ts +1 -0
  279. package/dist/plugins/structured-table-naming.js +18 -0
  280. package/dist/plugins/trusted-keys.d.ts +11 -0
  281. package/dist/plugins/trusted-keys.js +67 -0
  282. package/dist/plugins/trusted-signing-keys.d.ts +27 -0
  283. package/dist/plugins/trusted-signing-keys.js +40 -0
  284. package/dist/plugins/uninstall-bundle.d.ts +29 -0
  285. package/dist/plugins/uninstall-bundle.js +150 -0
  286. package/dist/plugins/verify-package.d.ts +36 -0
  287. package/dist/plugins/verify-package.js +121 -0
  288. package/dist/routes/admin-static.d.ts +8 -0
  289. package/dist/routes/admin-static.js +196 -0
  290. package/dist/routes/api-keys.d.ts +2 -0
  291. package/dist/routes/api-keys.js +95 -0
  292. package/dist/routes/api-playground.d.ts +2 -0
  293. package/dist/routes/api-playground.js +21 -0
  294. package/dist/routes/auth.d.ts +2 -0
  295. package/dist/routes/auth.js +102 -0
  296. package/dist/routes/content.d.ts +3 -0
  297. package/dist/routes/content.js +471 -0
  298. package/dist/routes/data-types.d.ts +3 -0
  299. package/dist/routes/data-types.js +100 -0
  300. package/dist/routes/docs-static.d.ts +8 -0
  301. package/dist/routes/docs-static.js +137 -0
  302. package/dist/routes/document-types.d.ts +3 -0
  303. package/dist/routes/document-types.js +149 -0
  304. package/dist/routes/headless-bridge.d.ts +10 -0
  305. package/dist/routes/headless-bridge.js +207 -0
  306. package/dist/routes/health.d.ts +2 -0
  307. package/dist/routes/health.js +15 -0
  308. package/dist/routes/marketplace-proxy.d.ts +8 -0
  309. package/dist/routes/marketplace-proxy.js +135 -0
  310. package/dist/routes/media.d.ts +6 -0
  311. package/dist/routes/media.js +93 -0
  312. package/dist/routes/plugin-api-routes.d.ts +12 -0
  313. package/dist/routes/plugin-api-routes.js +224 -0
  314. package/dist/routes/plugin-assets.d.ts +8 -0
  315. package/dist/routes/plugin-assets.js +51 -0
  316. package/dist/routes/plugin-management.d.ts +7 -0
  317. package/dist/routes/plugin-management.js +525 -0
  318. package/dist/routes/plugin-storage.d.ts +8 -0
  319. package/dist/routes/plugin-storage.js +104 -0
  320. package/dist/routes/plugins.d.ts +2 -0
  321. package/dist/routes/plugins.js +36 -0
  322. package/dist/routes/public-api.d.ts +9 -0
  323. package/dist/routes/public-api.js +545 -0
  324. package/dist/routes/published-item.d.ts +57 -0
  325. package/dist/routes/published-item.js +236 -0
  326. package/dist/routes/setup.d.ts +9 -0
  327. package/dist/routes/setup.js +477 -0
  328. package/dist/routes/snapshots.d.ts +3 -0
  329. package/dist/routes/snapshots.js +65 -0
  330. package/dist/routes/templates.d.ts +3 -0
  331. package/dist/routes/templates.js +37 -0
  332. package/dist/routes/themes.d.ts +2 -0
  333. package/dist/routes/themes.js +30 -0
  334. package/dist/routes/users.d.ts +2 -0
  335. package/dist/routes/users.js +113 -0
  336. package/dist/sandbox/register-local-plugin.d.ts +36 -0
  337. package/dist/sandbox/register-local-plugin.js +108 -0
  338. package/dist/sandbox/seed-sandbox.d.ts +20 -0
  339. package/dist/sandbox/seed-sandbox.js +122 -0
  340. package/dist/scripts/copy-admin-bundle.d.ts +1 -0
  341. package/dist/scripts/copy-admin-bundle.js +24 -0
  342. package/dist/scripts/copy-docs-bundle.d.ts +1 -0
  343. package/dist/scripts/copy-docs-bundle.js +22 -0
  344. package/dist/scripts/create-api-key.d.ts +5 -0
  345. package/dist/scripts/create-api-key.js +56 -0
  346. package/dist/scripts/generate-prisma-clients.d.ts +6 -0
  347. package/dist/scripts/generate-prisma-clients.js +125 -0
  348. package/dist/scripts/pack-bundled-templates.d.ts +1 -0
  349. package/dist/scripts/pack-bundled-templates.js +87 -0
  350. package/dist/setup/build-connection-string.d.ts +19 -0
  351. package/dist/setup/build-connection-string.js +14 -0
  352. package/dist/setup/bundled-templates.d.ts +19 -0
  353. package/dist/setup/bundled-templates.js +121 -0
  354. package/dist/setup/ensure-prisma-client.d.ts +3 -0
  355. package/dist/setup/ensure-prisma-client.js +23 -0
  356. package/dist/setup/install-starter.d.ts +14 -0
  357. package/dist/setup/install-starter.js +76 -0
  358. package/dist/setup/normalize-database-url.d.ts +2 -0
  359. package/dist/setup/normalize-database-url.js +35 -0
  360. package/dist/setup/persist-env-config.d.ts +2 -0
  361. package/dist/setup/persist-env-config.js +63 -0
  362. package/dist/setup/provision-database.d.ts +2 -0
  363. package/dist/setup/provision-database.js +89 -0
  364. package/dist/setup-app.d.ts +4 -0
  365. package/dist/setup-app.js +43 -0
  366. package/package.json +96 -0
  367. package/prisma/schema.prisma +303 -0
@@ -0,0 +1,42 @@
1
+ // VELORA_TRUST_PROXY (S160 final-fix round, finding 1) — threads into
2
+ // Fastify's own `trustProxy` constructor option, which governs how
3
+ // `request.ip` (and X-Forwarded-For) are resolved. Without it, Fastify
4
+ // trusts nothing and `request.ip` is always the socket's remote address —
5
+ // which is the load balancer / reverse proxy's own address whenever one
6
+ // sits in front of the process, collapsing every real visitor onto one
7
+ // value. Three S160 controls hang directly on request.ip: the platform's
8
+ // anonymous-IP rate lane (rate-limit.ts's `ip:` bucket), the forms plugin's
9
+ // per-IP token bucket (rate-bucket.ts / forms-api.ts), and the ip_hash
10
+ // column stored on every submission — all three are only genuinely
11
+ // per-visitor once the operator both runs behind a real, trusted proxy AND
12
+ // tells Fastify so here. See the .env.example block for the danger in the
13
+ // OTHER direction (setting this when NOT actually behind a trusted proxy).
14
+ //
15
+ // Default MUST remain today's behaviour: unset/empty means `undefined`, and
16
+ // app.ts omits the `trustProxy` constructor option entirely rather than
17
+ // passing it explicitly — nothing changes for an existing deployment that
18
+ // never set this var.
19
+ //
20
+ // Accepted forms, mirroring what Fastify's own trustProxy already knows how
21
+ // to interpret once it receives a boolean/number/string:
22
+ // - unset / empty (after trim) -> undefined
23
+ // - "true" / "false" (case-insensitive) -> boolean
24
+ // - a bare non-negative integer (e.g. "1") -> number, a hop count
25
+ // - anything else -> the trimmed string, passed straight through
26
+ // (Fastify itself parses "loopback" and a comma-separated IP/CIDR list)
27
+ export function parseTrustProxy(raw) {
28
+ const value = raw?.trim();
29
+ if (!value)
30
+ return undefined;
31
+ const lower = value.toLowerCase();
32
+ if (lower === "true")
33
+ return true;
34
+ if (lower === "false")
35
+ return false;
36
+ if (/^\d+$/.test(value))
37
+ return Number(value);
38
+ return value;
39
+ }
40
+ export function trustProxyFromEnv(env = process.env) {
41
+ return parseTrustProxy(env.VELORA_TRUST_PROXY);
42
+ }
@@ -0,0 +1 @@
1
+ export declare function validateDataTypeSettings(editorId: string, settings: Record<string, unknown>): string[];
@@ -0,0 +1,33 @@
1
+ import { Ajv } from "ajv";
2
+ import { BUILT_IN_SETTINGS_SCHEMAS } from "@velora-cms/plugin-sdk/datatypes";
3
+ // Server-side half of the settingsSchema pipeline (Session 69). Only
4
+ // covers BUILT-IN editors — Module Federation remotes (third-party/
5
+ // marketplace plugins) only ever load in the browser (Session 66), so the
6
+ // server has no way to see a remote plugin's settingsSchema. For any
7
+ // editorId not in BUILT_IN_SETTINGS_SCHEMAS, validation is skipped (not
8
+ // rejected) — a deliberate, documented boundary, not a gap.
9
+ const ajv = new Ajv({ allErrors: true });
10
+ const compiledValidators = new Map();
11
+ function getValidator(editorId) {
12
+ if (compiledValidators.has(editorId)) {
13
+ return compiledValidators.get(editorId);
14
+ }
15
+ const schema = BUILT_IN_SETTINGS_SCHEMAS[editorId];
16
+ if (!schema)
17
+ return undefined;
18
+ const validator = ajv.compile(schema);
19
+ compiledValidators.set(editorId, validator);
20
+ return validator;
21
+ }
22
+ // Returns a list of human-readable error messages — empty means valid
23
+ // (including "editorId has no known schema", which is intentionally not
24
+ // an error).
25
+ export function validateDataTypeSettings(editorId, settings) {
26
+ const validator = getValidator(editorId);
27
+ if (!validator)
28
+ return [];
29
+ const valid = validator(settings);
30
+ if (valid)
31
+ return [];
32
+ return (validator.errors ?? []).map((error) => `${error.instancePath || "settings"} ${error.message}`.trim());
33
+ }
@@ -0,0 +1,16 @@
1
+ import { ContentService } from "@velora-cms/content-service";
2
+ import { type ConnectionConfig, type DatabaseAdapter, type Migration } from "@velora-cms/db-adapter";
3
+ export interface ResolvedContentDatabase {
4
+ dialect: "postgresql" | "mysql" | "sqlite";
5
+ connection: ConnectionConfig;
6
+ migrations: Migration[];
7
+ }
8
+ export declare function dialectFromUrlScheme(url: string): ResolvedContentDatabase["dialect"] | undefined;
9
+ export declare function resolveContentDatabase(url: string): ResolvedContentDatabase;
10
+ export interface ContentDb {
11
+ adapter: DatabaseAdapter;
12
+ contentService: ContentService;
13
+ dialect: ResolvedContentDatabase["dialect"];
14
+ }
15
+ export declare function connectContentDb(): Promise<ContentDb>;
16
+ export declare function connectContentDbAt(url: string): Promise<ContentDb>;
@@ -0,0 +1,109 @@
1
+ import { ContentService } from "@velora-cms/content-service";
2
+ import { applyMigrations, MySQLAdapter, PostgreSQLAdapter, SQLiteAdapter, mysqlContentCurrentVersionMigration, mysqlContentFieldValuesMigration, mysqlContentSchemaMigration, mysqlContentTrashMigration, mysqlContentVersionsMigration, mysqlDataTypesMigration, mysqlDocumentTypeTabsAndTemplatesMigration, mysqlDropVersionPublishedAtMigration, mysqlSearchTrigramIndexesMigration, mysqlSnapshotsMigration, postgresqlContentCurrentVersionMigration, postgresqlContentFieldValuesMigration, postgresqlContentSchemaMigration, postgresqlContentTrashMigration, postgresqlContentVersionsMigration, postgresqlDataTypesMigration, postgresqlDocumentTypeTabsAndTemplatesMigration, postgresqlDropVersionPublishedAtMigration, postgresqlSearchTrigramIndexesMigration, postgresqlSnapshotsMigration, sqliteContentCurrentVersionMigration, sqliteContentFieldValuesMigration, sqliteContentSchemaMigration, sqliteContentTrashMigration, sqliteContentVersionsMigration, sqliteDataTypesMigration, sqliteDocumentTypeTabsAndTemplatesMigration, sqliteDropVersionPublishedAtMigration, sqliteSearchTrigramIndexesMigration, sqliteSnapshotsMigration, } from "@velora-cms/db-adapter";
3
+ // Dialect is derived from the connection string's scheme (Session 78) —
4
+ // the first real consumer of multi-dialect support outside the
5
+ // conformance suite, and a down-payment on the v1.x setup wizard.
6
+ // Order matters in every list: 0001 → 0010.
7
+ const MIGRATIONS = {
8
+ postgresql: [
9
+ postgresqlContentSchemaMigration,
10
+ postgresqlContentVersionsMigration,
11
+ postgresqlContentCurrentVersionMigration,
12
+ postgresqlSnapshotsMigration,
13
+ postgresqlDocumentTypeTabsAndTemplatesMigration,
14
+ postgresqlDataTypesMigration,
15
+ postgresqlContentFieldValuesMigration,
16
+ postgresqlSearchTrigramIndexesMigration,
17
+ postgresqlContentTrashMigration,
18
+ postgresqlDropVersionPublishedAtMigration,
19
+ ],
20
+ mysql: [
21
+ mysqlContentSchemaMigration,
22
+ mysqlContentVersionsMigration,
23
+ mysqlContentCurrentVersionMigration,
24
+ mysqlSnapshotsMigration,
25
+ mysqlDocumentTypeTabsAndTemplatesMigration,
26
+ mysqlDataTypesMigration,
27
+ mysqlContentFieldValuesMigration,
28
+ mysqlSearchTrigramIndexesMigration,
29
+ mysqlContentTrashMigration,
30
+ mysqlDropVersionPublishedAtMigration,
31
+ ],
32
+ sqlite: [
33
+ sqliteContentSchemaMigration,
34
+ sqliteContentVersionsMigration,
35
+ sqliteContentCurrentVersionMigration,
36
+ sqliteSnapshotsMigration,
37
+ sqliteDocumentTypeTabsAndTemplatesMigration,
38
+ sqliteDataTypesMigration,
39
+ sqliteContentFieldValuesMigration,
40
+ sqliteSearchTrigramIndexesMigration,
41
+ sqliteContentTrashMigration,
42
+ sqliteDropVersionPublishedAtMigration,
43
+ ],
44
+ };
45
+ // Scheme → dialect, shared with prisma.ts's resolvePrismaDialect (Session
46
+ // 131 fix). Both need the same URL-scheme rules; they diverge on what
47
+ // happens when nothing matches. There's no such thing as an unconnectable
48
+ // content database, so resolveContentDatabase below throws. Prisma dialect
49
+ // resolution is diagnostic only (it shapes a query, it doesn't open a
50
+ // connection) and must never crash boot over it, so it falls back to a
51
+ // default with a warning instead of throwing — see prisma.ts.
52
+ export function dialectFromUrlScheme(url) {
53
+ if (url.startsWith("postgres://") || url.startsWith("postgresql://"))
54
+ return "postgresql";
55
+ if (url.startsWith("mysql://"))
56
+ return "mysql";
57
+ if (url.startsWith("file:"))
58
+ return "sqlite";
59
+ return undefined;
60
+ }
61
+ export function resolveContentDatabase(url) {
62
+ const dialect = dialectFromUrlScheme(url);
63
+ switch (dialect) {
64
+ case "postgresql":
65
+ return { dialect, connection: { connectionString: url }, migrations: MIGRATIONS.postgresql };
66
+ case "mysql":
67
+ return { dialect, connection: { connectionString: url }, migrations: MIGRATIONS.mysql };
68
+ case "sqlite":
69
+ return { dialect, connection: { filename: url.slice("file:".length) }, migrations: MIGRATIONS.sqlite };
70
+ default:
71
+ throw new Error(`Unsupported content database URL "${url}" — use postgres://…, mysql://…, or file:<path> (sqlite).`);
72
+ }
73
+ }
74
+ function createAdapter(dialect) {
75
+ switch (dialect) {
76
+ case "postgresql":
77
+ return new PostgreSQLAdapter();
78
+ case "mysql":
79
+ return new MySQLAdapter();
80
+ case "sqlite":
81
+ return new SQLiteAdapter();
82
+ }
83
+ }
84
+ // Connects the adapter and brings the content tables up to date. Content
85
+ // tables are adapter-managed and tracked in velora_migrations; Prisma's
86
+ // tables stay in _prisma_migrations — the two never overlap (Two-Tier
87
+ // ORM Strategy). VELORA_CONTENT_DATABASE_URL exists because the sandbox
88
+ // splits the tiers (Prisma on SQLite, content on the selected dialect);
89
+ // normal dev sets only DATABASE_URL and behaves exactly as before.
90
+ export async function connectContentDb() {
91
+ const url = process.env.VELORA_CONTENT_DATABASE_URL ?? process.env.DATABASE_URL;
92
+ if (!url) {
93
+ throw new Error("VELORA_CONTENT_DATABASE_URL or DATABASE_URL must be set — see .env.example");
94
+ }
95
+ return connectContentDbAt(url);
96
+ }
97
+ // The explicit-URL variant (Session 151): the setup wizard's starter
98
+ // install needs a content-db connection for a database whose URL was
99
+ // chosen IN the very request being handled — it isn't in process.env yet,
100
+ // exactly the same reason loadPrismaClient grew its explicit datasourceUrl
101
+ // parameter. connectContentDb() above delegates here, so both paths run
102
+ // the identical resolve → connect → migrate sequence.
103
+ export async function connectContentDbAt(url) {
104
+ const resolved = resolveContentDatabase(url);
105
+ const adapter = createAdapter(resolved.dialect);
106
+ await adapter.connect(resolved.connection);
107
+ await applyMigrations(adapter, resolved.migrations);
108
+ return { adapter, contentService: new ContentService(adapter), dialect: resolved.dialect };
109
+ }
@@ -0,0 +1,14 @@
1
+ import { type Migration } from "@velora-cms/db-adapter";
2
+ import { type CoreMigrationDialect } from "./steps.js";
3
+ export type CoreMigrationOutcome = "recorded-all" | "baselined" | "applied" | "skipped-empty";
4
+ type CoreDialect = CoreMigrationDialect;
5
+ export declare function applyCoreMigrations(opts: {
6
+ dialect: CoreDialect;
7
+ databaseUrl: string;
8
+ mode: "fresh-push" | "boot";
9
+ stepsOverride?: Migration[];
10
+ }): Promise<{
11
+ outcome: CoreMigrationOutcome;
12
+ executedIds: string[];
13
+ }>;
14
+ export {};
@@ -0,0 +1,184 @@
1
+ import { applyMigrations, MySQLAdapter, PostgreSQLAdapter, SQLiteAdapter, } from "@velora-cms/db-adapter";
2
+ import { resolveContentDatabase } from "../content-db.js";
3
+ import { buildCoreMigrations } from "./steps.js";
4
+ // Separate from velora_migrations (the content-adapter ledger, tracked by
5
+ // content-db.ts's applyMigrations call): this ledger tracks the
6
+ // Prisma-owned schema's upgrade history, which content-db.ts never
7
+ // touches — Two-Tier ORM Strategy, two ledgers, never shared rows.
8
+ const LEDGER = "velora_core_migrations";
9
+ function createAdapterForDialect(dialect) {
10
+ switch (dialect) {
11
+ case "postgresql":
12
+ return new PostgreSQLAdapter();
13
+ case "mysql":
14
+ return new MySQLAdapter();
15
+ case "sqlite":
16
+ return new SQLiteAdapter();
17
+ }
18
+ }
19
+ // Boot-time ledger for the Prisma-owned schema (S185). Three starting
20
+ // shapes it must tell apart:
21
+ // - "fresh-push": setup just ran `prisma db push` and created the
22
+ // CURRENT schema from scratch — every step is already reflected, so
23
+ // record every id without running any SQL.
24
+ // - "boot" against a database with a complete ledger: normal restart,
25
+ // apply anything newer than what's recorded.
26
+ // - "boot" against a pre-ledger database (the 0.10-era self-hosted /
27
+ // demo-box case, `users` table present but no velora_core_migrations
28
+ // table yet): baseline first (record 0001 without executing — 0001
29
+ // marks "the 0.10.0-release db-push shape"; every schema change that
30
+ // shipped after that release, such as S182's api_keys.scope, is its
31
+ // own numbered step and is NEVER folded into the baseline) — then
32
+ // apply anything newer for real, which is exactly how a pre-S182
33
+ // database picks up 0002's ALTER TABLE.
34
+ // - "boot" against a genuinely empty database (no `users` table): there
35
+ // is nothing to baseline or migrate — the setup wizard hasn't run
36
+ // yet. Skip entirely and create no ledger table, so a later
37
+ // fresh-push still sees an untouched database.
38
+ export async function applyCoreMigrations(opts) {
39
+ const steps = opts.stepsOverride ?? buildCoreMigrations(opts.dialect);
40
+ // Same resolve→connect sequence content-db.ts uses to build an adapter
41
+ // from a URL — the content-migrations list on the result is ignored
42
+ // here, this ledger tracks the Prisma-owned schema, not the
43
+ // content-adapter tables.
44
+ const resolved = resolveContentDatabase(opts.databaseUrl);
45
+ if (resolved.dialect !== opts.dialect) {
46
+ throw new Error(`applyCoreMigrations: dialect "${opts.dialect}" does not match the database URL (which is ${resolved.dialect})`);
47
+ }
48
+ const adapter = createAdapterForDialect(resolved.dialect);
49
+ await adapter.connect(resolved.connection);
50
+ try {
51
+ if (opts.mode === "fresh-push") {
52
+ await recordWithoutExecuting(adapter, steps);
53
+ return { outcome: "recorded-all", executedIds: [] };
54
+ }
55
+ // A ledger table that exists but holds ZERO rows is treated as no
56
+ // ledger at all: ensureLedgerTable's CREATE TABLE autocommits on every
57
+ // dialect, so a crash between table creation and the (transactional)
58
+ // recording commit leaves exactly this shape behind. Reading it as
59
+ // "already baselined" would make the applied branch run every up()
60
+ // against a schema db push created in full — the empty table must fall
61
+ // back to the baseline path, which is idempotent and safe to re-run.
62
+ const hasLedger = (await tableExists(adapter, LEDGER)) &&
63
+ (await adapter.query({ sql: `SELECT id FROM ${LEDGER}` })).length > 0;
64
+ if (!hasLedger) {
65
+ const hasUsers = await tableExists(adapter, "users");
66
+ if (!hasUsers)
67
+ return { outcome: "skipped-empty", executedIds: [] };
68
+ // 0.10-era db-push database: baseline, then apply anything newer.
69
+ await recordWithoutExecuting(adapter, steps.slice(0, 1));
70
+ const executed = await applyTracked(adapter, steps);
71
+ return { outcome: "baselined", executedIds: executed };
72
+ }
73
+ const executed = await applyTracked(adapter, steps);
74
+ return { outcome: "applied", executedIds: executed };
75
+ }
76
+ finally {
77
+ await adapter.disconnect();
78
+ }
79
+ }
80
+ // Same CREATE TABLE IF NOT EXISTS + mysql VARCHAR id-column rule as
81
+ // migration-runner.ts's velora_migrations bootstrap: MySQL's InnoDB can't
82
+ // index a bare TEXT/BLOB column without an explicit key length, and
83
+ // migration ids here are short slugs like "0001_core_baseline", never
84
+ // real UUIDs, so a short VARCHAR is the right fit.
85
+ //
86
+ // Width note (S185 fix-wave 2): both columns are VARCHAR(191) on mysql,
87
+ // not TEXT. schema.prisma's CoreMigration model (`id String @id` and
88
+ // `appliedAt String @map("applied_at")`, neither with a `@db.VarChar` —
89
+ // that annotation is provider-specific and would break the other two
90
+ // dialects' mapping) maps a plain `String` field to VARCHAR(191) on mysql
91
+ // by Prisma's own default. This hand-written DDL is set to match that
92
+ // default exactly, on both columns, so the two definitions of this table
93
+ // — this runner's CREATE TABLE and schema.prisma's model — always AGREE.
94
+ // Whether a given Prisma version would refuse a width mismatch outright or
95
+ // silently alter the column underneath a `db push` is version-dependent
96
+ // and not something this code relies on either way; matching the mapping
97
+ // removes the question entirely rather than betting on Prisma's behavior
98
+ // in either direction. Contrast migration-runner.ts's own VARCHAR(255) for
99
+ // velora_migrations: that ledger is adapter-owned, never declared in
100
+ // schema.prisma, and never seen by `db push` — it keeps 255 and is
101
+ // intentionally left untouched here.
102
+ async function ensureLedgerTable(adapter) {
103
+ const textColumn = adapter.dialect === "mysql" ? "VARCHAR(191)" : "TEXT";
104
+ await adapter.execute({
105
+ sql: `CREATE TABLE IF NOT EXISTS ${LEDGER} (id ${textColumn} PRIMARY KEY, applied_at ${textColumn} NOT NULL)`,
106
+ });
107
+ }
108
+ // Records ids as applied WITHOUT running their up() — used both for the
109
+ // fresh-push shortcut (every step already reflected by db push) and for
110
+ // baselining 0001 alone on a pre-ledger database.
111
+ //
112
+ // ensureLedgerTable stays OUTSIDE the transaction — mysql DDL autocommits,
113
+ // so a CREATE TABLE inside a transaction block would just be committed
114
+ // immediately anyway and can't be rolled back with the rest of the work.
115
+ // The SELECT + per-row INSERT loop that follows IS wrapped in a
116
+ // transaction: a crash partway through therefore leaves the ledger table
117
+ // PRESENT but EMPTY (the CREATE TABLE autocommitted; the row inserts
118
+ // rolled back). The boot path treats that empty table as "no ledger" and
119
+ // re-runs the baseline path, which is idempotent — see the hasLedger
120
+ // check in applyCoreMigrations. Without the wrapper, a crash mid-loop
121
+ // would instead leave a present-but-INCOMPLETE ledger, which no check can
122
+ // distinguish from a genuinely baselined database — next boot would then
123
+ // apply() steps whose columns/tables db push already created.
124
+ async function recordWithoutExecuting(adapter, steps) {
125
+ await ensureLedgerTable(adapter);
126
+ await adapter.transaction(async (tx) => {
127
+ const rows = await tx.query({ sql: `SELECT id FROM ${LEDGER}` });
128
+ const applied = new Set(rows.map((row) => row.id));
129
+ const placeholders = adapter.dialect === "postgresql" ? "($1, $2)" : "(?, ?)";
130
+ for (const step of steps) {
131
+ if (applied.has(step.id))
132
+ continue;
133
+ await tx.execute({
134
+ sql: `INSERT INTO ${LEDGER} (id, applied_at) VALUES ${placeholders}`,
135
+ params: [step.id, new Date().toISOString()],
136
+ });
137
+ }
138
+ });
139
+ }
140
+ // Runs applyMigrations against the core ledger and reports which ids were
141
+ // newly executed (diffing the ledger's rows before/after), so callers can
142
+ // distinguish "nothing to do" from "actually ran something."
143
+ //
144
+ // Load-bearing order: ensureLedgerTable runs BEFORE applyMigrations. Both
145
+ // issue a `CREATE TABLE IF NOT EXISTS ${LEDGER}`, but with different column
146
+ // widths (this module's VARCHAR(191) matching schema.prisma vs. the shared
147
+ // runner's own VARCHAR(255)/TEXT default for velora_migrations-style
148
+ // ledgers) — IF NOT EXISTS means only whichever CREATE TABLE runs first on
149
+ // a truly fresh database actually defines the table, so ensureLedgerTable
150
+ // must win that race, never applyMigrations' internal one.
151
+ async function applyTracked(adapter, steps) {
152
+ await ensureLedgerTable(adapter);
153
+ const before = new Set((await adapter.query({ sql: `SELECT id FROM ${LEDGER}` })).map((row) => row.id));
154
+ await applyMigrations(adapter, steps, { ledgerTable: LEDGER });
155
+ const after = await adapter.query({ sql: `SELECT id FROM ${LEDGER}` });
156
+ return after.map((row) => row.id).filter((id) => !before.has(id));
157
+ }
158
+ async function tableExists(adapter, table) {
159
+ switch (adapter.dialect) {
160
+ case "sqlite": {
161
+ const rows = await adapter.query({
162
+ sql: "SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?",
163
+ params: [table],
164
+ });
165
+ return rows.length > 0;
166
+ }
167
+ case "mysql": {
168
+ const rows = await adapter.query({
169
+ sql: "SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?",
170
+ params: [table],
171
+ });
172
+ return rows.length > 0;
173
+ }
174
+ case "postgresql": {
175
+ const rows = await adapter.query({
176
+ sql: "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name = $1",
177
+ params: [table],
178
+ });
179
+ return rows.length > 0;
180
+ }
181
+ default:
182
+ throw new Error(`applyCoreMigrations: unsupported dialect "${adapter.dialect}"`);
183
+ }
184
+ }
@@ -0,0 +1,4 @@
1
+ import type { Migration } from "@velora-cms/db-adapter";
2
+ export type CoreMigrationDialect = "postgresql" | "mysql" | "sqlite";
3
+ export declare function buildCoreMigrations(dialect: CoreMigrationDialect): Migration[];
4
+ export declare const CORE_MIGRATION_IDS: string[];
@@ -0,0 +1,66 @@
1
+ // The Prisma-owned schema's upgrade ledger. 0001 is a pure baseline: it
2
+ // marks "the 0.10.0-release db-push shape" and carries no SQL. Every schema
3
+ // change that ships AFTER that release becomes its own numbered step here —
4
+ // it must NEVER be folded back into the baseline, even if it lands before
5
+ // the next version tags. 0002 is the first such case: S182 added
6
+ // `api_keys.scope` after 0.10.0/0.10.1 had already shipped, so a pre-S182
7
+ // source-checkout site baselines at 0001 with no scope column and needs
8
+ // 0002 to repair it.
9
+ // Every future step must exist for postgresql, mysql AND sqlite and
10
+ // be additive-only — destructive statements are banned from this ledger.
11
+ // The pinning test asserts CORE_MIGRATION_IDS; update it with every new
12
+ // step (the ledger list and the test move together, always).
13
+ const coreBaseline = {
14
+ id: "0001_core_baseline",
15
+ name: "core baseline (0.10.0-release db-push shape)",
16
+ up: async () => { },
17
+ down: async () => { },
18
+ };
19
+ // api_keys.scope (S182): `TEXT NOT NULL DEFAULT 'read'` on postgresql/
20
+ // sqlite, `VARCHAR(191) NOT NULL DEFAULT 'read'` on mysql — matching
21
+ // schema.prisma's `scope String @default("read")`, which Prisma maps to
22
+ // VARCHAR(191) on mysql by its own default (no `@db.VarChar` override in
23
+ // either schema.prisma or .prisma-variant-mysql.schema.prisma).
24
+ //
25
+ // up() must be idempotent: a post-S182 database (fresh db-push, or the
26
+ // demo box after S182 shipped) already has the column, and this step must
27
+ // run harmlessly against it too. Rather than branch on "has 0001 already
28
+ // run without this column" (which the ledger can't tell apart from "db
29
+ // push already included it"), probe directly — try a SELECT of the column
30
+ // and only ALTER if that probe fails. The probe is dialect-free (the same
31
+ // SELECT works identically against all three), so only the ALTER itself
32
+ // needs the per-dialect branch below.
33
+ function apiKeyScopeStep(dialect) {
34
+ return {
35
+ id: "0002_api_key_scope",
36
+ name: "api_keys.scope column (S182)",
37
+ up: async (tx) => {
38
+ try {
39
+ await tx.query({ sql: "SELECT scope FROM api_keys LIMIT 1" });
40
+ return; // column already present — nothing to do
41
+ }
42
+ catch {
43
+ // column missing — pre-S182 database, fall through and add it
44
+ }
45
+ const alter = dialect === "postgresql"
46
+ ? "ALTER TABLE api_keys ADD COLUMN IF NOT EXISTS scope TEXT NOT NULL DEFAULT 'read'"
47
+ : dialect === "mysql"
48
+ ? "ALTER TABLE api_keys ADD COLUMN scope VARCHAR(191) NOT NULL DEFAULT 'read'"
49
+ : "ALTER TABLE api_keys ADD COLUMN scope TEXT NOT NULL DEFAULT 'read'";
50
+ await tx.execute({ sql: alter });
51
+ },
52
+ // No-op, same as the baseline: additive steps never need to undo
53
+ // anything (house pattern — this ledger only ever moves forward).
54
+ down: async () => { },
55
+ };
56
+ }
57
+ // A factory, not a plain array: 0002's up() needs to know which dialect
58
+ // it's running against (TransactionContext carries no dialect field, only
59
+ // DatabaseAdapter does), so the registry is built per-dialect at the call
60
+ // site instead of threading dialect through the shared Migration type.
61
+ // CORE_MIGRATION_IDS below stays dialect-independent — ids never vary by
62
+ // dialect — so it's fine to read off of any one dialect's build.
63
+ export function buildCoreMigrations(dialect) {
64
+ return [coreBaseline, apiKeyScopeStep(dialect)];
65
+ }
66
+ export const CORE_MIGRATION_IDS = buildCoreMigrations("sqlite").map((m) => m.id);
@@ -0,0 +1,2 @@
1
+ import type { PrismaClient } from "@prisma/client";
2
+ export declare function loadPrismaClient(clientDir: string | undefined, datasourceUrl?: string): Promise<PrismaClient>;
@@ -0,0 +1,44 @@
1
+ import { pathToFileURL } from "node:url";
2
+ import { join } from "node:path";
3
+ // Shared by db/prisma.ts's own env-var-driven boot (no datasourceUrl —
4
+ // Prisma reads DATABASE_URL from process.env the way its constructor
5
+ // always has) and Session 97's setup-complete handler (an explicit
6
+ // clientDir for a just-chosen dialect AND an explicit databaseUrl,
7
+ // since the value it needs isn't in process.env yet at that point).
8
+ export async function loadPrismaClient(clientDir, datasourceUrl) {
9
+ const options = datasourceUrl ? { datasources: { db: { url: datasourceUrl } } } : undefined;
10
+ if (!clientDir) {
11
+ // Session 164 final review fix: this used to be a static top-level
12
+ // `import { PrismaClient } from "@prisma/client"`, the ONLY value
13
+ // import of that package under apps/server/src (every other reader
14
+ // imports just the type). `pnpm deploy --legacy --prod` does not copy
15
+ // Prisma's generated `.prisma/client` companion directory (a `pnpm
16
+ // deploy` limitation with Prisma's split-package generated-client
17
+ // layout — see generate-prisma-clients.ts's generateDefaultPrismaClient
18
+ // comment), so a static import of the value crashed a flattened deploy
19
+ // target at import time — before DATABASE_URL or boot-mode logic ever
20
+ // ran — with `SyntaxError: Named export 'PrismaClient' not found`.
21
+ // That crash happens outside index.ts's `try { mode = await
22
+ // resolveBootMode(...) }` (a rejected PROMISE, not a static-import
23
+ // failure), so the operator got a raw stack trace instead of the
24
+ // "Refusing to start:" message.
25
+ //
26
+ // This branch is the only place a bare `@prisma/client` construction
27
+ // ever runs: every production path resolves an explicit clientDir
28
+ // (db/resolve-client-dir.ts derives one from DATABASE_URL's scheme
29
+ // whenever it's set), so `!clientDir` is reachable only pre-setup,
30
+ // where resolveBootMode returns "setup-full" before ever calling
31
+ // countAdmins, and buildSetupOnlyApp() never touches Prisma at all.
32
+ // Deferring the import to here — a dynamic import, evaluated only if
33
+ // this branch actually runs — means the crashing static import no
34
+ // longer exists at all, on any path.
35
+ const { PrismaClient: DefaultPrismaClient } = await import("@prisma/client");
36
+ return new DefaultPrismaClient(options);
37
+ }
38
+ const mod = await import(pathToFileURL(join(clientDir, "index.js")).href);
39
+ const Ctor = (mod.PrismaClient ?? mod.default?.PrismaClient);
40
+ if (!Ctor) {
41
+ throw new Error(`${clientDir} has no PrismaClient export in index.js`);
42
+ }
43
+ return new Ctor(options);
44
+ }
@@ -0,0 +1,3 @@
1
+ import type { Dialect } from "@velora-cms/prisma-variants";
2
+ export declare const prisma: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
3
+ export declare function resolvePrismaDialect(clientDir: string | undefined, databaseUrl: string | undefined): Dialect;
@@ -0,0 +1,67 @@
1
+ import { dialectFromUrlScheme } from "./content-db.js";
2
+ import { loadPrismaClient } from "./load-prisma-client.js";
3
+ import { resolveClientDir } from "./resolve-client-dir.js";
4
+ // The sandbox (velora-dev, Session 78) runs Prisma's standard tables on
5
+ // SQLite via a generated schema variant whose client is emitted into the
6
+ // sandbox state dir. VELORA_PRISMA_CLIENT_DIR points at that generated
7
+ // client; normal dev never sets it and gets @prisma/client untouched.
8
+ export const prisma = await loadPrismaClient(resolveClientDir());
9
+ // Which dialect `prisma` above is actually querying — needed by any query
10
+ // that has to shape itself per-provider (e.g. media-service.ts's filename
11
+ // search, Session 131).
12
+ //
13
+ // Session 131's first attempt read this straight off VELORA_PRISMA_CLIENT_DIR
14
+ // (generate-prisma-clients.ts's clientDirFor() names each generated client's
15
+ // directory after its own dialect, dist/prisma-clients/<dialect>) and threw
16
+ // if the last path segment wasn't a recognized name. That crashed boot in
17
+ // velora-dev: the sandbox always points VELORA_PRISMA_CLIENT_DIR at an
18
+ // un-suffixed "<stateDir>/prisma-client" for every --db choice (see
19
+ // packages/velora-dev/src/config.ts), so the throw fired on every sandbox
20
+ // dialect, not just an unconfigured one.
21
+ //
22
+ // The dialect of the standard-table Prisma client is really a property of
23
+ // the database it connects to, and DATABASE_URL's scheme is the trusted way
24
+ // to derive that (content-db.ts's resolveContentDatabase does the same for
25
+ // the content database, Session 78) — so that's the primary signal now.
26
+ // Resolution order:
27
+ // 1. VELORA_PRISMA_CLIENT_DIR, if its last path segment is one of the
28
+ // three recognized dialect names — the explicit multi-dialect
29
+ // dist/prisma-clients/<dialect> layout stays authoritative when it's
30
+ // actually in play, since that's a stronger signal than a URL scheme.
31
+ // 2. Otherwise, DATABASE_URL's scheme (postgres/postgresql:// →
32
+ // postgresql, mysql:// → mysql, file: → sqlite) — this is what makes
33
+ // the sandbox's un-suffixed client dir resolve correctly per --db
34
+ // choice instead of crashing.
35
+ // 3. If neither yields a dialect (no DATABASE_URL, unrecognized
36
+ // everything), fall back to "postgresql" — schema.prisma's own default
37
+ // `provider` (see packages/prisma-variants) — and log a warning naming
38
+ // both channels. Never throw: this only shapes a query, it doesn't
39
+ // open a connection, and a misconfiguration here must be loud in logs,
40
+ // not fatal to boot.
41
+ //
42
+ // Deliberately NOT computed eagerly at module load (unlike `prisma` above):
43
+ // prisma-client-dir.test.ts points VELORA_PRISMA_CLIENT_DIR at an arbitrary
44
+ // stub directory to exercise loadPrismaClient()'s dynamic import in
45
+ // isolation, with no dialect-named directory in play at all — an eager
46
+ // call here would warn at import time for that legitimate, unrelated use.
47
+ // Callers that need the dialect (app.ts and the media integration test, wiring MediaService)
48
+ // call this directly with both env vars.
49
+ export function resolvePrismaDialect(clientDir, databaseUrl) {
50
+ if (clientDir) {
51
+ let normalized = clientDir.replaceAll("\\", "/");
52
+ while (normalized.endsWith("/"))
53
+ normalized = normalized.slice(0, -1);
54
+ const marker = normalized.split("/").pop();
55
+ if (marker === "postgresql" || marker === "mysql" || marker === "sqlite") {
56
+ return marker;
57
+ }
58
+ }
59
+ if (databaseUrl) {
60
+ const dialect = dialectFromUrlScheme(databaseUrl);
61
+ if (dialect)
62
+ return dialect;
63
+ }
64
+ console.warn(`resolvePrismaDialect: could not determine the Prisma dialect from VELORA_PRISMA_CLIENT_DIR=${clientDir ? `"${clientDir}"` : "(unset)"} or DATABASE_URL=${databaseUrl ? `"${databaseUrl}"` : "(unset)"} — defaulting to postgresql (schema.prisma's own default provider). Query shaping that depends on the ` +
65
+ "real dialect (e.g. media-service.ts's filename search) may be wrong; set one of those env vars to fix it.");
66
+ return "postgresql";
67
+ }
@@ -0,0 +1,2 @@
1
+ export declare function hasGeneratedClientOnDisk(dir: string): boolean;
2
+ export declare function resolveClientDir(env?: NodeJS.ProcessEnv, hasGeneratedClient?: (dir: string) => boolean): string | undefined;