@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,636 @@
1
+ import { validatePluginManifest, } from "@velora-cms/plugin-sdk/manifest";
2
+ import { DocumentTypeInUseError, DocumentTypeService } from "@velora-cms/content-service";
3
+ /** Manifest failed Session 60's validation — carries the readable
4
+ * `path: message` errors for the future install route to surface. */
5
+ export class PluginInstallError extends Error {
6
+ errors;
7
+ constructor(message, errors = []) {
8
+ super(message);
9
+ this.errors = errors;
10
+ this.name = "PluginInstallError";
11
+ }
12
+ }
13
+ /** The manifest is valid but declares it doesn't support the site's
14
+ * active database — blocked with the declared reason, never a silent
15
+ * failure. Subclass of PluginInstallError so general install handling
16
+ * keeps working while the marketplace/UI can distinguish. */
17
+ export class PluginIncompatibleError extends PluginInstallError {
18
+ constructor(message) {
19
+ super(message);
20
+ this.name = "PluginIncompatibleError";
21
+ }
22
+ }
23
+ export class PluginNotInstalledError extends Error {
24
+ constructor(pluginId) {
25
+ super(`No installed plugin with id "${pluginId}"`);
26
+ this.name = "PluginNotInstalledError";
27
+ }
28
+ }
29
+ /** The manifest declares pluginDependencies that aren't all installed AND
30
+ * active. Rejected with the full list, not just the first miss, so the
31
+ * installer can resolve everything in one pass rather than discovering
32
+ * missing dependencies one at a time. Subclass of PluginInstallError so
33
+ * existing catch sites keep working. */
34
+ export class PluginDependencyError extends PluginInstallError {
35
+ missingDependencies;
36
+ constructor(pluginId, missingDependencies) {
37
+ super(`Plugin "${pluginId}" requires the following plugin(s), which must be installed and active first: ${missingDependencies.join(", ")}`);
38
+ this.missingDependencies = missingDependencies;
39
+ this.name = "PluginDependencyError";
40
+ }
41
+ }
42
+ /** A declared migration's up()/down() threw during install. Carries the
43
+ * plugin id, the specific migration id that failed, and the original
44
+ * cause — install() has already rolled back every migration that
45
+ * succeeded earlier in this same batch by the time this is thrown, so
46
+ * the plugin is left with no partial migration state and no registry
47
+ * row. Subclass of PluginInstallError so existing catch sites keep
48
+ * working. */
49
+ export class PluginMigrationError extends PluginInstallError {
50
+ migrationId;
51
+ cause;
52
+ constructor(pluginId, migrationId, cause) {
53
+ super(`Plugin "${pluginId}"'s migration "${migrationId}" failed: ${cause instanceof Error ? cause.message : String(cause)}`);
54
+ this.migrationId = migrationId;
55
+ this.cause = cause;
56
+ this.name = "PluginMigrationError";
57
+ }
58
+ }
59
+ /** Installed but disabled — the gate SimpleStorageAPI needs before an
60
+ * HTTP request touches a plugin's stored values: a disabled plugin's
61
+ * views aren't mounted anywhere, so its storage shouldn't be live either. */
62
+ export class PluginNotActiveError extends Error {
63
+ constructor(pluginId) {
64
+ super(`Plugin "${pluginId}" is installed but not active — enable it before using its storage`);
65
+ this.name = "PluginNotActiveError";
66
+ }
67
+ }
68
+ /** The plugin is installed but its manifest (the CODE — hooks are
69
+ * functions) isn't attached in this process, so it can't be activated:
70
+ * enabled:true for something that isn't running would be a lying state.
71
+ * Whatever loads plugin code at boot re-attaches via attachManifest. */
72
+ export class PluginNotLoadedError extends Error {
73
+ constructor(pluginId) {
74
+ super(`Plugin "${pluginId}" is installed but its manifest is not loaded in this process — ` +
75
+ `attach it with attachManifest() before activating`);
76
+ this.name = "PluginNotLoadedError";
77
+ }
78
+ }
79
+ /** Thrown when uninstall() is called on a structured-storage plugin
80
+ * without confirmStructuredDataCleanup: true. The snapshot has ALREADY
81
+ * been taken by this point — nothing else has happened (no onUninstall,
82
+ * no migration rollback, no row deletion) — so retrying with
83
+ * confirmStructuredDataCleanup: true is always safe. */
84
+ export class StructuredDataCleanupRequiresConfirmationError extends Error {
85
+ snapshotGroupId;
86
+ constructor(pluginId, snapshotGroupId) {
87
+ super(`Uninstalling structured-storage plugin "${pluginId}" requires confirmation to proceed — ` +
88
+ `its data was snapshotted as "${snapshotGroupId}". Call uninstall() again with ` +
89
+ `{ confirmStructuredDataCleanup: true } to actually delete its tables.`);
90
+ this.snapshotGroupId = snapshotGroupId;
91
+ this.name = "StructuredDataCleanupRequiresConfirmationError";
92
+ }
93
+ }
94
+ /** F1 QA fix wave: thrown by uninstall()'s document-type guard when one or
95
+ * MORE tracked document types are still in use — aggregated across EVERY
96
+ * tracked document type, not just the first to fail, so the operator sees
97
+ * the whole blocking set in one 409 instead of discovering it one retry at
98
+ * a time. Distinct from content-service's own DocumentTypeInUseError
99
+ * (which only ever describes a single document type, by id) — that class
100
+ * is still what assertDocumentTypeDeletable() throws per-call; this one is
101
+ * what uninstall() throws once it's walked every tracked document type and
102
+ * collected every failure. */
103
+ export class PluginDocumentTypesInUseError extends Error {
104
+ blockers;
105
+ constructor(pluginId, blockers) {
106
+ super(`Cannot uninstall plugin "${pluginId}": the following document type(s) are still in use: ` +
107
+ blockers.map((blocker) => blocker.documentType).join(", "));
108
+ this.blockers = blockers;
109
+ this.name = "PluginDocumentTypesInUseError";
110
+ }
111
+ }
112
+ // install() runs a plugin's declared migrations and onInstall hook
113
+ // before persisting the registry row (Session 72) — a failure at either
114
+ // step leaves no partial state, matching activate()'s "hook before
115
+ // state" philosophy. uninstall() checks every tracked document type is
116
+ // safe to delete FIRST (before anything else, including the
117
+ // structured-data snapshot), then runs onUninstall and rolls migrations
118
+ // back before deleting the row, tolerating a missing manifest the same
119
+ // way deactivate() does (destructive operations must never be blocked by
120
+ // a missing manifest) — see both methods' own doc comments for the full
121
+ // ordering rationale.
122
+ export class PluginRegistryService {
123
+ prisma;
124
+ adapter;
125
+ // Attached manifests — the runtime half the DB row can't hold (hooks
126
+ // are functions). install() attaches automatically; after a server
127
+ // restart the loader (Session 66's federation loader, Month 6's local
128
+ // plugin loader) re-attaches via attachManifest().
129
+ manifests = new Map();
130
+ // In-memory mirror of the DB `enabled` flag (Session 112) — the public
131
+ // read path's per-request serializer lookup needs a sync, in-process
132
+ // answer and must not hit the DB on every content read. Kept in lockstep
133
+ // with every write to the flag below (install/activate/deactivate/
134
+ // uninstall/attachManifest); never read independently as a source of
135
+ // truth — requireActivePlugin() etc. still go through the DB row.
136
+ enabledIds = new Set();
137
+ activeDialect;
138
+ structuredDataLifecycle;
139
+ documentTypeService;
140
+ constructor(prisma, adapter, options) {
141
+ this.prisma = prisma;
142
+ this.adapter = adapter;
143
+ this.activeDialect = options.activeDialect;
144
+ this.structuredDataLifecycle = options.structuredDataLifecycle ?? {
145
+ snapshot: async () => "",
146
+ cleanup: async () => { },
147
+ };
148
+ this.documentTypeService = new DocumentTypeService(adapter);
149
+ }
150
+ /** Non-throwing lookup — the read every other method here already does
151
+ * privately, exposed for callers (SimpleStorageAPI) that need to check
152
+ * installation state without triggering a lifecycle transition. */
153
+ async getInstalledPlugin(pluginId) {
154
+ return this.prisma.pluginRegistry.findUnique({ where: { pluginId } });
155
+ }
156
+ /** Installed AND enabled, or throw — the exact gate SimpleStorageAPI
157
+ * needs on every get()/set(). */
158
+ async requireActivePlugin(pluginId) {
159
+ const row = await this.getInstalledPlugin(pluginId);
160
+ if (!row) {
161
+ throw new PluginNotInstalledError(pluginId);
162
+ }
163
+ if (!row.enabled) {
164
+ throw new PluginNotActiveError(pluginId);
165
+ }
166
+ return row;
167
+ }
168
+ /** Read-only exposure of the attached manifest for a plugin id — used
169
+ * by request-time dispatchers (plugin-api-routes.ts) that need a
170
+ * plugin's declared contributions without going through install()/
171
+ * activate() again. Returns undefined if the manifest isn't attached
172
+ * in this process (never installed, or a restart happened and
173
+ * attachManifest() hasn't re-attached it yet). */
174
+ getManifest(pluginId) {
175
+ return this.manifests.get(pluginId);
176
+ }
177
+ /** Re-attach a loaded plugin's manifest to an existing installation
178
+ * (post-restart bridge for the boot-time plugin loader). */
179
+ async attachManifest(manifest) {
180
+ const row = await this.prisma.pluginRegistry.findUnique({
181
+ where: { pluginId: manifest.id },
182
+ });
183
+ if (!row) {
184
+ throw new PluginNotInstalledError(manifest.id);
185
+ }
186
+ this.manifests.set(manifest.id, manifest);
187
+ // Post-restart bridge: the enabled mirror is process-local and empty
188
+ // on a fresh process, so re-attaching an already-active plugin must
189
+ // seed it from the row the lookup above already fetched.
190
+ if (row.enabled) {
191
+ this.enabledIds.add(manifest.id);
192
+ }
193
+ else {
194
+ this.enabledIds.delete(manifest.id);
195
+ }
196
+ }
197
+ /** The inverse of attachManifest: forget the in-process manifest so
198
+ * request-time consumers (the S89 apiRoutes dispatcher's
199
+ * requireActivePlugin/route lookup) stop answering for this plugin
200
+ * immediately — the uninstall route calls this so no restart is
201
+ * needed. A manifest that was never attached is a no-op. */
202
+ detachManifest(pluginId) {
203
+ this.manifests.delete(pluginId);
204
+ }
205
+ /**
206
+ * Validate a manifest (Session 60's validator — the contribution
207
+ * matrix included) and persist it. Session 127: the trust tier is now
208
+ * an optional caller-supplied value (`opts.trustTier`), defaulting to
209
+ * 'unverified' so every pre-S127 caller (which never supplied one)
210
+ * behaves identically. Local/dev plugins remain unsigned by
211
+ * definition and so always take the default.
212
+ * Installed ≠ active — rows start disabled; activate() is Session 63.
213
+ */
214
+ async install(manifest, opts) {
215
+ const result = validatePluginManifest(manifest);
216
+ if (!result.ok) {
217
+ throw new PluginInstallError(`Plugin manifest failed validation:\n${result.errors.map((e) => ` - ${e}`).join("\n")}`, result.errors);
218
+ }
219
+ const { manifest: plugin } = result;
220
+ // Database compatibility gate (Session 64): blocked with the
221
+ // declared reason, never a silent failure — the marketplace
222
+ // pre-filters by dialect, but sideloads land here too.
223
+ const { supported, unsupportedReason } = plugin.databaseCompatibility;
224
+ if (!supported.includes(this.activeDialect)) {
225
+ const reason = unsupportedReason?.[this.activeDialect];
226
+ throw new PluginIncompatibleError(`Plugin "${plugin.id}" does not support the active database (${this.activeDialect}). ` +
227
+ `Supported: ${supported.join(", ")}.${reason ? ` Reason: ${reason}` : ""}`);
228
+ }
229
+ const existing = await this.prisma.pluginRegistry.findUnique({
230
+ where: { pluginId: plugin.id },
231
+ });
232
+ if (existing) {
233
+ throw new PluginInstallError(`Plugin "${plugin.id}" is already installed (version ${existing.version})`);
234
+ }
235
+ // Dependency resolution (Session 71): every declared dependency must
236
+ // already be installed AND active — a merely-installed-but-disabled
237
+ // dependency's views/routes aren't actually running, so this plugin
238
+ // couldn't rely on it either. Collect every miss in one pass rather
239
+ // than failing on the first, so the installer sees the whole picture.
240
+ if (plugin.pluginDependencies && plugin.pluginDependencies.length > 0) {
241
+ const missing = [];
242
+ for (const dependencyId of plugin.pluginDependencies) {
243
+ const dependency = await this.prisma.pluginRegistry.findUnique({
244
+ where: { pluginId: dependencyId },
245
+ });
246
+ if (!dependency || !dependency.enabled) {
247
+ missing.push(dependencyId);
248
+ }
249
+ }
250
+ if (missing.length > 0) {
251
+ throw new PluginDependencyError(plugin.id, missing);
252
+ }
253
+ }
254
+ // Migrations + onInstall (Session 72): the last gate before the
255
+ // registry row exists, so a failure here leaves no partial state —
256
+ // same "hook before state" philosophy as activate(). ctx is
257
+ // deliberately {} today (PluginMigrationContext, manifest.ts) — this
258
+ // is the only sense in which migrations run "against whichever Tier
259
+ // 1 database is active": the activeDialect check above, not a live
260
+ // adapter connection plugins could use to write raw SQL.
261
+ const applied = [];
262
+ if (plugin.migrations && plugin.migrations.length > 0) {
263
+ for (const migration of plugin.migrations) {
264
+ try {
265
+ await migration.up({});
266
+ await this.prisma.pluginMigrationRecord.create({
267
+ data: { pluginId: plugin.id, migrationId: migration.id },
268
+ });
269
+ applied.push(migration);
270
+ }
271
+ catch (cause) {
272
+ await this.rollbackMigrations(plugin.id, applied);
273
+ throw new PluginMigrationError(plugin.id, migration.id, cause);
274
+ }
275
+ }
276
+ }
277
+ // Document types the manifest provisions at install (Month 8, Session
278
+ // 88) — only section/template plugins carry this contribution. Runs
279
+ // AFTER migrations (mirrors why onInstall already runs after
280
+ // migrations) and BEFORE onInstall, so a plugin's own install hook can
281
+ // rely on its document types already existing.
282
+ //
283
+ // Two-phase (Session 149, Task 2 amendment): a manifest declares
284
+ // treeRules' allowedParentTypes/allowedChildTypes by document type
285
+ // NAME (there's no id to reference at manifest-authoring time — the
286
+ // server mints one per entry, right here), but
287
+ // ContentService.assertValidPlacement compares those arrays against
288
+ // the real minted ids. Before this fix the name strings rode straight
289
+ // through to storage and could never match, silently breaking any
290
+ // cross-referencing treeRules (plugins/commerce never hit this — both
291
+ // its document types declare empty treeRules arrays).
292
+ //
293
+ // Phase 1 creates every declared type with its name-bearing arrays
294
+ // stripped (allowedAtRoot needs no resolution and is preserved),
295
+ // recording declaredName -> mintedId as each row is created. Phase 2
296
+ // walks the ORIGINAL declared requests, resolves every name against
297
+ // that map, and applies the resolved treeRules via the same update
298
+ // surface the admin Document Type editor's PUT /api/document-types/:id
299
+ // route uses (apps/server/src/routes/document-types.ts) —
300
+ // adapter.updateDocumentType, a full replace of the mutable
301
+ // definition (kind/defaultTemplateId untouched). There's no
302
+ // DocumentTypeService wrapper for update (the route calls the adapter
303
+ // directly too), so this mirrors that rather than inventing one. A
304
+ // name that isn't one of THIS plugin's own declared types is an
305
+ // install failure — the single try/catch below rolls back every
306
+ // document type phase 1 created (plus migrations) exactly like a
307
+ // phase-1 failure already did.
308
+ const createdDocumentTypes = [];
309
+ if (plugin.type === "section" || plugin.type === "template") {
310
+ const declared = plugin.contributions.documentTypes ?? [];
311
+ try {
312
+ const mintedIdByName = new Map();
313
+ for (const request of declared) {
314
+ // Fail before the side effect: a manifest declaring the same
315
+ // document type name twice would otherwise let
316
+ // mintedIdByName.set() below silently overwrite the first
317
+ // minted id with the second (last-wins) — every name resolution
318
+ // in phase 2 is load-bearing for tree-rule enforcement, so a
319
+ // silently ambiguous name must never reach it.
320
+ if (mintedIdByName.has(request.name)) {
321
+ throw new PluginInstallError(`Plugin "${plugin.id}" declares document type "${request.name}" more than once — document type names must be unique within a single plugin`);
322
+ }
323
+ const phase1Request = request.kind === "page"
324
+ ? {
325
+ ...request,
326
+ treeRules: {
327
+ allowedAtRoot: request.treeRules.allowedAtRoot,
328
+ allowedParentTypes: [],
329
+ allowedChildTypes: [],
330
+ },
331
+ }
332
+ : request;
333
+ const created = await this.documentTypeService.createDocumentType(phase1Request);
334
+ await this.prisma.pluginDocumentType.create({
335
+ data: { pluginId: plugin.id, documentTypeId: created.id },
336
+ });
337
+ createdDocumentTypes.push(created);
338
+ mintedIdByName.set(request.name, created.id);
339
+ }
340
+ for (const [index, request] of declared.entries()) {
341
+ if (request.kind !== "page")
342
+ continue;
343
+ const { allowedParentTypes, allowedChildTypes } = request.treeRules;
344
+ if (allowedParentTypes.length === 0 && allowedChildTypes.length === 0)
345
+ continue;
346
+ const resolveNames = (names) => names.map((name) => {
347
+ const id = mintedIdByName.get(name);
348
+ if (!id) {
349
+ throw new PluginInstallError(`Plugin "${plugin.id}" document type "${request.name}" declares a treeRules reference to "${name}", ` +
350
+ `which is not one of this plugin's own declared document types (${declared.map((d) => d.name).join(", ")})`);
351
+ }
352
+ return id;
353
+ });
354
+ const createdType = createdDocumentTypes[index];
355
+ await this.adapter.updateDocumentType(createdType.id, {
356
+ name: createdType.name,
357
+ icon: createdType.icon,
358
+ fields: createdType.fields,
359
+ tabs: createdType.tabs,
360
+ treeRules: {
361
+ allowedAtRoot: request.treeRules.allowedAtRoot,
362
+ allowedParentTypes: resolveNames(allowedParentTypes),
363
+ allowedChildTypes: resolveNames(allowedChildTypes),
364
+ },
365
+ });
366
+ }
367
+ }
368
+ catch (cause) {
369
+ await this.rollbackDocumentTypes(plugin.id, createdDocumentTypes);
370
+ await this.rollbackMigrations(plugin.id, applied);
371
+ throw cause;
372
+ }
373
+ }
374
+ try {
375
+ await plugin.onInstall?.();
376
+ }
377
+ catch (cause) {
378
+ await this.rollbackDocumentTypes(plugin.id, createdDocumentTypes);
379
+ await this.rollbackMigrations(plugin.id, applied);
380
+ throw cause;
381
+ }
382
+ const row = await this.prisma.pluginRegistry.create({
383
+ data: {
384
+ pluginId: plugin.id,
385
+ name: plugin.name,
386
+ type: plugin.type,
387
+ version: plugin.version,
388
+ // Session 127: the tier a verified install earned, defaulting to
389
+ // the pre-S127 literal so every existing caller is unchanged.
390
+ trustTier: opts?.trustTier ?? "unverified",
391
+ storageType: plugin.databaseCompatibility.storageType,
392
+ enabled: false,
393
+ },
394
+ });
395
+ this.manifests.set(plugin.id, plugin);
396
+ // Mirror the row just persisted — install() always writes enabled:
397
+ // false today, so this is a no-op in practice, but it's written
398
+ // against row.enabled (not a hardcoded false) so a future
399
+ // auto-activate-on-install path can't silently desync the mirror.
400
+ if (row.enabled) {
401
+ this.enabledIds.add(plugin.id);
402
+ }
403
+ return row;
404
+ }
405
+ /** Roll back a batch of already-applied migrations in reverse order,
406
+ * removing each tracking row as it rolls back. Shared by install()'s
407
+ * two failure paths (a later migration failing, or onInstall failing
408
+ * after all migrations succeeded). */
409
+ async rollbackMigrations(pluginId, migrations) {
410
+ for (const migration of [...migrations].reverse()) {
411
+ await migration.down({});
412
+ await this.prisma.pluginMigrationRecord.deleteMany({
413
+ where: { pluginId, migrationId: migration.id },
414
+ });
415
+ }
416
+ }
417
+ /** Delete every document type created so far in THIS install() call, in
418
+ * reverse order, plus its PluginDocumentType tracking row — always safe
419
+ * to hard-delete without assertDocumentTypeDeletable first, since these
420
+ * were just created inside this same call and cannot yet have any
421
+ * content or template referencing them. Shared by install()'s two
422
+ * documentTypes-era failure paths (a later entry failing, or onInstall
423
+ * failing after all entries succeeded) — same shape as
424
+ * rollbackMigrations. */
425
+ async rollbackDocumentTypes(pluginId, documentTypes) {
426
+ for (const documentType of [...documentTypes].reverse()) {
427
+ await this.documentTypeService.deleteDocumentType(documentType.id);
428
+ await this.prisma.pluginDocumentType.deleteMany({
429
+ where: { pluginId, documentTypeId: documentType.id },
430
+ });
431
+ }
432
+ }
433
+ /**
434
+ * Enable an installed plugin. Hooks fire on TRANSITIONS only —
435
+ * activating an already-active plugin is a no-op. onActivate runs
436
+ * BEFORE enabled:true is persisted: a plugin that fails to start
437
+ * stays disabled. Requires the manifest to be attached (installed
438
+ * but unloaded code can't be "active" — that would be a lying state).
439
+ */
440
+ async activate(pluginId) {
441
+ const row = await this.prisma.pluginRegistry.findUnique({ where: { pluginId } });
442
+ if (!row) {
443
+ throw new PluginNotInstalledError(pluginId);
444
+ }
445
+ if (row.enabled) {
446
+ return;
447
+ }
448
+ const manifest = this.manifests.get(pluginId);
449
+ if (!manifest) {
450
+ throw new PluginNotLoadedError(pluginId);
451
+ }
452
+ await manifest.onActivate?.();
453
+ await this.prisma.pluginRegistry.update({
454
+ where: { pluginId },
455
+ data: { enabled: true },
456
+ });
457
+ this.enabledIds.add(pluginId);
458
+ }
459
+ /**
460
+ * Disable an installed plugin without losing its configuration or
461
+ * data. Deliberately asymmetric with activate(): enabled:false is
462
+ * persisted FIRST and onDeactivate runs after (a hook error
463
+ * propagates, but the plugin is already off — you deactivate things
464
+ * BECAUSE they're broken, so disabling must never be blocked), and a
465
+ * missing manifest is fine (post-restart you can still switch a
466
+ * plugin off; the hook is skipped).
467
+ */
468
+ async deactivate(pluginId) {
469
+ const row = await this.prisma.pluginRegistry.findUnique({ where: { pluginId } });
470
+ if (!row) {
471
+ throw new PluginNotInstalledError(pluginId);
472
+ }
473
+ if (!row.enabled) {
474
+ return;
475
+ }
476
+ await this.prisma.pluginRegistry.update({
477
+ where: { pluginId },
478
+ data: { enabled: false },
479
+ });
480
+ this.enabledIds.delete(pluginId);
481
+ await this.manifests.get(pluginId)?.onDeactivate?.();
482
+ }
483
+ /**
484
+ * Remove an installed plugin. For structured-storage plugins, the
485
+ * confirmation gate is checked FIRST — before onUninstall, before
486
+ * migration rollback, before anything else destructive (Month 8,
487
+ * Session 87): a snapshot is always taken, and if the caller hasn't
488
+ * passed confirmStructuredDataCleanup: true, uninstall() throws
489
+ * StructuredDataCleanupRequiresConfirmationError right there, having
490
+ * changed nothing else — the row, migrations, and manifest are all
491
+ * untouched, so retrying with confirmation is always safe. Only once
492
+ * past that gate does the rest of teardown proceed: fallible cleanup
493
+ * (onUninstall, migration rollback) runs BEFORE the irreversible row
494
+ * delete (Session 72) — a failure there leaves the plugin
495
+ * still-installed and retryable rather than orphaned. Order is
496
+ * stack-shaped, inverse of install(): onUninstall (the last thing
497
+ * installed) runs first, migrations (the first thing installed) roll
498
+ * back last, in LIFO order — reversing manifest.migrations' own
499
+ * declared array, the same source of truth install() walked forward
500
+ * through, rather than sorting the tracked rows by appliedAt. Two
501
+ * migrations applied back-to-back inside the same install() call can
502
+ * land the exact same DateTime (Postgres' now() has finite, and on
503
+ * some platforms coarse, resolution — reproduced on real CI: two
504
+ * inserts a few microseconds apart still tied, and ORDER BY gives no
505
+ * guarantee which tied row sorts first), which silently rolled
506
+ * migrations back out of order. The manifest array has no such
507
+ * ambiguity: array position is exact. If the manifest isn't attached
508
+ * (no server restart re-attached it), both are silently skipped —
509
+ * can't call functions that don't exist in this process — matching
510
+ * deactivate()'s "destructive operations must never be blocked by a
511
+ * missing manifest," applied more strongly here since uninstall is far
512
+ * less reversible than deactivate. The actual structured-data cleanup
513
+ * (dropping the plugin's tables) runs only after confirmation, right
514
+ * before the registry row is deleted.
515
+ */
516
+ async uninstall(pluginId, options) {
517
+ const row = await this.prisma.pluginRegistry.findUnique({ where: { pluginId } });
518
+ if (!row) {
519
+ throw new PluginNotInstalledError(pluginId);
520
+ }
521
+ // Document-type deletion guard, checked FIRST — cheaper and
522
+ // unconditional (never confirmable, unlike structured-data cleanup
523
+ // below), so it fails fast before any other side effect. A blocked
524
+ // document type is not a "confirm to proceed" situation: the caller
525
+ // must resolve the underlying content/template references themselves.
526
+ // F1 QA fix wave: walks every tracked document type and aggregates
527
+ // ALL failures (not just the first) into one PluginDocumentTypesInUseError
528
+ // — an admin with three content-bearing document types used to learn
529
+ // about them one at a time, each retry surfacing the next. The name
530
+ // comes from adapter.getDocumentType() (an existing, already-
531
+ // implemented-for-all-three-dialects read — not a new adapter method)
532
+ // since the tracking row itself only has the id.
533
+ const trackedDocumentTypes = await this.prisma.pluginDocumentType.findMany({ where: { pluginId } });
534
+ const blockers = [];
535
+ for (const tracked of trackedDocumentTypes) {
536
+ try {
537
+ await this.documentTypeService.assertDocumentTypeDeletable(tracked.documentTypeId);
538
+ }
539
+ catch (error) {
540
+ if (!(error instanceof DocumentTypeInUseError))
541
+ throw error;
542
+ const documentType = await this.adapter.getDocumentType(tracked.documentTypeId);
543
+ blockers.push({
544
+ documentTypeId: tracked.documentTypeId,
545
+ documentType: documentType?.name ?? tracked.documentTypeId,
546
+ reason: error.reason,
547
+ contentCount: error.contentCount,
548
+ });
549
+ }
550
+ }
551
+ if (blockers.length > 0) {
552
+ throw new PluginDocumentTypesInUseError(pluginId, blockers);
553
+ }
554
+ // Checked next, before onUninstall/migration rollback/anything else
555
+ // — a rejected call must be safe to retry, which means nothing else
556
+ // can have happened yet when this throws. simple-storage plugins never
557
+ // take this branch, so snapshotGroupId stays null for them (Task 6:
558
+ // the CONFIRMED pass's minted id is threaded through to the return
559
+ // below — the unconfirmed pass still throws with its id on the error,
560
+ // as before).
561
+ let snapshotGroupId = null;
562
+ if (row.storageType === "structured") {
563
+ snapshotGroupId = await this.structuredDataLifecycle.snapshot(pluginId);
564
+ if (!options?.confirmStructuredDataCleanup) {
565
+ throw new StructuredDataCleanupRequiresConfirmationError(pluginId, snapshotGroupId);
566
+ }
567
+ }
568
+ const manifest = this.manifests.get(pluginId);
569
+ if (manifest) {
570
+ await manifest.onUninstall?.();
571
+ const records = await this.prisma.pluginMigrationRecord.findMany({ where: { pluginId } });
572
+ const trackedByMigrationId = new Map(records.map((record) => [record.migrationId, record]));
573
+ // Reversing manifest.migrations for rollback order (rather than
574
+ // trusting the tracked rows' appliedAt) assumes that array is
575
+ // APPEND-ONLY for an already-installed plugin: a plugin update may
576
+ // only add new entries after the existing ones, never reorder or
577
+ // remove entries an earlier install already applied. Violate that
578
+ // and this reversal silently rolls back in the wrong order --
579
+ // there is no other signal here to detect or correct for it.
580
+ for (const migration of [...(manifest.migrations ?? [])].reverse()) {
581
+ const record = trackedByMigrationId.get(migration.id);
582
+ if (!record)
583
+ continue;
584
+ await migration.down({});
585
+ await this.prisma.pluginMigrationRecord.delete({ where: { id: record.id } });
586
+ }
587
+ }
588
+ if (row.storageType === "structured") {
589
+ await this.structuredDataLifecycle.cleanup(pluginId);
590
+ }
591
+ for (const tracked of trackedDocumentTypes) {
592
+ await this.documentTypeService.deleteDocumentType(tracked.documentTypeId);
593
+ }
594
+ await this.prisma.pluginDocumentType.deleteMany({ where: { pluginId } });
595
+ await this.prisma.pluginRegistry.delete({ where: { pluginId } });
596
+ // Sweeps any tracking rows the unattached-manifest path above
597
+ // couldn't roll back individually (down() needs the manifest's
598
+ // function reference, which doesn't exist without it).
599
+ await this.prisma.pluginMigrationRecord.deleteMany({ where: { pluginId } });
600
+ this.manifests.delete(pluginId);
601
+ this.enabledIds.delete(pluginId);
602
+ return { snapshotGroupId };
603
+ }
604
+ /** Active plugins with an attached manifest declaring serializers —
605
+ * the public read path's per-request lookup (Session 112). Sync and
606
+ * in-memory: an active-but-unattached plugin (the standing S89
607
+ * no-boot-loader gap) is skipped exactly like its apiRoutes are. */
608
+ listActiveSerializerContributions() {
609
+ const out = [];
610
+ for (const [pluginId, manifest] of this.manifests) {
611
+ if (!this.enabledIds.has(pluginId))
612
+ continue;
613
+ const serializers = manifest.contributions.serializers;
614
+ if (serializers)
615
+ out.push({ pluginId, serializers });
616
+ }
617
+ return out;
618
+ }
619
+ /** Active plugins with an attached manifest declaring a handler for
620
+ * this specific event — the hook dispatcher's per-event lookup (S159).
621
+ * Sync and in-memory, same shape as listActiveSerializerContributions:
622
+ * an active-but-unattached plugin is skipped exactly like its apiRoutes
623
+ * and serializers are. */
624
+ listActiveHookContributions(event) {
625
+ const out = [];
626
+ for (const [pluginId, manifest] of this.manifests) {
627
+ if (!this.enabledIds.has(pluginId))
628
+ continue;
629
+ const hooks = manifest.contributions.hooks;
630
+ const handler = hooks?.[event];
631
+ if (handler)
632
+ out.push({ pluginId, handler });
633
+ }
634
+ return out;
635
+ }
636
+ }
@@ -0,0 +1,23 @@
1
+ import type { PrismaClient } from "@prisma/client";
2
+ import type { DatabaseAdapter } from "@velora-cms/db-adapter";
3
+ export interface SeedTemplateContentDeps {
4
+ prisma: PrismaClient;
5
+ adapter: DatabaseAdapter;
6
+ }
7
+ export type SeedTemplateContentResult = "none" | "invalid" | "skipped" | {
8
+ created: number;
9
+ };
10
+ /**
11
+ * Seeds a template plugin's sample-content.json as real, published
12
+ * content — creation order in the file IS the seed order (parents
13
+ * precede children per D1's documented contract), and every node is
14
+ * created THEN published, so it lands as version 1, currently published,
15
+ * matching the immutable-versioning path exactly the way a human editor
16
+ * publishing through the admin UI would produce.
17
+ *
18
+ * D2 governs every early return here: idempotent-by-skip (no duplicates
19
+ * on a second install/second call) and non-fatal (a seeding problem never
20
+ * unwinds an otherwise-successful plugin install — the caller's install
21
+ * stands regardless of what this function returns).
22
+ */
23
+ export declare function seedTemplateSampleContent(deps: SeedTemplateContentDeps, pluginId: string, storedPackageDir: string, createdBy?: string): Promise<SeedTemplateContentResult>;