@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,87 @@
1
+ // Build-time only. Packs the first-party starter templates the setup
2
+ // wizard's optional "starter template" step offers (currently just the
3
+ // blog template — plugins/blog) with the REAL velora-plugin build
4
+ // pipeline, and lays the result out for setup/bundled-templates.ts to
5
+ // find: apps/server/bundled-templates/<pluginId>/{package.tar.gz,
6
+ // manifest.json, sample-content.json} (repo path — what a `tsx`-run dev
7
+ // server resolves), then copied wholesale into
8
+ // apps/server/dist/bundled-templates (the production-shaped location —
9
+ // copy-docs-bundle.ts's precedent: ship the artifact inside the server's
10
+ // own dist/, not just the repo path).
11
+ //
12
+ // ONE plugin only, packed IN-PROCESS via packPlugin(). velora-plugin's
13
+ // build runs a real Vite Module Federation build — running a SECOND one
14
+ // inside the same process deadlocks reproducibly (S143, discovered while
15
+ // building apps/marketplace/scripts/seed-artifacts.ts: five straight
16
+ // hangs at the second plugin, hours of spun CPU, while every
17
+ // single-plugin run completed in seconds — leaked in-process Vite build
18
+ // state, not a property of any one plugin). See seed-artifact-one.ts for
19
+ // the child-process-per-plugin pattern this script MUST switch to before
20
+ // a second bundled template is ever added here.
21
+ import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
22
+ import { dirname, join } from "node:path";
23
+ import { fileURLToPath } from "node:url";
24
+ import { loadManifest } from "velora-plugin";
25
+ import { packPlugin } from "velora-plugin/pack";
26
+ // This script runs from TWO locations: <server>/dist/scripts (compiled,
27
+ // via `pnpm build`) and <server>/src/scripts (standalone `tsx` run via the
28
+ // pack-templates script). Both sit exactly two directories under the
29
+ // package root, so anchor everything off that root — never off `here`'s
30
+ // parent, which would land the dist copy inside src/ on a tsx run and
31
+ // shadow the repo-dir candidate resolveBundledTemplatesDir() checks.
32
+ const here = dirname(fileURLToPath(import.meta.url)); // <server>/{dist|src}/scripts
33
+ const serverDir = join(here, "..", ".."); // <server> (package root)
34
+ const serverDist = join(serverDir, "dist"); // <server>/dist
35
+ const repoRoot = join(serverDir, "..", ".."); // repo root
36
+ const PLUGIN_DIRS = [join(repoRoot, "plugins", "blog")];
37
+ const repoOutRoot = join(serverDir, "bundled-templates");
38
+ const distOutRoot = join(serverDist, "bundled-templates");
39
+ async function packOne(pluginDir) {
40
+ const manifestResult = await loadManifest(pluginDir);
41
+ if (!manifestResult.ok) {
42
+ throw new Error(`pack-bundled-templates: manifest failed to load from ${pluginDir}:\n${manifestResult.errors.join("\n")}`);
43
+ }
44
+ const { id } = manifestResult.manifest;
45
+ console.log(`[pack-bundled-templates] packing ${id} (real build — this takes a while)…`);
46
+ const packed = await packPlugin(pluginDir);
47
+ try {
48
+ const templateOutDir = join(repoOutRoot, id);
49
+ rmSync(templateOutDir, { recursive: true, force: true });
50
+ mkdirSync(templateOutDir, { recursive: true });
51
+ cpSync(packed.archivePath, join(templateOutDir, "package.tar.gz"));
52
+ // manifest.json and sample-content.json (when present) come from the
53
+ // build's own outDir — velora-plugin's writeManifestJson/
54
+ // copySampleContentIfPresent already put them there; this only ever
55
+ // COPIES what the build produced, never regenerates it.
56
+ const manifestJsonPath = join(packed.buildResult.outDir, "manifest.json");
57
+ if (!existsSync(manifestJsonPath)) {
58
+ throw new Error(`pack-bundled-templates: ${manifestJsonPath} missing after build — did velora-plugin's writeManifestJson change?`);
59
+ }
60
+ cpSync(manifestJsonPath, join(templateOutDir, "manifest.json"));
61
+ const sampleContentPath = join(packed.buildResult.outDir, "sample-content.json");
62
+ if (existsSync(sampleContentPath)) {
63
+ cpSync(sampleContentPath, join(templateOutDir, "sample-content.json"));
64
+ }
65
+ console.log(`[pack-bundled-templates] ${id} -> ${templateOutDir}`);
66
+ }
67
+ finally {
68
+ // packPlugin leaves <pluginDir>/<id>-<version>.tar.gz behind (its
69
+ // default outFile) — apps/marketplace/scripts/seed-artifact-one.ts's
70
+ // precedent for cleaning it up unconditionally, success or failure.
71
+ rmSync(packed.archivePath, { force: true });
72
+ }
73
+ }
74
+ async function main() {
75
+ for (const pluginDir of PLUGIN_DIRS) {
76
+ await packOne(pluginDir);
77
+ }
78
+ rmSync(distOutRoot, { recursive: true, force: true });
79
+ cpSync(repoOutRoot, distOutRoot, { recursive: true });
80
+ console.log(`[pack-bundled-templates] copied bundled templates -> ${distOutRoot}`);
81
+ }
82
+ main().catch((error) => {
83
+ // Loud failure, same convention as copy-docs-bundle.ts: a broken bundled
84
+ // template is a build regression, never a skippable case.
85
+ console.error(`[pack-bundled-templates] failed: ${error instanceof Error ? error.stack ?? error.message : String(error)}`);
86
+ process.exit(1);
87
+ });
@@ -0,0 +1,19 @@
1
+ export type DatabaseSelection = {
2
+ dialect: "sqlite";
3
+ filePath: string;
4
+ } | {
5
+ dialect: "postgresql";
6
+ host: string;
7
+ port: number;
8
+ database: string;
9
+ username: string;
10
+ password: string;
11
+ } | {
12
+ dialect: "mysql";
13
+ host: string;
14
+ port: number;
15
+ database: string;
16
+ username: string;
17
+ password: string;
18
+ };
19
+ export declare function buildConnectionString(selection: DatabaseSelection): string;
@@ -0,0 +1,14 @@
1
+ import { normalizeDatabaseUrl } from "./normalize-database-url.js";
2
+ // Credentials must be encoded — a password containing @, :, or / would
3
+ // otherwise silently corrupt the assembled URL (e.g. a literal "@" in
4
+ // the password would be parsed as the user/host separator).
5
+ export function buildConnectionString(selection) {
6
+ if (selection.dialect === "sqlite") {
7
+ // Absolute, always — see normalize-database-url.ts for why a relative
8
+ // file: URL becomes two physical databases.
9
+ return normalizeDatabaseUrl(selection.filePath);
10
+ }
11
+ const user = encodeURIComponent(selection.username);
12
+ const password = encodeURIComponent(selection.password);
13
+ return `${selection.dialect}://${user}:${password}@${selection.host}:${selection.port}/${selection.database}`;
14
+ }
@@ -0,0 +1,19 @@
1
+ import type { BundledTemplate } from "@velora-cms/api-schemas";
2
+ export declare function resolveBundledTemplatesDir(): string | null;
3
+ /**
4
+ * Never throws. Returns [] when the bundled-templates directory can't be
5
+ * resolved, is empty, or every entry in it is malformed — the "outside
6
+ * setup mode" and "nothing bundled" cases both answer this way from
7
+ * routes/setup.ts.
8
+ */
9
+ export declare function listBundledTemplates(): BundledTemplate[];
10
+ /**
11
+ * Resolves the packed archive for one bundled template by EXACT match
12
+ * against listBundledTemplates() — pluginId is only ever compared with
13
+ * `===`, never joined into a filesystem path itself. The path actually
14
+ * joined and returned is built from the matched listing's own pluginId
15
+ * (which came from enumerating real directory entries, not from the
16
+ * request), so an unrelated or path-traversal-shaped input can only ever
17
+ * fail to match and return null.
18
+ */
19
+ export declare function resolveBundledTemplateTarball(pluginId: string): string | null;
@@ -0,0 +1,121 @@
1
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ // Lists the first-party starter templates pack-bundled-templates.ts (a
5
+ // build-time script) packs into the server build, for the setup wizard's
6
+ // optional "starter template" step. Resolution order mirrors
7
+ // routes/docs-static.ts's resolveDocsDir() exactly:
8
+ // 1. VELORA_BUNDLED_TEMPLATES_DIR (ops override)
9
+ // 2. <server dist>/bundled-templates (what pack-bundled-templates.ts
10
+ // copies there — the production-shaped location)
11
+ // 3. <repo>/apps/server/bundled-templates (the pre-copy location the
12
+ // script writes FIRST, and the only one that exists when running the
13
+ // server straight off `tsx` in the monorepo — same "dev candidate"
14
+ // role docs-static.ts's apps/docs/dist-bundle candidate plays there)
15
+ // This module is imported by routes/setup.ts, which is registered by BOTH
16
+ // buildApp() (full app, db access available) and buildSetupOnlyApp() (a
17
+ // bare Fastify app during first-run setup, NO db access) — so everything
18
+ // here must be pure filesystem, never prisma/adapter.
19
+ //
20
+ // A missing or malformed bundled-templates tree NEVER throws: it degrades
21
+ // to an empty list, same "never break boot over an optional extra"
22
+ // philosophy as docs-static.ts's 404-with-cause.
23
+ function isUsableBundledTemplatesDir(candidate) {
24
+ try {
25
+ return statSync(candidate).isDirectory();
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ }
31
+ export function resolveBundledTemplatesDir() {
32
+ const override = process.env.VELORA_BUNDLED_TEMPLATES_DIR;
33
+ if (override) {
34
+ const resolved = resolve(override);
35
+ return isUsableBundledTemplatesDir(resolved) ? resolved : null;
36
+ }
37
+ const here = dirname(fileURLToPath(import.meta.url)); // dist/setup or src/setup
38
+ const candidates = [
39
+ join(here, "..", "bundled-templates"), // dist sibling: dist/setup/../bundled-templates
40
+ join(here, "..", "..", "bundled-templates"), // repo path: apps/server/bundled-templates
41
+ // (same two levels-up from both dist/setup and src/setup, since both
42
+ // sit two directories under the apps/server package root)
43
+ ];
44
+ return candidates.find(isUsableBundledTemplatesDir) ?? null;
45
+ }
46
+ function isNonEmptyString(value) {
47
+ return typeof value === "string" && value.length > 0;
48
+ }
49
+ /**
50
+ * Reads and validates one <bundledTemplatesDir>/<entryName>/manifest.json.
51
+ * Returns null (never throws) for anything unreadable, unparsable, or
52
+ * missing the fields the setup wizard needs — a malformed entry is
53
+ * skipped, not fatal to the rest of the listing.
54
+ */
55
+ function readTemplateListing(templateDir) {
56
+ const manifestPath = join(templateDir, "manifest.json");
57
+ let parsed;
58
+ try {
59
+ parsed = JSON.parse(readFileSync(manifestPath, "utf8"));
60
+ }
61
+ catch {
62
+ return null;
63
+ }
64
+ if (!isNonEmptyString(parsed.id) || !isNonEmptyString(parsed.name) || !isNonEmptyString(parsed.version)) {
65
+ return null;
66
+ }
67
+ const sampleContent = existsSync(join(templateDir, "sample-content.json"));
68
+ return {
69
+ pluginId: parsed.id,
70
+ version: parsed.version,
71
+ name: parsed.name,
72
+ ...(isNonEmptyString(parsed.description) ? { description: parsed.description } : {}),
73
+ sampleContent,
74
+ };
75
+ }
76
+ /**
77
+ * Never throws. Returns [] when the bundled-templates directory can't be
78
+ * resolved, is empty, or every entry in it is malformed — the "outside
79
+ * setup mode" and "nothing bundled" cases both answer this way from
80
+ * routes/setup.ts.
81
+ */
82
+ export function listBundledTemplates() {
83
+ const dir = resolveBundledTemplatesDir();
84
+ if (!dir)
85
+ return [];
86
+ let entries;
87
+ try {
88
+ entries = readdirSync(dir, { withFileTypes: true })
89
+ .filter((entry) => entry.isDirectory())
90
+ .map((entry) => entry.name);
91
+ }
92
+ catch {
93
+ return [];
94
+ }
95
+ const templates = [];
96
+ for (const entryName of entries) {
97
+ const listing = readTemplateListing(join(dir, entryName));
98
+ if (listing)
99
+ templates.push(listing);
100
+ }
101
+ return templates;
102
+ }
103
+ /**
104
+ * Resolves the packed archive for one bundled template by EXACT match
105
+ * against listBundledTemplates() — pluginId is only ever compared with
106
+ * `===`, never joined into a filesystem path itself. The path actually
107
+ * joined and returned is built from the matched listing's own pluginId
108
+ * (which came from enumerating real directory entries, not from the
109
+ * request), so an unrelated or path-traversal-shaped input can only ever
110
+ * fail to match and return null.
111
+ */
112
+ export function resolveBundledTemplateTarball(pluginId) {
113
+ const match = listBundledTemplates().find((template) => template.pluginId === pluginId);
114
+ if (!match)
115
+ return null;
116
+ const dir = resolveBundledTemplatesDir();
117
+ if (!dir)
118
+ return null;
119
+ const tarballPath = join(dir, match.pluginId, "package.tar.gz");
120
+ return existsSync(tarballPath) ? tarballPath : null;
121
+ }
@@ -0,0 +1,3 @@
1
+ export declare function ensurePrismaClientGenerated(dialect: "postgresql" | "mysql" | "sqlite", opts?: {
2
+ clientDir?: string;
3
+ }): Promise<"present" | "generated">;
@@ -0,0 +1,23 @@
1
+ import { clientDirFor, generatePrismaClients } from "../scripts/generate-prisma-clients.js";
2
+ import { hasGeneratedClientOnDisk } from "../db/resolve-client-dir.js";
3
+ // An npm-installed server ships no generated Prisma clients (they are
4
+ // platform-specific and huge) — the dialect's client is generated on this
5
+ // machine the first time it is needed: at wizard provisioning, and here at
6
+ // boot as self-heal after a node_modules wipe.
7
+ export async function ensurePrismaClientGenerated(dialect, opts = {}) {
8
+ // resolve-client-dir.ts:64-66 gives VELORA_PRISMA_CLIENT_DIR strict
9
+ // precedence over the dialect-derived dist/prisma-clients/<dialect> path
10
+ // — velora-dev's sandbox sets it to point at its own state directory for
11
+ // every --db choice. Honor that same precedence here: when it's set,
12
+ // that directory's owner (not this self-heal) manages what lives there.
13
+ // Generating into clientDirFor(dialect) instead would spend up to a
14
+ // minute producing a client at a path boot never actually loads.
15
+ if (process.env.VELORA_PRISMA_CLIENT_DIR?.trim())
16
+ return "present";
17
+ const dir = opts.clientDir ?? clientDirFor(dialect);
18
+ if (hasGeneratedClientOnDisk(dir))
19
+ return "present";
20
+ console.log(`generating Prisma clients for ${dialect} (first run after install — this can take a minute)…`);
21
+ await generatePrismaClients([dialect]);
22
+ return "generated";
23
+ }
@@ -0,0 +1,14 @@
1
+ import type { PrismaClient } from "@prisma/client";
2
+ import type { SetupStarterResult, SetupStarterSelection } from "@velora-cms/api-schemas";
3
+ export interface InstallStarterTemplateOptions {
4
+ /** The setup handler's dialect-specific client, still connected — the
5
+ * same instance that just created the admin user. */
6
+ prisma: PrismaClient;
7
+ /** The just-built connection string for the chosen database — not in
8
+ * process.env yet at this point in the request. */
9
+ databaseUrl: string;
10
+ /** The freshly-created admin row's id: sample content's createdBy. */
11
+ adminUserId: string;
12
+ starter: SetupStarterSelection;
13
+ }
14
+ export declare function installStarterTemplate(options: InstallStarterTemplateOptions): Promise<SetupStarterResult>;
@@ -0,0 +1,76 @@
1
+ import { connectContentDbAt } from "../db/content-db.js";
2
+ import { installPackageTarball } from "../plugins/install-package-tarball.js";
3
+ import { PluginRegistryService } from "../plugins/plugin-registry-service.js";
4
+ import { resolveBundledTemplateTarball } from "./bundled-templates.js";
5
+ export async function installStarterTemplate(options) {
6
+ const { prisma, databaseUrl, adminUserId, starter } = options;
7
+ const failed = (reason) => ({
8
+ pluginId: starter.pluginId,
9
+ outcome: "failed",
10
+ reason,
11
+ });
12
+ try {
13
+ const tarballPath = resolveBundledTemplateTarball(starter.pluginId);
14
+ if (!tarballPath) {
15
+ return failed(`No bundled starter template found for "${starter.pluginId}"`);
16
+ }
17
+ // The content-db connection for the CHOSEN database — brings the
18
+ // content tables up to date (the setup-only app never connected a
19
+ // content db; the later real boot re-runs the same migrations
20
+ // idempotently via velora_migrations).
21
+ const contentDb = await connectContentDbAt(databaseUrl);
22
+ try {
23
+ // Same service construction as install-built-package.ts's CLI entry:
24
+ // the registry service plus the three prisma-backed row callbacks.
25
+ const service = new PluginRegistryService(prisma, contentDb.adapter, {
26
+ activeDialect: contentDb.dialect,
27
+ });
28
+ const setRemoteUrl = async (pluginId, remoteUrl) => {
29
+ await prisma.pluginRegistry.update({ where: { pluginId }, data: { remoteUrl } });
30
+ };
31
+ const syncManifestFields = async (pluginId, fields) => {
32
+ await prisma.pluginRegistry.update({ where: { pluginId }, data: fields });
33
+ };
34
+ const setPackagePath = async (pluginId, packagePath) => {
35
+ await prisma.pluginRegistry.update({ where: { pluginId }, data: { packagePath } });
36
+ };
37
+ // remoteUrl "" — a template plugin has no client bundle, so there is
38
+ // no remoteEntry.js to point the admin loader at (the same rule
39
+ // install-from-marketplace.ts applies to view-less plugin types).
40
+ await installPackageTarball(service, tarballPath, "", setRemoteUrl, syncManifestFields, setPackagePath, {
41
+ seed: starter.includeSampleContent
42
+ ? { prisma, adapter: contentDb.adapter, createdBy: adminUserId }
43
+ : undefined,
44
+ });
45
+ return { pluginId: starter.pluginId, outcome: "installed" };
46
+ }
47
+ finally {
48
+ // Best-effort: a disconnect hiccup must not convert a completed
49
+ // install into a reported failure via the outer catch.
50
+ try {
51
+ await contentDb.adapter.disconnect();
52
+ }
53
+ catch (disconnectError) {
54
+ console.warn("[install-starter] content-db disconnect failed after starter install", disconnectError);
55
+ }
56
+ }
57
+ }
58
+ catch (error) {
59
+ console.error(`[install-starter] starter "${starter.pluginId}" failed — setup itself stands`, error);
60
+ return failed(failureReason(error));
61
+ }
62
+ }
63
+ /**
64
+ * Compresses an arbitrary thrown error into a schema-safe, single-line
65
+ * `reason` for the setup response: first line only, trimmed, capped at
66
+ * 200 chars, never empty ("" would fail SetupStarterResultSchema's
67
+ * `min(1)` and turn an already-succeeded setup into a 500). This response
68
+ * is unauthenticated, so the full error (stack, paths, connection
69
+ * strings) stays in the server-side log above — never in the reason.
70
+ */
71
+ function failureReason(error) {
72
+ const message = error instanceof Error ? error.message : String(error);
73
+ const firstLine = (message.split("\n", 1)[0] ?? "").trim();
74
+ const capped = firstLine.length > 200 ? firstLine.slice(0, 200) : firstLine;
75
+ return capped.length > 0 ? capped : "unknown error";
76
+ }
@@ -0,0 +1,2 @@
1
+ export declare const FILE_PREFIX = "file:";
2
+ export declare function normalizeDatabaseUrl(url: string, cwd?: string): string;
@@ -0,0 +1,35 @@
1
+ import { isAbsolute, resolve } from "node:path";
2
+ // Config-visible constant, not a magic literal repeated between this
3
+ // module and its own tests (env-file-path.ts's DEFAULT_ENV_FILENAME sets
4
+ // the same precedent) — normalize-database-url.test.ts and
5
+ // build-connection-string.test.ts import this instead of spelling "file:"
6
+ // out themselves.
7
+ export const FILE_PREFIX = "file:";
8
+ // One choke point for the Session 155 "one sqlite database is two files"
9
+ // trap. A relative `file:` URL is resolved differently by Prisma's CLI
10
+ // (schema-directory-relative, see setup/provision-database.ts's
11
+ // `--schema` invocation) and by the content-db adapter (cwd-relative), so
12
+ // `file:./velora.db` produced two physical files that were each
13
+ // internally consistent and collectively wrong — the operator backs up
14
+ // the one they were told about, which may not be the one being written.
15
+ //
16
+ // Making the path absolute removes the divergence rather than documenting
17
+ // it: there is nothing relative left for the two resolvers to disagree
18
+ // about.
19
+ //
20
+ // Applied in TWO places, which together cover every source of a database
21
+ // URL: buildConnectionString (what the wizard collects) and index.ts (an
22
+ // externally injected DATABASE_URL, normalised in place at boot before
23
+ // anything reads it).
24
+ //
25
+ // Non-sqlite URLs are returned byte-identical — the credential encoding
26
+ // buildConnectionString performs must not be disturbed.
27
+ export function normalizeDatabaseUrl(url, cwd = process.cwd()) {
28
+ const isFileUrl = url.startsWith(FILE_PREFIX);
29
+ if (!isFileUrl && url.includes("://"))
30
+ return url;
31
+ const path = isFileUrl ? url.slice(FILE_PREFIX.length) : url;
32
+ if (path.length === 0)
33
+ return url;
34
+ return `${FILE_PREFIX}${isAbsolute(path) ? path : resolve(cwd, path)}`;
35
+ }
@@ -0,0 +1,2 @@
1
+ export declare function upsertEnvVars(content: string, vars: Record<string, string>): string;
2
+ export declare function persistDatabaseConfig(databaseUrl: string, envPath?: string): void;
@@ -0,0 +1,63 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { resolveEnvFilePath } from "../config/env-file-path.js";
3
+ export function upsertEnvVars(content, vars) {
4
+ let out = content;
5
+ for (const [key, value] of Object.entries(vars)) {
6
+ const line = `${key}=${value}`;
7
+ const pattern = new RegExp(`^${key}=.*$`, "m");
8
+ if (pattern.test(out)) {
9
+ out = out.replace(pattern, () => line);
10
+ }
11
+ else {
12
+ out = out.length > 0 && !out.endsWith("\n") ? `${out}\n${line}\n` : `${out}${line}\n`;
13
+ }
14
+ }
15
+ return out;
16
+ }
17
+ // Writes ONLY DATABASE_URL, and only to the path config/env-file-path.ts
18
+ // resolves — the same path load-env.ts reads at the next boot, so the two
19
+ // cannot drift.
20
+ //
21
+ // Two things this deliberately no longer does:
22
+ //
23
+ // - It no longer walks four levels up from its own compiled location to
24
+ // find the repo root. That assumed the monorepo's directory depth and
25
+ // overshot on a flattened `pnpm deploy` output.
26
+ //
27
+ // - It no longer writes VELORA_PRISMA_CLIENT_DIR. That was an absolute
28
+ // path captured from the machine that ran setup, wrong as soon as the
29
+ // install moved. db/resolve-client-dir.ts derives it from
30
+ // DATABASE_URL's scheme instead. The variable is still READ, and
31
+ // still wins when set explicitly — velora-dev's sandbox depends on
32
+ // that (packages/velora-dev/src/config.ts).
33
+ //
34
+ // One thing that was true before this file's packaging rework and still
35
+ // is: this only ever writes a physical .env FILE. A deployment target
36
+ // configured entirely by externally injected environment variables (a
37
+ // container's env block, a platform's secret manager) has no file for
38
+ // this to find or create, and persisting to one there would be actively
39
+ // wrong — nothing downstream would read it back, and it would leave a
40
+ // stray file with no one owning its lifecycle. That per-deployment-shape
41
+ // decision now DOES exist upstream, in routes/setup.ts's POST
42
+ // /api/setup/complete handler: it calls persistDatabaseConfig() only when
43
+ // `!opts.databaseConfigured` (the setup-full path, where DATABASE_URL was
44
+ // unset at boot). In admin-only mode (opts.databaseConfigured: true —
45
+ // DATABASE_URL was already injected by the environment) it skips this
46
+ // call entirely, precisely because that shape has nothing of its own to
47
+ // persist. This module still just writes to whatever path it's given (or
48
+ // resolveEnvFilePath() derives) — it has no opinion of its own about
49
+ // when it should run; that decision belongs to, and now lives in, the
50
+ // caller.
51
+ //
52
+ // Only ever called on the setup-full path (routes/setup.ts's
53
+ // `if (!opts.databaseConfigured)` guard around this call), where
54
+ // DATABASE_URL was unset at boot. Two other cases never reach it: an
55
+ // already-fully-configured instance (setupRequired: false) is rejected by
56
+ // this route's earlier 409 guard before any of this runs at all, and
57
+ // admin-only mode (opts.databaseConfigured: true, DATABASE_URL already
58
+ // injected by the environment) reaches admin creation but is excluded by
59
+ // that same `if` — see the comment above for why.
60
+ export function persistDatabaseConfig(databaseUrl, envPath = resolveEnvFilePath()) {
61
+ const existing = existsSync(envPath) ? readFileSync(envPath, "utf8") : "";
62
+ writeFileSync(envPath, upsertEnvVars(existing, { DATABASE_URL: databaseUrl }));
63
+ }
@@ -0,0 +1,2 @@
1
+ import type { Dialect } from "@velora-cms/prisma-variants";
2
+ export declare function provisionDatabase(dialect: Dialect, databaseUrl: string): Promise<void>;
@@ -0,0 +1,89 @@
1
+ import { execFile } from "node:child_process";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { promisify } from "node:util";
5
+ import { writeVariantSchema } from "../scripts/generate-prisma-clients.js";
6
+ const execFileAsync = promisify(execFile);
7
+ // Anchored the same way generate-prisma-clients.ts anchors its own
8
+ // SERVER_DIR (see that file's comment): npx should always resolve
9
+ // `prisma` as apps/server's own devDependency, not walk up from whatever
10
+ // cwd happened to invoke this function and potentially trigger an
11
+ // unwanted auto-install. Compiled location is dist/setup/provision-database.js,
12
+ // two levels under the package root (dist/setup -> dist -> apps/server) —
13
+ // same depth as dist/scripts.
14
+ const SERVER_DIR = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
15
+ // Deliberately `db push`, never `migrate deploy`/`migrate dev`: the real
16
+ // migration history under apps/server/prisma/migrations/ is hard-locked
17
+ // to provider = "postgresql" (migration_lock.toml) and its SQL is
18
+ // Postgres-specific — pointing a mysql/sqlite schema variant at it fails
19
+ // outright. `db push` is provider-agnostic and has no migration-history
20
+ // dependency, matching velora-dev's sandbox (Session 78) and Session 94's
21
+ // own verification test. Trade-off, deliberately unsolved this session: a
22
+ // database provisioned this way has no _prisma_migrations table, so it
23
+ // can't later be incrementally upgraded via a normal `migrate deploy` —
24
+ // that's a separate problem (existing self-hosted instance schema
25
+ // updates), not first-run setup.
26
+ // Twin of generate-prisma-clients.ts's runPrismaGenerate — same spawnSync +
27
+ // stdio: "inherit" + shell: true pattern, same fix for the same reason (see
28
+ // that file's comment on the vitest-worker "onTaskUpdate" RPC timeout).
29
+ // This call site's own single spawnSync is shorter in isolation (~10-12s
30
+ // against real infra), but it is a live setup-request code path — provision
31
+ // on any given call can run slower under load (the full-suite run's
32
+ // mysql-dialect setup-complete case measured 37s wall for the whole
33
+ // request) — so it carries the same class of risk and gets the same fix.
34
+ async function provisionDatabaseNow(dialect, databaseUrl) {
35
+ const variantPath = writeVariantSchema(dialect);
36
+ try {
37
+ const { stdout, stderr } = await execFileAsync("npx", ["prisma", "db", "push", "--schema", `"${variantPath}"`, "--skip-generate"], {
38
+ cwd: SERVER_DIR,
39
+ shell: true,
40
+ // Same rationale as generate-prisma-clients.ts: the 1 MiB default
41
+ // maxBuffer kills the child on overflow — setup must never fail
42
+ // that way over verbose prisma output.
43
+ maxBuffer: 64 * 1024 * 1024,
44
+ env: { ...process.env, DATABASE_URL: databaseUrl },
45
+ });
46
+ if (stdout)
47
+ process.stdout.write(stdout);
48
+ if (stderr)
49
+ process.stderr.write(stderr);
50
+ }
51
+ catch (error) {
52
+ const failed = error;
53
+ if (failed.stdout)
54
+ process.stdout.write(failed.stdout);
55
+ if (failed.stderr)
56
+ process.stderr.write(failed.stderr);
57
+ throw new Error(`provisionDatabase: prisma db push failed for ${dialect} (exit ${failed.code})`);
58
+ }
59
+ }
60
+ // `prisma db push` is not safe to run truly concurrently against the same
61
+ // target: two overlapping schema-engine invocations racing on the same
62
+ // fresh schema were observed to fail outright — postgresql refuses with a
63
+ // data-loss warning it can't auto-accept, mysql fails a bare `CREATE TABLE`
64
+ // with "already exists" — instead of both landing cleanly. Before this
65
+ // file's spawnSync -> execFile conversion this was invisible: spawnSync
66
+ // blocks the entire process, so two "concurrent" provisionDatabase() calls
67
+ // in the same Node process could never actually overlap — the second
68
+ // caller's code couldn't even start running until the first's synchronous
69
+ // call returned, which serialized them as a side effect. Fixing the real
70
+ // bug (spawnSync blocking the event loop past vitest's RPC timeout) removed
71
+ // that accidental serialization and exposed the race directly:
72
+ // setup-complete.integration.test.ts's M-3 concurrent-completion test
73
+ // started seeing [200, 400] instead of [200, 409] on both postgresql and
74
+ // mysql. Restoring in-process serialization explicitly — a bare promise
75
+ // chain, not a new dependency — keeps calls in the SAME process (e.g. two
76
+ // inbound setup requests racing the same live server, exactly what that
77
+ // test reproduces) queued one at a time, while still letting the event
78
+ // loop answer other work between them. Calls from separate processes
79
+ // (separate vitest workers, a real deploy) are unaffected either way, same
80
+ // as before.
81
+ let queue = Promise.resolve();
82
+ export function provisionDatabase(dialect, databaseUrl) {
83
+ const run = queue.then(() => provisionDatabaseNow(dialect, databaseUrl));
84
+ // Chain the queue off a version that never rejects, so one failed
85
+ // provision doesn't wedge every call queued after it — each caller still
86
+ // observes its own real outcome (including a real rejection) via `run`.
87
+ queue = run.then(() => undefined, () => undefined);
88
+ return run;
89
+ }
@@ -0,0 +1,4 @@
1
+ import { type FastifyInstance } from "fastify";
2
+ export declare function buildSetupOnlyApp(opts?: {
3
+ databaseConfigured: boolean;
4
+ }): Promise<FastifyInstance>;
@@ -0,0 +1,43 @@
1
+ import Fastify from "fastify";
2
+ import { serializerCompiler, validatorCompiler } from "fastify-type-provider-zod";
3
+ import { adminStaticRoutes } from "./routes/admin-static.js";
4
+ import { setupRoutes } from "./routes/setup.js";
5
+ // The reduced "not configured yet" boot mode (Session 96), later widened
6
+ // (Task 4, boot/resolve-boot-mode.ts's resolveBootMode) to a second case:
7
+ // a genuinely minimal app, built whenever resolveBootMode() picks anything
8
+ // other than "full" — that's no longer only DATABASE_URL being unset
9
+ // (setup-full); it's also "setup-admin-only", where DATABASE_URL IS set
10
+ // but no admin row exists yet. Never calls connectContentDb(), never
11
+ // touches prisma, never constructs PluginRegistryService/MediaService/
12
+ // StructuredStorageAPI — in the setup-full case there is nothing
13
+ // configured for those to connect to yet, and in setup-admin-only the
14
+ // whole point of this app is the single admin-creation route, not the
15
+ // rest of the stack. This is a SEPARATE boot path, not a gate inside
16
+ // buildApp() itself: buildApp() calls connectContentDb() before any hook
17
+ // could be registered, and connectContentDb() throws immediately when no
18
+ // database URL is set — a hook registered later in the same app could
19
+ // never run in that case.
20
+ //
21
+ // Session 164: also built when DATABASE_URL IS set but the database holds
22
+ // no admin user — the admin-only mode. In that case Prisma HAS already
23
+ // been reached, by boot/resolve-boot-mode.ts's probe, before this app was
24
+ // chosen; the "never touches prisma" invariant above is about the
25
+ // unconfigured path and still holds there.
26
+ export async function buildSetupOnlyApp(opts = { databaseConfigured: false }) {
27
+ const app = Fastify({ logger: true }).withTypeProvider();
28
+ app.setValidatorCompiler(validatorCompiler);
29
+ app.setSerializerCompiler(serializerCompiler);
30
+ await app.register(setupRoutes, { setupRequired: true, databaseConfigured: opts.databaseConfigured });
31
+ // S184: the wizard IS the admin SPA, so this reduced boot mode has to
32
+ // serve /velora too — a fresh install has no other browser surface.
33
+ // Registered BEFORE setNotFoundHandler below, and route matching beats a
34
+ // not-found handler regardless, so the 503 "not configured yet" reply
35
+ // still covers every path this module does not own. admin-static.ts is
36
+ // deliberately Prisma-free (see its rate-limit comment) so importing it
37
+ // here cannot violate this path's no-Prisma invariant.
38
+ await app.register(adminStaticRoutes);
39
+ app.setNotFoundHandler((_request, reply) => {
40
+ reply.code(503).send({ message: "Velora is not configured yet — complete setup first." });
41
+ });
42
+ return app;
43
+ }