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