@voltro/cli 0.33.0 → 0.34.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/CHANGELOG.md +1801 -0
- package/bin/nodeEnvironment.d.mts +30 -0
- package/bin/nodeEnvironment.mjs +158 -0
- package/bin/voltro.mjs +69 -5
- package/dist/addCommand-BNeoeSxe.js +124 -0
- package/dist/addCommand-aXSQveak.js +2 -0
- package/dist/agentsMd-BTchIZku.js +2 -0
- package/dist/agentsMd-mhQMF1bx.js +254 -0
- package/dist/apiBuild-BICVGnEC.js +2 -0
- package/dist/{apiBuild-h9VHtnlw.js → apiBuild-DZF_f0_I.js} +46 -46
- package/dist/appPort-B_HpJ_ck.js +48 -0
- package/dist/baselineCommand-C2ClWZN3.js +2 -0
- package/dist/baselineCommand-DIttzO8A.js +227 -0
- package/dist/bin.js +71 -28
- package/dist/build-CE7Ca9gm.js +711 -0
- package/dist/cacheCommand-DA4OH9xt.js +42 -0
- package/dist/capabilitiesCommand-nq_pz5xd.js +123 -0
- package/dist/checkCommand-Dv8r9tGO.js +231 -0
- package/dist/checkCommand-YZDmkAGd.js +2 -0
- package/dist/{cliArgs-qdZSElM3.js → cliArgs-D4p8n7EE.js} +12 -1
- package/dist/cliError-BmdYnghb.js +10 -0
- package/dist/cliOutput-D1tSBoRM.js +15 -0
- package/dist/{cliRuntime-Oh517vCV.js → cliRuntime-Dh7UDinH.js} +20 -20
- package/dist/cloudClient-DWL-Hw_T.js +67 -0
- package/dist/cloudCmd-Cvv5HGaZ.js +364 -0
- package/dist/clusterCmd-CNXKlcvD.js +54 -0
- package/dist/codegen-CYM3Zqrf.js +605 -0
- package/dist/codegen-ChBi_hVa.js +2 -0
- package/dist/codegenCommand-DC6w2tNZ.js +30 -0
- package/dist/codemodRunner-DRRqXR74.js +5243 -0
- package/dist/commandRunner-BLAEFLjp.js +47 -0
- package/dist/commands-gutsz-Ac.js +808 -0
- package/dist/connectionConfig-UFlIEiys.js +66 -0
- package/dist/dashboardCommand-3YG8p-UA.js +25 -0
- package/dist/dataCommand-qL0r7fPO.js +535 -0
- package/dist/dataProfile-dW-PsfLB.js +15 -0
- package/dist/{dbCommand-DTLKAfbA.js → dbCommand-B6X0FZbq.js} +551 -401
- package/dist/dbCommand-CpdKLeQq.js +2 -0
- package/dist/{dev-C_P8FLSx.js → dev-CerMd0mW.js} +3122 -3129
- package/dist/dev-CoG-ZPx8.js +3 -0
- package/dist/devActivity-Dx_3nnGv.js +100 -0
- package/dist/devActivity.js +1 -1
- package/dist/dialectDriver-CgXnDfec.js +39 -0
- package/dist/discover-C9XKJDco.js +25 -0
- package/dist/doctorCommand-BvqGBwNG.js +2 -0
- package/dist/{checkCommand-xGhRFFg2.js → doctorCommand-CnDXQxfa.js} +520 -1278
- package/dist/dormancyCommand-Dszo57d6.js +69 -0
- package/dist/e2eCmd-BRabZww-.js +147 -0
- package/dist/embeddingsCommand-C0sKVRo1.js +73 -0
- package/dist/envCommand-DPgdV1Bq.js +60 -0
- package/dist/evalCommand-6RUfPen4.js +118 -0
- package/dist/evolveCommand-DHpkgjgH.js +281 -0
- package/dist/fileTaxonomy-CJfgOllU.js +457 -0
- package/dist/frameworkTableAssembly-BGHmck-x.js +2 -0
- package/dist/{frameworkTableAssembly-BwIrO5nv.js → frameworkTableAssembly-DkkP6BgC.js} +184 -148
- package/dist/generateCommand-oibemh97.js +147 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +4 -3
- package/dist/infoCommand-BJw9nLUR.js +60 -0
- package/dist/{inspect-BUUjt773.js → inspect-CBqFtAKA.js} +82 -40
- package/dist/inspect-C_T_WGvl.js +2 -0
- package/dist/inspectCmd-Bppy-GGw.js +224 -0
- package/dist/inspectFetch-Cm8_wVvp.js +151 -0
- package/dist/inspectMetrics-CfdKLh6t.js +72 -0
- package/dist/loadEnv-D9nEOClM.js +44 -0
- package/dist/logFileSink-C_D2wRN1.js +105 -0
- package/dist/logsCmd-CCca3KRZ.js +260 -0
- package/dist/manifestBuild-ChsKAhmn.js +2 -0
- package/dist/{manifestBuild-BLrVuSlM.js → manifestBuild-sxpwdKY1.js} +1 -1
- package/dist/metaCommands-7MJfZ5cf.js +196 -0
- package/dist/migrate-CBwOt_iV.js +83 -0
- package/dist/mssqlClusterPatch-_4cE_nun.js +44 -0
- package/dist/newCommand-COWOJ1_E.js +156 -0
- package/dist/nodeEnvironment-cGFAj1J8.js +28 -0
- package/dist/packageCommand-Cug_3Ogl.js +271 -0
- package/dist/pageConvention-cEiRxdab.js +5 -0
- package/dist/privacyCommand-C-Df56U_.js +146 -0
- package/dist/projectScaffold-DmzEKHib.js +2 -0
- package/dist/projectScaffold-LMMtaavR.js +814 -0
- package/dist/renderModeScan-D7J1B7Kw.js +105 -0
- package/dist/renderProfile-1OWWAAtx.js +81 -0
- package/dist/runtimeRegistry-DMeKfTHP.js +81 -0
- package/dist/runtimeTrace-CRxalXTs.js +91 -0
- package/dist/scheduleCmd--jksTrf6.js +69 -0
- package/dist/scheduleManifestCmd-D2x0CTTY.js +249 -0
- package/dist/schemaIr-UJybUUZW.js +103 -0
- package/dist/{sdkgen-C81QIkiL.js → sdkgen-CYJscZC7.js} +111 -209
- package/dist/seedRunner-TFHHiToI.js +329 -0
- package/dist/serveCommand-B_isw7q4.js +1647 -0
- package/dist/serveCommand-DOvbgRnQ.js +2 -0
- package/dist/serveEntry.js +5 -5
- package/dist/serverlessCommand-CfJZy6dS.js +482 -0
- package/dist/start-9LiUOfES.js +1087 -0
- package/dist/start-B-9Nsp-S.js +3 -0
- package/dist/startEntry.js +2 -2
- package/dist/staticCommand-Dr2M6tpU.js +304 -0
- package/dist/storageCommand-Co6NfLqN.js +42 -0
- package/dist/templates-De8IR5-c.js +102 -0
- package/dist/test-CI6iDsYc.js +115 -0
- package/dist/tracesCmd-CkEZQrtt.js +232 -0
- package/dist/tsconfigPaths-BWXBWgcl.js +107 -0
- package/dist/tsxLoader-EuXmSJ1K.js +51 -0
- package/dist/typecheckCommand-BlsWiCNq.js +61 -0
- package/dist/updateCommand-Bkptutss.js +585 -0
- package/dist/updateCommand-us1_hdIC.js +2 -0
- package/dist/{inspectMetrics-1xzTKAFx.js → webDev-CBYvPqQr.js} +975 -1559
- package/dist/webDev-Cg-fFiyd2.js +2 -0
- package/dist/webhookDiscovery-CrGAfhIG.js +2 -0
- package/dist/webhookDiscovery-D7VaeMlz.js +51 -0
- package/dist/webhooksCommand-CID96Rga.js +267 -0
- package/dist/workflowsCmd-D1VTmLMY.js +608 -0
- package/package.json +179 -17
- package/templates/AGENTS.core.md +58 -3
- package/templates/AGENTS.md +64 -7
- package/templates/agent-docs/_index.md +6 -4
- package/templates/agent-docs/_manifest.json +22 -5
- package/templates/agent-docs/ai.md +370 -0
- package/templates/agent-docs/authentication.md +265 -31
- package/templates/agent-docs/caching.md +6 -0
- package/templates/agent-docs/cli.md +794 -50
- package/templates/agent-docs/data.md +550 -11
- package/templates/agent-docs/database/migrations.md +174 -25
- package/templates/agent-docs/database/misc.md +156 -40
- package/templates/agent-docs/database/querying.md +19 -1
- package/templates/agent-docs/database/scaling.md +60 -0
- package/templates/agent-docs/database/schema.md +1 -0
- package/templates/agent-docs/database/seedsdialects.md +208 -19
- package/templates/agent-docs/database/transactions.md +68 -0
- package/templates/agent-docs/deployment.md +69 -3
- package/templates/agent-docs/introduction.md +87 -16
- package/templates/agent-docs/local-first-mobile.md +79 -4
- package/templates/agent-docs/multi-tenancy.md +95 -20
- package/templates/agent-docs/observability.md +58 -3
- package/templates/agent-docs/plugins/ai-flows.md +161 -2
- package/templates/agent-docs/plugins/analytics-postgres.md +1 -1
- package/templates/agent-docs/plugins/audit.md +37 -1
- package/templates/agent-docs/plugins/auth-social.md +143 -0
- package/templates/agent-docs/plugins/auth-workos.md +4 -2
- package/templates/agent-docs/plugins/auth.md +131 -6
- package/templates/agent-docs/plugins/billing.md +132 -15
- package/templates/agent-docs/plugins/cdc-out.md +46 -7
- package/templates/agent-docs/plugins/clickhouse.md +1 -1
- package/templates/agent-docs/plugins/duckdb.md +1 -1
- package/templates/agent-docs/plugins/flags.md +132 -0
- package/templates/agent-docs/plugins/governance.md +105 -7
- package/templates/agent-docs/plugins/multitenancy.md +9 -4
- package/templates/agent-docs/plugins/presence.md +13 -2
- package/templates/agent-docs/plugins/ratelimit.md +9 -0
- package/templates/agent-docs/plugins/search.md +157 -6
- package/templates/agent-docs/plugins/sso-saml.md +47 -8
- package/templates/agent-docs/plugins/webhooks.md +105 -0
- package/templates/agent-docs/plugins.md +150 -18
- package/templates/agent-docs/reference.md +60 -3
- package/templates/agent-docs/releases.md +1117 -0
- package/templates/agent-docs/routing.md +43 -25
- package/templates/agent-docs/scheduling.md +10 -0
- package/templates/agent-docs/schema-driven-ui.md +92 -12
- package/templates/agent-docs/security.md +426 -0
- package/templates/agent-docs/templates/apibackends.md +87 -18
- package/templates/agent-docs/templates/appshells.md +32 -14
- package/templates/agent-docs/templates/overview.md +13 -8
- package/templates/agent-docs/testing.md +211 -14
- package/templates/agent-docs/whats-new.md +1700 -104
- package/templates/agent-docs/workflows.md +130 -14
- package/templates/apps/api-ai/actions/summarize.action.ts +11 -0
- package/templates/apps/api-ai/package.json +8 -7
- package/templates/apps/api-auth/actions/me.action.ts +13 -0
- package/templates/apps/api-auth/package.json +9 -8
- package/templates/apps/api-backend/mutations/notes.create.mutation.ts +9 -0
- package/templates/apps/api-backend/package.json +12 -8
- package/templates/apps/api-backend/queries/notes.query.ts +30 -8
- package/templates/apps/api-backend-deactivation/actions/users.get.action.ts +14 -0
- package/templates/apps/api-backend-deactivation/mutations/users.create.mutation.ts +8 -0
- package/templates/apps/api-backend-deactivation/mutations/users.deactivate.mutation.ts +10 -0
- package/templates/apps/api-backend-deactivation/package.json +8 -7
- package/templates/apps/api-backend-mail/actions/sendWelcome.action.ts +17 -0
- package/templates/apps/api-backend-mail/mutations/notes.create.mutation.ts +9 -0
- package/templates/apps/api-backend-mail/package.json +9 -8
- package/templates/apps/api-backend-mail/queries/notes.query.ts +30 -8
- package/templates/apps/api-backend-mariadb/.env.example +14 -0
- package/templates/apps/api-backend-mariadb/mutations/notes.create.mutation.ts +9 -0
- package/templates/apps/api-backend-mariadb/package.json +10 -9
- package/templates/apps/api-backend-mariadb/queries/notes.query.ts +30 -8
- package/templates/apps/api-backend-sqlite/.env.example +14 -0
- package/templates/apps/api-backend-sqlite/mutations/notes.create.mutation.ts +9 -0
- package/templates/apps/api-backend-sqlite/package.json +9 -8
- package/templates/apps/api-backend-sqlite/queries/notes.query.ts +30 -8
- package/templates/apps/api-backend-storage/actions/uploadAvatar.action.ts +13 -0
- package/templates/apps/api-backend-storage/actions/uploadDocument.action.ts +12 -0
- package/templates/apps/api-backend-storage/mutations/notes.create.mutation.ts +9 -0
- package/templates/apps/api-backend-storage/package.json +9 -8
- package/templates/apps/api-backend-storage/queries/notes.query.ts +30 -8
- package/templates/apps/api-cms/actions/content.get.action.ts +7 -0
- package/templates/apps/api-cms/actions/content.types.action.ts +6 -0
- package/templates/apps/api-cms/actions/me.action.ts +13 -0
- package/templates/apps/api-cms/app.config.ts +19 -0
- package/templates/apps/api-cms/authz.ts +63 -0
- package/templates/apps/api-cms/mutations/content.publish.mutation.ts +10 -0
- package/templates/apps/api-cms/mutations/content.saveDraft.mutation.ts +10 -0
- package/templates/apps/api-cms/mutations/content.unpublish.mutation.ts +5 -0
- package/templates/apps/api-cms/package.json +11 -10
- package/templates/apps/api-cms/queries/content.list.query.ts +23 -7
- package/templates/apps/api-cms/tests/accessDecisions.test.ts +121 -0
- package/templates/apps/api-cms/tests/content.descriptors.test.ts +8 -4
- package/templates/apps/api-collab/mutations/documents.create.mutation.ts +8 -0
- package/templates/apps/api-collab/mutations/documents.setBody.mutation.ts +13 -0
- package/templates/apps/api-collab/package.json +9 -8
- package/templates/apps/api-collab/queries/documents.query.ts +19 -7
- package/templates/apps/api-data-advanced/package.json +9 -8
- package/templates/apps/api-data-advanced/queries/authors.withBooks.query.ts +12 -0
- package/templates/apps/api-data-advanced/queries/books.search.query.ts +9 -0
- package/templates/apps/api-durable/mutations/orders.approve.mutation.ts +17 -0
- package/templates/apps/api-durable/mutations/orders.place.mutation.ts +9 -0
- package/templates/apps/api-durable/package.json +9 -8
- package/templates/apps/api-feature-flags/actions/notes.export.action.ts +16 -0
- package/templates/apps/api-feature-flags/mutations/notes.create.mutation.ts +12 -0
- package/templates/apps/api-feature-flags/package.json +10 -9
- package/templates/apps/api-governance/README.md +30 -8
- package/templates/apps/api-governance/actions/profiles.get.action.server.ts +17 -1
- package/templates/apps/api-governance/actions/profiles.get.action.ts +29 -4
- package/templates/apps/api-governance/database/schema.ts +16 -4
- package/templates/apps/api-governance/mutations/profiles.create.mutation.ts +12 -0
- package/templates/apps/api-governance/package.json +9 -8
- package/templates/apps/api-kv/actions/sync.pull.action.ts +15 -0
- package/templates/apps/api-kv/actions/sync.reset.action.ts +13 -0
- package/templates/apps/api-kv/actions/sync.status.action.ts +7 -0
- package/templates/apps/api-kv/package.json +9 -8
- package/templates/apps/api-kv/queries/events.list.query.ts +19 -8
- package/templates/apps/api-moderation/mutations/comments.create.mutation.ts +11 -0
- package/templates/apps/api-moderation/mutations/posts.create.mutation.ts +13 -0
- package/templates/apps/api-moderation/package.json +9 -8
- package/templates/apps/api-observability/mutations/notes.create.mutation.ts +8 -0
- package/templates/apps/api-observability/package.json +9 -8
- package/templates/apps/api-observability/queries/notes.list.query.ts +13 -0
- package/templates/apps/api-ratelimit/mutations/notes.create.mutation.ts +14 -0
- package/templates/apps/api-ratelimit/package.json +9 -8
- package/templates/apps/api-rbac/package.json +9 -8
- package/templates/apps/api-rest/package.json +8 -7
- package/templates/apps/api-saas/mutations/projects.create.mutation.ts +13 -0
- package/templates/apps/api-saas/package.json +12 -11
- package/templates/apps/api-saas/queries/projects.list.query.ts +11 -0
- package/templates/apps/api-saas-starter/actions/me.action.ts +13 -0
- package/templates/apps/api-saas-starter/app.config.ts +19 -0
- package/templates/apps/api-saas-starter/authz.ts +75 -0
- package/templates/apps/api-saas-starter/mutations/invites.create.mutation.ts +10 -0
- package/templates/apps/api-saas-starter/mutations/projects.create.mutation.ts +9 -0
- package/templates/apps/api-saas-starter/package.json +15 -11
- package/templates/apps/api-saas-starter/queries/invites.list.query.ts +19 -8
- package/templates/apps/api-saas-starter/queries/projects.list.query.ts +18 -7
- package/templates/apps/api-saas-starter/tests/accessDecisions.test.ts +135 -0
- package/templates/apps/api-search/mutations/articles.create.mutation.ts +14 -0
- package/templates/apps/api-search/package.json +9 -8
- package/templates/apps/api-search/queries/articles.list.query.ts +21 -8
- package/templates/apps/api-status/README.md +10 -3
- package/templates/apps/api-status/app.config.ts +8 -3
- package/templates/apps/api-status/authz.ts +5 -3
- package/templates/apps/api-status/package.json +9 -8
- package/templates/apps/api-status/queries/components.list.query.ts +14 -6
- package/templates/apps/api-status/queries/incidents.live.query.ts +23 -10
- package/templates/apps/api-status/queries/updates.list.query.ts +16 -9
- package/templates/apps/api-status/tests/status.test.ts +9 -1
- package/templates/apps/api-versioning/actions/documents.asOf.action.ts +12 -0
- package/templates/apps/api-versioning/actions/documents.history.action.ts +13 -0
- package/templates/apps/api-versioning/mutations/documents.create.mutation.ts +9 -0
- package/templates/apps/api-versioning/mutations/documents.update.mutation.ts +12 -0
- package/templates/apps/api-versioning/package.json +9 -8
- package/templates/apps/api-webhooks/mutations/orders.fulfill.mutation.ts +16 -0
- package/templates/apps/api-webhooks/package.json +10 -9
- package/templates/apps/api-webhooks/queries/orders.list.query.ts +10 -0
- package/templates/apps/changelog/package.json +8 -6
- package/templates/apps/edge-functions/package.json +2 -2
- package/templates/apps/frontend-admin/package.json +10 -8
- package/templates/apps/frontend-admin/src/lib/admin.ts +20 -9
- package/templates/apps/frontend-admin/src/locales/de.ts +11 -1
- package/templates/apps/frontend-admin/src/locales/en.ts +13 -1
- package/templates/apps/frontend-admin/src/pages/admin/[entity]/page.tsx +65 -22
- package/templates/apps/frontend-admin/src/pages/admin/entity.test.tsx +130 -23
- package/templates/apps/frontend-admin/src/pages/admin/layout.tsx +3 -2
- package/templates/apps/frontend-admin/src/pages/admin/page.test.tsx +19 -2
- package/templates/apps/frontend-admin/src/pages/admin/page.tsx +9 -4
- package/templates/apps/frontend-app/app.config.ts +4 -3
- package/templates/apps/frontend-app/package.json +11 -8
- package/templates/apps/frontend-app/src/lib/api.ts +25 -0
- package/templates/apps/frontend-app/src/pages/page.test.tsx +130 -82
- package/templates/apps/frontend-app/src/pages/page.tsx +14 -18
- package/templates/apps/frontend-auth/package.json +10 -8
- package/templates/apps/frontend-blank/package.json +9 -7
- package/templates/apps/frontend-cms/package.json +11 -9
- package/templates/apps/frontend-collab/package.json +12 -9
- package/templates/apps/frontend-collab/src/pages/page.test.tsx +122 -78
- package/templates/apps/frontend-contact/package.json +9 -7
- package/templates/apps/frontend-dashboard/package.json +9 -7
- package/templates/apps/frontend-docs/package.json +9 -7
- package/templates/apps/frontend-i18n/package.json +8 -6
- package/templates/apps/frontend-landing/package.json +9 -7
- package/templates/apps/frontend-portal/package.json +10 -8
- package/templates/apps/frontend-saas/app.config.ts +10 -6
- package/templates/apps/frontend-saas/package.json +10 -8
- package/templates/apps/frontend-saas/src/lib/api.ts +27 -32
- package/templates/apps/frontend-saas/src/pages/dashboard/billing/page.tsx +7 -8
- package/templates/apps/frontend-saas/src/pages/dashboard/page.test.tsx +27 -3
- package/templates/apps/frontend-saas/src/pages/dashboard/page.tsx +4 -4
- package/templates/apps/frontend-saas/src/pages/dashboard/team/page.tsx +3 -4
- package/templates/apps/frontend-spa/package.json +9 -7
- package/templates/apps/frontend-ssr/package.json +9 -7
- package/templates/apps/frontend-ssr-api/package.json +10 -8
- package/templates/apps/frontend-static-blog/package.json +8 -6
- package/templates/apps/frontend-status/package.json +10 -8
- package/templates/apps/mobile-app/README.md +1 -0
- package/templates/apps/mobile-app/package.json +4 -2
- package/templates/apps/mobile-app/src/app/index.tsx +22 -12
- package/templates/apps/mobile-app/src/app/orders/[id].tsx +1 -1
- package/templates/apps/mobile-app/src/lib/api.ts +34 -0
- package/templates/apps/mobile-app/voltro.mobile.ts +4 -2
- package/templates/baselines/bare/.env.example +14 -0
- package/templates/baselines/bare/baseline.json +4 -4
- package/templates/baselines/compose/.env.example +14 -0
- package/templates/baselines/compose/README.md +1 -1
- package/templates/baselines/compose/baseline.json +5 -5
- package/templates/baselines/compose-mariadb/.env.example +14 -0
- package/templates/baselines/compose-mariadb/README.md +1 -1
- package/templates/baselines/compose-mariadb/baseline.json +5 -5
- package/templates/baselines/helm/.env.example +14 -0
- package/templates/baselines/helm/baseline.json +4 -4
- package/dist/apiBuild-C-x9YacA.js +0 -2
- package/dist/checkCommand-DRovTKza.js +0 -2
- package/dist/commands-CJfepbm4.js +0 -11541
- package/dist/dbCommand-b1gum4td.js +0 -2
- package/dist/dev-iiMtlkfs.js +0 -3
- package/dist/devActivity-BhIu6ncs.js +0 -159
- package/dist/frameworkTableAssembly-D-EebUQX.js +0 -2
- package/dist/inspect-mmBuRXmy.js +0 -2
- package/dist/manifestBuild-Dj8Jjoto.js +0 -2
- package/dist/seedRunner-Bqxgp7HZ.js +0 -230
- package/dist/serveCommand-DdaM4Hup.js +0 -1608
- package/dist/start-C0koT0UO.js +0 -1084
- /package/templates/apps/api-ai/actions/{summarize.action.server.tsx → summarize.action.server.ts} +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
//#region src/connectionConfig.ts
|
|
2
|
+
var e = () => {
|
|
3
|
+
let e = t(process.env.DB_ACQUIRE_TIMEOUT_MS), n = t(process.env.DB_ACQUIRE_QUEUE_LIMIT);
|
|
4
|
+
return {
|
|
5
|
+
...e === void 0 ? {} : { acquireTimeoutMs: e },
|
|
6
|
+
...n === void 0 ? {} : { acquireQueueLimit: n }
|
|
7
|
+
};
|
|
8
|
+
}, t = (e) => {
|
|
9
|
+
if (e === void 0 || e === "") return;
|
|
10
|
+
let t = Number(e);
|
|
11
|
+
return Number.isInteger(t) && t >= 0 ? t : void 0;
|
|
12
|
+
}, n = () => {
|
|
13
|
+
let e = process.env.DB_STATEMENT_TIMEOUT_MS;
|
|
14
|
+
if (e === void 0 || e === "") return;
|
|
15
|
+
let t = Number(e);
|
|
16
|
+
return Number.isInteger(t) && t > 0 ? t : void 0;
|
|
17
|
+
}, r = () => {
|
|
18
|
+
let e = process.env.PG_SSL;
|
|
19
|
+
if (!(e === void 0 || e === "")) {
|
|
20
|
+
if (e === "require") return !0;
|
|
21
|
+
if (e === "disable") return !1;
|
|
22
|
+
throw Error(`PG_SSL '${e}' is not supported — use 'require' (TLS without certificate verification) or 'disable' (plaintext).`);
|
|
23
|
+
}
|
|
24
|
+
}, i = () => {
|
|
25
|
+
let e = process.env.DB_MAX_CONNECTIONS ?? process.env.PG_MAX_CONNECTIONS;
|
|
26
|
+
if (e === void 0 || e === "") return;
|
|
27
|
+
let t = Number(e);
|
|
28
|
+
return Number.isInteger(t) && t > 0 ? t : void 0;
|
|
29
|
+
}, a = () => !process.env.DB_URL && !process.env.DB_PRIMARY_URL && !process.env.DB_DIRECT_URL && !process.env.DB_MIGRATE_URL && !process.env.DB_HOST && !process.env.PG_HOST, o = (t) => {
|
|
30
|
+
let a = i(), o = process.env.DB_SCHEMA, s = r(), c = t === "runtime" ? n() : void 0, l = {
|
|
31
|
+
...a === void 0 ? {} : { maxConnections: a },
|
|
32
|
+
...s === void 0 ? {} : { ssl: s },
|
|
33
|
+
...o !== void 0 && o.length > 0 ? { schema: o } : {},
|
|
34
|
+
...c === void 0 ? {} : { statementTimeoutMs: c },
|
|
35
|
+
...e()
|
|
36
|
+
}, u = t === "migration" ? process.env.DB_DIRECT_URL ?? process.env.DB_MIGRATE_URL ?? process.env.DB_URL ?? process.env.DB_PRIMARY_URL : process.env.DB_URL ?? process.env.DB_PRIMARY_URL;
|
|
37
|
+
return u ? {
|
|
38
|
+
url: u,
|
|
39
|
+
...l
|
|
40
|
+
} : {
|
|
41
|
+
host: process.env.DB_HOST ?? process.env.PG_HOST ?? "localhost",
|
|
42
|
+
port: Number(process.env.DB_PORT ?? process.env.PG_PORT ?? 5432),
|
|
43
|
+
username: process.env.DB_USER ?? process.env.PG_USER ?? "app",
|
|
44
|
+
password: process.env.DB_PASSWORD ?? process.env.PG_PASSWORD ?? "app",
|
|
45
|
+
database: process.env.DB_DATABASE ?? process.env.PG_DATABASE ?? "app",
|
|
46
|
+
...l
|
|
47
|
+
};
|
|
48
|
+
}, s = (e, t) => ({
|
|
49
|
+
...e,
|
|
50
|
+
url: t
|
|
51
|
+
}), c = () => {
|
|
52
|
+
let e = o("runtime"), t = e.ssl === !0 ? { ssl: { rejectUnauthorized: !1 } } : {};
|
|
53
|
+
return e.url === void 0 ? {
|
|
54
|
+
host: e.host ?? "localhost",
|
|
55
|
+
port: e.port ?? 5432,
|
|
56
|
+
user: e.username ?? "app",
|
|
57
|
+
password: e.password ?? "app",
|
|
58
|
+
database: e.database ?? "app",
|
|
59
|
+
...t
|
|
60
|
+
} : {
|
|
61
|
+
connectionString: e.url,
|
|
62
|
+
...t
|
|
63
|
+
};
|
|
64
|
+
}, l = () => !a();
|
|
65
|
+
//#endregion
|
|
66
|
+
export { o as a, s as i, i as n, c as o, a as r, l as t };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { d as e } from "./dev-CerMd0mW.js";
|
|
2
|
+
import { P as t, j as n } from "./webDev-CBYvPqQr.js";
|
|
3
|
+
import { t as r } from "./start-9LiUOfES.js";
|
|
4
|
+
import { join as i } from "node:path";
|
|
5
|
+
import { existsSync as a } from "node:fs";
|
|
6
|
+
import { createLogger as o } from "@voltro/logger";
|
|
7
|
+
//#region src/dashboardCommand.ts
|
|
8
|
+
var s = o({ scope: "voltro:dashboard" }), c = (e, t) => {
|
|
9
|
+
let n = e.indexOf(t);
|
|
10
|
+
return n >= 0 ? e[n + 1] : void 0;
|
|
11
|
+
}, l = async (o) => {
|
|
12
|
+
process.env[n] = "1";
|
|
13
|
+
let l = c(o, "--port") ?? process.env.VOLTRO_DASHBOARD_PORT ?? "5179";
|
|
14
|
+
process.env.VOLTRO_DASHBOARD_PORT = l;
|
|
15
|
+
let u = t(process.cwd());
|
|
16
|
+
if (!u) return s.error("dashboard app not found. Install it with `pnpm add @voltro/dashboard`, or set VOLTRO_DASHBOARD_PATH to a dashboard app directory."), 1;
|
|
17
|
+
let d = a(i(u, ".framework", "dist", "index.html"));
|
|
18
|
+
return s.info(`serving the Voltro dashboard on :${l}`, {
|
|
19
|
+
from: u,
|
|
20
|
+
mode: d ? "start" : "dev",
|
|
21
|
+
apps: process.env.VOLTRO_DASHBOARD_APPS ? "configured" : "none (set VOLTRO_DASHBOARD_APPS)"
|
|
22
|
+
}), d ? r([u]) : e([u]);
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { l as runDashboardCommand };
|
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
import { t as e } from "./cliError-BmdYnghb.js";
|
|
2
|
+
import { c as t, i as n, o as r } from "./dev-CerMd0mW.js";
|
|
3
|
+
import { n as i, t as a } from "./cliArgs-D4p8n7EE.js";
|
|
4
|
+
import { r as o } from "./dialectDriver-CgXnDfec.js";
|
|
5
|
+
import { t as s } from "./dataProfile-dW-PsfLB.js";
|
|
6
|
+
import { o as c, t as l } from "./inspectFetch-Cm8_wVvp.js";
|
|
7
|
+
import { r as u } from "./dbCommand-B6X0FZbq.js";
|
|
8
|
+
import { createLogger as d } from "@voltro/logger";
|
|
9
|
+
import { Effect as f, Stream as p } from "effect";
|
|
10
|
+
import { SqlClient as m } from "@effect/sql";
|
|
11
|
+
import { declaredSnapshot as h, fingerprintSchema as g, introspectSchema as _ } from "@voltro/database/sql";
|
|
12
|
+
import { connectionIdentity as v, normaliseTarget as y, sameDatabase as b, streamTable as x } from "@voltro/database";
|
|
13
|
+
import { STORAGE_REFS_TABLE as S, resolveStorageProvider as C } from "@voltro/plugin-storage";
|
|
14
|
+
import { assessLiveImport as ee, backupArtifactName as w, backupCommand as te, classificationFromSnapshot as ne, decryptStream as T, encryptStream as re, packBundle as E, peekBundle as D, previewMasking as ie, restoreCommand as O, runExport as k, runImport as A, runNativeStep as j, storageAssetSink as M, storageAssetSource as ae, storageBlobSink as oe, storageBlobSource as se, unpackBundle as ce, unpackBundleToDir as N } from "@voltro/data-transfer";
|
|
15
|
+
//#region src/backupStamp.ts
|
|
16
|
+
var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
17
|
+
stampVersion: 1,
|
|
18
|
+
dialect: e.dialect,
|
|
19
|
+
schemaFingerprint: e.schemaFingerprint,
|
|
20
|
+
voltroVersion: e.voltroVersion,
|
|
21
|
+
createdAt: e.createdAt
|
|
22
|
+
}), F = (e) => {
|
|
23
|
+
let t;
|
|
24
|
+
try {
|
|
25
|
+
t = JSON.parse(e);
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
if (typeof t != "object" || !t) return null;
|
|
30
|
+
let n = t;
|
|
31
|
+
if (n.stampVersion !== 1 || typeof n.dialect != "string" || typeof n.voltroVersion != "string" || typeof n.createdAt != "string") return null;
|
|
32
|
+
let r = n.schemaFingerprint;
|
|
33
|
+
return r !== null && typeof r != "string" ? null : {
|
|
34
|
+
stampVersion: 1,
|
|
35
|
+
dialect: n.dialect,
|
|
36
|
+
schemaFingerprint: r,
|
|
37
|
+
voltroVersion: n.voltroVersion,
|
|
38
|
+
createdAt: n.createdAt
|
|
39
|
+
};
|
|
40
|
+
}, ue = (e) => {
|
|
41
|
+
let { stamp: t, currentDialect: n, currentFingerprint: r } = e;
|
|
42
|
+
if (t === null) return {
|
|
43
|
+
warn: `no ${P} beside the dump — an older/handmade backup. Cannot verify dialect or schema version; make sure this dump is a ${n} dump.`,
|
|
44
|
+
info: []
|
|
45
|
+
};
|
|
46
|
+
let i = [`backup produced by @voltro/cli ${t.voltroVersion} at ${t.createdAt}`, `schema fingerprint: ${t.schemaFingerprint ?? "<none recorded>"}`];
|
|
47
|
+
return t.dialect === n ? t.schemaFingerprint !== null && r !== null && t.schemaFingerprint !== r ? {
|
|
48
|
+
warn: `schema skew — the backup's schema (${t.schemaFingerprint.slice(0, 12)}) differs from what this code declares (${r.slice(0, 12)}). Run \`voltro db apply\` after the restore, or the app may boot against a schema it doesn't understand.`,
|
|
49
|
+
info: i
|
|
50
|
+
} : { info: i } : {
|
|
51
|
+
refuse: `dialect mismatch — backup is a ${t.dialect} dump, but DB_DIALECT is ${n}. A cross-dialect restore is never valid.`,
|
|
52
|
+
info: i
|
|
53
|
+
};
|
|
54
|
+
}, I = (e) => {
|
|
55
|
+
try {
|
|
56
|
+
let t = new URL(e), n = t.pathname.replace(/^\//, "");
|
|
57
|
+
return `${t.hostname.toLowerCase()}:${t.port || "(default)"}/${n}`;
|
|
58
|
+
} catch {
|
|
59
|
+
return e.trim();
|
|
60
|
+
}
|
|
61
|
+
}, de = (e) => {
|
|
62
|
+
let t = e.flagUrl ?? e.envUrl;
|
|
63
|
+
if (t === void 0 || t.trim() === "") return {
|
|
64
|
+
ok: !1,
|
|
65
|
+
error: "no drill target — pass `--drill-url <url>` or set `DRILL_DB_URL`. The drill restores into a THROWAWAY database (never the live one), so it needs its own connection."
|
|
66
|
+
};
|
|
67
|
+
let n = I(t);
|
|
68
|
+
return e.liveKeys.some((e) => e === n) ? {
|
|
69
|
+
ok: !1,
|
|
70
|
+
error: `drill target (${n}) is the LIVE database — a restore drill must target a throwaway DB, never production. It would --clean and overwrite it.`
|
|
71
|
+
} : {
|
|
72
|
+
ok: !0,
|
|
73
|
+
url: t
|
|
74
|
+
};
|
|
75
|
+
}, fe = (e) => {
|
|
76
|
+
let { stampFingerprint: t, restoredFingerprint: n, restoredTableCount: r } = e;
|
|
77
|
+
return r === 0 ? {
|
|
78
|
+
pass: !1,
|
|
79
|
+
lines: ["FAIL — the restore produced ZERO tables. The dump is empty or unreadable; this backup would NOT recover your app."]
|
|
80
|
+
} : t !== null && n !== null && t !== n ? {
|
|
81
|
+
pass: !1,
|
|
82
|
+
lines: [`FAIL — restored ${r} table(s), but the schema fingerprint (${n.slice(0, 12)}) does NOT match the backup's stamp (${t.slice(0, 12)}).`, "The restore did not reproduce the schema that was backed up — the artifact is inconsistent."]
|
|
83
|
+
} : t === null || n === null ? {
|
|
84
|
+
pass: !0,
|
|
85
|
+
lines: [`PASS (partial) — restored ${r} table(s) into the throwaway DB.`, "No stamped fingerprint to cross-check the schema shape (older/hand-made backup) — the bytes restore, but the shape was not verified."]
|
|
86
|
+
} : {
|
|
87
|
+
pass: !0,
|
|
88
|
+
lines: [`PASS — restored ${r} table(s); schema fingerprint matches the backup stamp (${n.slice(0, 12)}).`]
|
|
89
|
+
};
|
|
90
|
+
}, L = d({ scope: "voltro:data" }), pe = async () => {
|
|
91
|
+
try {
|
|
92
|
+
let { createRequire: e } = await import("node:module"), { join: t } = await import("node:path"), { readFileSync: n } = await import("node:fs"), r = e(t(process.cwd(), "package.json")).resolve("@voltro/cli/package.json");
|
|
93
|
+
return JSON.parse(n(r, "utf8")).version ?? "unknown";
|
|
94
|
+
} catch {
|
|
95
|
+
return "unknown";
|
|
96
|
+
}
|
|
97
|
+
}, R = async (e) => {
|
|
98
|
+
try {
|
|
99
|
+
return g(await K(e));
|
|
100
|
+
} catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}, z = (e) => {
|
|
104
|
+
if (e.event !== "done") return;
|
|
105
|
+
let t = e.total === void 0 ? "" : ` / ${e.total}`;
|
|
106
|
+
L.info(`${e.phase} [${e.index + 1}/${e.tableCount}] ${e.table}`, { rows: `${e.rowsDone}${t}` });
|
|
107
|
+
}, B = async (e) => {
|
|
108
|
+
let t = (e) => e?.meta?.databaseId;
|
|
109
|
+
if (e) {
|
|
110
|
+
let n = await l({
|
|
111
|
+
name: "target",
|
|
112
|
+
url: e
|
|
113
|
+
}, "/_voltro/inspect/app");
|
|
114
|
+
if (n.kind === "ok") return {
|
|
115
|
+
label: e,
|
|
116
|
+
databaseId: t(n.data)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
for (let e of await c()) {
|
|
120
|
+
let n = await l(e, "/_voltro/inspect/app");
|
|
121
|
+
if (n.kind === "ok") return {
|
|
122
|
+
label: `${e.name} (${e.url})`,
|
|
123
|
+
databaseId: t(n.data)
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}, V = async (e) => {
|
|
128
|
+
let t = e.includes("--allow-live"), n = t ? null : await B(H(e, "--api-url")), i = v({
|
|
129
|
+
dialect: W(),
|
|
130
|
+
...r()
|
|
131
|
+
}), a = y({
|
|
132
|
+
dialect: W(),
|
|
133
|
+
...r()
|
|
134
|
+
}), { refuse: o, message: s } = ee({
|
|
135
|
+
liveInstance: n?.label ?? null,
|
|
136
|
+
allowLive: t,
|
|
137
|
+
sameTarget: b(i, n?.databaseId),
|
|
138
|
+
...a === void 0 ? {} : { targetLabel: `${a.host}:${a.port}/${a.database}` }
|
|
139
|
+
});
|
|
140
|
+
return o ? (L.error(s ?? "refusing: live instance detected"), !1) : !0;
|
|
141
|
+
}, H = i, me = [
|
|
142
|
+
"--api-url",
|
|
143
|
+
"--bundle-key",
|
|
144
|
+
"--compression",
|
|
145
|
+
"--consistency",
|
|
146
|
+
"--drill-url",
|
|
147
|
+
"--mode",
|
|
148
|
+
"--on-conflict",
|
|
149
|
+
"--passphrase",
|
|
150
|
+
"--profile",
|
|
151
|
+
"--tables",
|
|
152
|
+
"--target",
|
|
153
|
+
"--tenant",
|
|
154
|
+
"--token"
|
|
155
|
+
], U = (e) => a(e, me), W = () => {
|
|
156
|
+
let t = (process.env.DB_DIALECT ?? "postgres").toLowerCase();
|
|
157
|
+
if (t === "memory") throw new e("voltro data: requires a real dialect, not DB_DIALECT=memory.");
|
|
158
|
+
return t;
|
|
159
|
+
}, G = async (e, t) => {
|
|
160
|
+
let n = (await o(e)).makeSqlLayer(t);
|
|
161
|
+
return f.runPromise(m.SqlClient.pipe(f.flatMap(_), f.provide(n)));
|
|
162
|
+
}, K = (e) => G(e, r()), he = () => {
|
|
163
|
+
let e = r(), t = [];
|
|
164
|
+
return e.url && t.push(I(e.url)), (e.host || e.database) && t.push(`${(e.host ?? "localhost").toLowerCase()}:${e.port ?? "(default)"}/${e.database ?? ""}`), t;
|
|
165
|
+
}, q = async () => {
|
|
166
|
+
let r = await t(process.cwd());
|
|
167
|
+
if (!r) throw new e("voltro data: no app.config.ts found in the current directory.");
|
|
168
|
+
let i = await n(r, void 0), a = W();
|
|
169
|
+
return {
|
|
170
|
+
store: i,
|
|
171
|
+
snapshot: await K(a),
|
|
172
|
+
dialect: a
|
|
173
|
+
};
|
|
174
|
+
}, J = (e) => x(e, {
|
|
175
|
+
table: S,
|
|
176
|
+
chunkSize: 500
|
|
177
|
+
}).pipe(p.map((e) => ({
|
|
178
|
+
key: String(e.key),
|
|
179
|
+
contentType: String(e.contentType ?? "application/octet-stream"),
|
|
180
|
+
size: Number(e.size ?? 0)
|
|
181
|
+
}))), Y = (e) => !!e && e.endsWith(".vbundle"), X = (e) => H(e, "--passphrase") ?? process.env.VOLTRO_BUNDLE_KEY, ge = (e) => e.includes("--encrypt") || H(e, "--passphrase") !== void 0 || process.env.VOLTRO_BUNDLE_KEY !== void 0, _e = async (e, t) => {
|
|
182
|
+
let { createWriteStream: n } = await import("node:fs"), { pipeline: r } = await import("node:stream/promises"), { Readable: i } = await import("node:stream");
|
|
183
|
+
await r(i.from(e), n(t));
|
|
184
|
+
}, Z = (e) => ({ async *[Symbol.asyncIterator]() {
|
|
185
|
+
let { createReadStream: t } = await import("node:fs");
|
|
186
|
+
for await (let n of t(e)) yield n instanceof Uint8Array ? n : new Uint8Array(n);
|
|
187
|
+
} }), ve = (e) => {
|
|
188
|
+
let t = H(e, "--tenant");
|
|
189
|
+
if (t) return {
|
|
190
|
+
kind: "tenant",
|
|
191
|
+
tenantId: t
|
|
192
|
+
};
|
|
193
|
+
let n = H(e, "--tables");
|
|
194
|
+
return n ? {
|
|
195
|
+
kind: "tables",
|
|
196
|
+
tables: n.split(",").map((e) => e.trim()).filter(Boolean)
|
|
197
|
+
} : { kind: "all" };
|
|
198
|
+
}, ye = async () => ne(h(await u(process.cwd()))), be = "voltro/tenant", xe = async () => {
|
|
199
|
+
let e = (await u(process.cwd())).filter((e) => (e.appliedMixins ?? []).some((e) => e.id === be)).map((e) => e.tableName);
|
|
200
|
+
return e.length > 0 ? e : void 0;
|
|
201
|
+
}, Q = (e) => {
|
|
202
|
+
for (let t of e.tables) if (t.samples.length !== 0) {
|
|
203
|
+
console.log(`\n ${t.table}`);
|
|
204
|
+
for (let e of t.samples) console.log(` ${e.column} [${e.action}] ${JSON.stringify(e.before)} → ${JSON.stringify(e.after)}`);
|
|
205
|
+
}
|
|
206
|
+
if (e.leaks.length > 0) {
|
|
207
|
+
console.log("\n ⚠ possible leaks in KEPT columns:");
|
|
208
|
+
for (let t of e.leaks) console.log(` ${t.table}.${t.column} looks like ${t.pattern}: ${JSON.stringify(t.sample)}`);
|
|
209
|
+
}
|
|
210
|
+
if (e.unclassified.length > 0) {
|
|
211
|
+
console.log("\n ✗ unclassified (would BLOCK a real export — add .sensitive()/.safe() or a policy override):");
|
|
212
|
+
for (let t of e.unclassified) console.log(` ${t}`);
|
|
213
|
+
} else console.log("\n ✓ every exported column is classified — safe to run.");
|
|
214
|
+
}, Se = async (e) => {
|
|
215
|
+
let t = H(e, "--target") === "api", n = H(e, "--bundle-key"), r = U(e);
|
|
216
|
+
if (!r && !(t && n)) return L.error("usage: voltro data export <outDir> [--target direct|api] [--api-url <url>] [--token <secret>] [--profile <name>] [--tenant <id>] [--tables a,b] [--bundle-key <storage-key>] [--assets] [--compression zstd|gzip|none] [--consistency live|snapshot] [--dry-run]"), 1;
|
|
217
|
+
if (t) {
|
|
218
|
+
let t = H(e, "--api-url");
|
|
219
|
+
if (!t) return L.error("--target api requires --api-url <url> (the running instance)"), 1;
|
|
220
|
+
let i = H(e, "--token") ?? process.env.VOLTRO_DATA_TRANSFER_SECRET;
|
|
221
|
+
if (!i) return L.error("--target api requires --token <secret> (or VOLTRO_DATA_TRANSFER_SECRET) matching the instance secret"), 1;
|
|
222
|
+
let a = H(e, "--tables"), o = {
|
|
223
|
+
...H(e, "--profile") ? { profile: H(e, "--profile") } : {},
|
|
224
|
+
...H(e, "--tenant") ? { tenant: H(e, "--tenant") } : {},
|
|
225
|
+
...a ? { tables: a.split(",").map((e) => e.trim()).filter(Boolean) } : {},
|
|
226
|
+
...H(e, "--consistency") === "snapshot" ? { consistency: "snapshot" } : {},
|
|
227
|
+
...H(e, "--compression") ? { compression: H(e, "--compression") } : {},
|
|
228
|
+
...e.includes("--assets") ? { assets: !0 } : {},
|
|
229
|
+
...n ? { bundleKey: n } : {}
|
|
230
|
+
}, s = await fetch(`${t.replace(/\/+$/, "")}/_voltro/admin/export`, {
|
|
231
|
+
method: "POST",
|
|
232
|
+
headers: {
|
|
233
|
+
"content-type": "application/json",
|
|
234
|
+
authorization: `Bearer ${i}`
|
|
235
|
+
},
|
|
236
|
+
body: JSON.stringify(o)
|
|
237
|
+
});
|
|
238
|
+
if (!s.ok) return L.error(`api export failed: HTTP ${s.status} — ${await s.text()}`), 1;
|
|
239
|
+
if (n) return L.info("api export complete (pushed to storage)", {
|
|
240
|
+
via: t,
|
|
241
|
+
...await s.json()
|
|
242
|
+
}), 0;
|
|
243
|
+
let { resolve: c } = await import("node:path"), l = new Uint8Array(await s.arrayBuffer());
|
|
244
|
+
return await N((async function* () {
|
|
245
|
+
yield l;
|
|
246
|
+
})(), c(process.cwd(), r)), L.info("api export complete (downloaded from the running instance)", {
|
|
247
|
+
outDir: r,
|
|
248
|
+
tables: s.headers.get("x-export-tables") ?? void 0,
|
|
249
|
+
rows: s.headers.get("x-export-rows") ?? void 0,
|
|
250
|
+
masked: s.headers.get("x-export-masked") ?? void 0
|
|
251
|
+
}), 0;
|
|
252
|
+
}
|
|
253
|
+
if (!r) return L.error("a <outDir> is required for a direct export"), 1;
|
|
254
|
+
let i = H(e, "--profile"), a = i ? await s(i) : {}, { store: o, snapshot: c, dialect: l } = await q(), u = e.includes("--assets") || a.assets === !0, d = u ? C({}) : void 0, p = H(e, "--compression") ?? a.compression, m = H(e, "--consistency") === "snapshot" ? "snapshot" : a.consistency ?? "live", h = a.masking, g = a.subset, _ = a.scope ?? ve(e), v = h ? await ye() : void 0, y = _.kind === "tenant" ? await xe() : void 0, b = y ? { tenantTables: y } : {};
|
|
255
|
+
if (e.includes("--dry-run")) {
|
|
256
|
+
if (!h) return L.error("--dry-run previews masking, but the profile sets no masking policy"), 1;
|
|
257
|
+
let e = await f.runPromise(ie({
|
|
258
|
+
store: o,
|
|
259
|
+
snapshot: c,
|
|
260
|
+
masking: h,
|
|
261
|
+
...v ? { classification: v } : {},
|
|
262
|
+
...g ? {} : {
|
|
263
|
+
scope: _,
|
|
264
|
+
...b
|
|
265
|
+
}
|
|
266
|
+
}));
|
|
267
|
+
return Q(e), +(e.unclassified.length > 0);
|
|
268
|
+
}
|
|
269
|
+
if (Y(r)) {
|
|
270
|
+
let t = await import("node:os"), n = await import("node:fs/promises"), { resolve: i, join: a } = await import("node:path"), s = await n.mkdtemp(a(t.tmpdir(), "voltro-export-"));
|
|
271
|
+
try {
|
|
272
|
+
let t = await f.runPromise(k({
|
|
273
|
+
store: o,
|
|
274
|
+
snapshot: c,
|
|
275
|
+
dialect: l,
|
|
276
|
+
outDir: s,
|
|
277
|
+
...g ? { subset: g } : {
|
|
278
|
+
scope: _,
|
|
279
|
+
...b
|
|
280
|
+
},
|
|
281
|
+
consistency: m,
|
|
282
|
+
...p ? { compression: p } : {},
|
|
283
|
+
...h ? { masking: h } : {},
|
|
284
|
+
...v ? { classification: v } : {},
|
|
285
|
+
onProgress: z
|
|
286
|
+
})), n = E({
|
|
287
|
+
dir: s,
|
|
288
|
+
...d ? { blobs: se(d, () => J(o)) } : {}
|
|
289
|
+
}), a = ge(e);
|
|
290
|
+
if (a) {
|
|
291
|
+
let t = X(e);
|
|
292
|
+
if (!t) return L.error("--encrypt requires --passphrase <p> or VOLTRO_BUNDLE_KEY (a dedicated key, NOT the transfer secret)"), 1;
|
|
293
|
+
n = re(n, t);
|
|
294
|
+
}
|
|
295
|
+
return await _e(n, i(process.cwd(), r)), L.info("export complete (single file)", {
|
|
296
|
+
file: r,
|
|
297
|
+
encrypted: a,
|
|
298
|
+
assets: u,
|
|
299
|
+
tables: t.tables.length,
|
|
300
|
+
rows: t.tables.reduce((e, t) => e + t.rowCount, 0)
|
|
301
|
+
}), 0;
|
|
302
|
+
} finally {
|
|
303
|
+
await n.rm(s, {
|
|
304
|
+
recursive: !0,
|
|
305
|
+
force: !0
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
let x = await f.runPromise(k({
|
|
310
|
+
store: o,
|
|
311
|
+
snapshot: c,
|
|
312
|
+
dialect: l,
|
|
313
|
+
outDir: r,
|
|
314
|
+
...g ? { subset: g } : {
|
|
315
|
+
scope: _,
|
|
316
|
+
...b
|
|
317
|
+
},
|
|
318
|
+
consistency: m,
|
|
319
|
+
...p ? { compression: p } : {},
|
|
320
|
+
...h ? { masking: h } : {},
|
|
321
|
+
...v ? { classification: v } : {},
|
|
322
|
+
...d ? { assets: ae(d, () => J(o)) } : {},
|
|
323
|
+
onProgress: z
|
|
324
|
+
}));
|
|
325
|
+
return L.info("export complete", {
|
|
326
|
+
outDir: r,
|
|
327
|
+
tables: x.tables.length,
|
|
328
|
+
rows: x.tables.reduce((e, t) => e + t.rowCount, 0),
|
|
329
|
+
assets: x.assets.count,
|
|
330
|
+
compression: x.compression,
|
|
331
|
+
...x.masking ? { maskedColumns: x.masking.transformed.length } : {}
|
|
332
|
+
}), 0;
|
|
333
|
+
}, Ce = async (e) => {
|
|
334
|
+
let t = H(e, "--target") === "api", n = H(e, "--bundle-key"), r = U(e);
|
|
335
|
+
if (!r && !(t && n)) return L.error("usage: voltro data import <bundleDir> [--target direct|api] [--api-url <url>] [--token <secret>] [--bundle-key <storage-key>] [--mode upsert|append|replace] [--on-conflict skip|fail] [--atomic] [--assets] [--no-verify] [--force] [--allow-live] (--force: import despite schema drift AND cross-dialect warnings)"), 1;
|
|
336
|
+
let i = H(e, "--mode") ?? "upsert", a = H(e, "--on-conflict") ?? "skip";
|
|
337
|
+
if (t) {
|
|
338
|
+
let t = H(e, "--api-url");
|
|
339
|
+
if (!t) return L.error("--target api requires --api-url <url> (the running instance)"), 1;
|
|
340
|
+
let o = H(e, "--token") ?? process.env.VOLTRO_DATA_TRANSFER_SECRET;
|
|
341
|
+
if (!o) return L.error("--target api requires --token <secret> (or VOLTRO_DATA_TRANSFER_SECRET) matching the instance secret"), 1;
|
|
342
|
+
let s = {
|
|
343
|
+
authorization: `Bearer ${o}`,
|
|
344
|
+
"x-import-mode": i,
|
|
345
|
+
"x-import-on-conflict": a,
|
|
346
|
+
...e.includes("--atomic") ? { "x-import-atomic": "1" } : {},
|
|
347
|
+
...e.includes("--force") ? { "x-import-force": "1" } : {}
|
|
348
|
+
}, { resolve: c } = await import("node:path"), l;
|
|
349
|
+
if (n) s["content-type"] = "application/json", l = JSON.stringify({ bundleKey: n });
|
|
350
|
+
else if (Y(r)) {
|
|
351
|
+
let t = Z(c(process.cwd(), r)), n = X(e);
|
|
352
|
+
n && (t = T(t, n));
|
|
353
|
+
let i = [];
|
|
354
|
+
for await (let e of t) i.push(Buffer.from(e));
|
|
355
|
+
s["content-type"] = "application/octet-stream", l = Buffer.concat(i);
|
|
356
|
+
} else {
|
|
357
|
+
await (await import("node:fs/promises")).access(c(process.cwd(), r, "assets", "index.ndjson")).then(() => !0, () => !1) && L.warn("this directory bundle has assets; --target api uploads DATA ONLY. Pack a single-file `.vbundle` (voltro data export <name>.vbundle --assets) to transfer assets over the API.");
|
|
358
|
+
let e = [];
|
|
359
|
+
for await (let t of E({ dir: c(process.cwd(), r) })) e.push(Buffer.from(t));
|
|
360
|
+
s["content-type"] = "application/octet-stream", l = Buffer.concat(e);
|
|
361
|
+
}
|
|
362
|
+
let u = await fetch(`${t.replace(/\/+$/, "")}/_voltro/admin/import`, {
|
|
363
|
+
method: "POST",
|
|
364
|
+
body: l,
|
|
365
|
+
headers: s
|
|
366
|
+
});
|
|
367
|
+
return u.ok ? (L.info("api import complete (imported by the running instance)", {
|
|
368
|
+
via: t,
|
|
369
|
+
...await u.json()
|
|
370
|
+
}), 0) : (L.error(`api import failed: HTTP ${u.status} — ${await u.text()}`), 1);
|
|
371
|
+
}
|
|
372
|
+
if (!r) return L.error("a <bundleDir> is required for a direct import"), 1;
|
|
373
|
+
if (!await V(e)) return 1;
|
|
374
|
+
let { store: o, snapshot: s } = await q(), c = e.includes("--force"), l = (e) => L.warn(e), u = e.includes("--assets") ? C({}) : void 0;
|
|
375
|
+
if (Y(r)) {
|
|
376
|
+
let t = await import("node:os"), n = await import("node:fs/promises"), { resolve: d, join: p } = await import("node:path"), m = await n.mkdtemp(p(t.tmpdir(), "voltro-import-"));
|
|
377
|
+
try {
|
|
378
|
+
let t = Z(d(process.cwd(), r)), n = X(e);
|
|
379
|
+
n && (t = T(t, n)), await ce(t, {
|
|
380
|
+
dir: m,
|
|
381
|
+
blobs: oe(u ?? C({}))
|
|
382
|
+
});
|
|
383
|
+
let p = await f.runPromise(A({
|
|
384
|
+
store: o,
|
|
385
|
+
bundleDir: m,
|
|
386
|
+
mode: i,
|
|
387
|
+
onConflict: a,
|
|
388
|
+
atomic: e.includes("--atomic"),
|
|
389
|
+
verify: !e.includes("--no-verify"),
|
|
390
|
+
targetDialect: W(),
|
|
391
|
+
allowIncompatible: c,
|
|
392
|
+
targetSnapshot: s,
|
|
393
|
+
force: c,
|
|
394
|
+
onWarn: l,
|
|
395
|
+
onProgress: z,
|
|
396
|
+
assetsAlreadyRestored: !0
|
|
397
|
+
}));
|
|
398
|
+
return L.info("import complete (single file)", {
|
|
399
|
+
file: r,
|
|
400
|
+
tables: p.tables.length,
|
|
401
|
+
rows: p.tables.reduce((e, t) => e + t.rowCount, 0)
|
|
402
|
+
}), 0;
|
|
403
|
+
} finally {
|
|
404
|
+
await n.rm(m, {
|
|
405
|
+
recursive: !0,
|
|
406
|
+
force: !0
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
let d = await f.runPromise(A({
|
|
411
|
+
store: o,
|
|
412
|
+
bundleDir: r,
|
|
413
|
+
mode: i,
|
|
414
|
+
onConflict: a,
|
|
415
|
+
atomic: e.includes("--atomic"),
|
|
416
|
+
verify: !e.includes("--no-verify"),
|
|
417
|
+
targetDialect: W(),
|
|
418
|
+
allowIncompatible: c,
|
|
419
|
+
targetSnapshot: s,
|
|
420
|
+
force: c,
|
|
421
|
+
onWarn: l,
|
|
422
|
+
onProgress: z,
|
|
423
|
+
...u ? { assets: M(u) } : {}
|
|
424
|
+
}));
|
|
425
|
+
return L.info("import complete", {
|
|
426
|
+
bundleDir: r,
|
|
427
|
+
tables: d.tables.length,
|
|
428
|
+
rows: d.tables.reduce((e, t) => e + t.rowCount, 0),
|
|
429
|
+
assets: d.assets.count
|
|
430
|
+
}), 0;
|
|
431
|
+
}, $ = () => {
|
|
432
|
+
let e = r();
|
|
433
|
+
return {
|
|
434
|
+
...e.url ? { url: e.url } : {},
|
|
435
|
+
...e.host ? { host: e.host } : {},
|
|
436
|
+
...e.port ? { port: e.port } : {},
|
|
437
|
+
...e.username ? { username: e.username } : {},
|
|
438
|
+
...e.password ? { password: e.password } : {},
|
|
439
|
+
...e.database ? { database: e.database } : {}
|
|
440
|
+
};
|
|
441
|
+
}, we = async (e) => {
|
|
442
|
+
let t = U(e);
|
|
443
|
+
if (!t) return L.error("usage: voltro data backup <outDir> (native pg_dump/mysqldump/… + consistent artifact)"), 1;
|
|
444
|
+
let n = W(), { mkdir: r, writeFile: i } = await import("node:fs/promises"), { join: a } = await import("node:path");
|
|
445
|
+
await r(t, { recursive: !0 });
|
|
446
|
+
let o = a(t, w(n));
|
|
447
|
+
await f.runPromise(j(te(n, $(), o)));
|
|
448
|
+
let s = le({
|
|
449
|
+
dialect: n,
|
|
450
|
+
schemaFingerprint: await R(n),
|
|
451
|
+
voltroVersion: await pe(),
|
|
452
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
453
|
+
});
|
|
454
|
+
return await i(a(t, P), `${JSON.stringify(s, null, 2)}\n`, "utf8"), L.info("native backup complete", {
|
|
455
|
+
dialect: n,
|
|
456
|
+
artifact: o,
|
|
457
|
+
stamp: P,
|
|
458
|
+
schemaFingerprint: s.schemaFingerprint ?? "<none>",
|
|
459
|
+
assets: "NOT included — use `voltro data export --assets` for rows + blobs"
|
|
460
|
+
}), 0;
|
|
461
|
+
}, Te = async (e, t) => {
|
|
462
|
+
let n = W(), { join: r } = await import("node:path"), { readFile: i } = await import("node:fs/promises"), a = r(e, w(n)), o = de({
|
|
463
|
+
flagUrl: H(t, "--drill-url"),
|
|
464
|
+
envUrl: process.env.DRILL_DB_URL,
|
|
465
|
+
liveKeys: he()
|
|
466
|
+
});
|
|
467
|
+
if (!o.ok) return L.error(`restore --drill: ${o.error}`), 1;
|
|
468
|
+
let s = await i(r(e, P), "utf8").then(F, () => null);
|
|
469
|
+
if (s && s.dialect !== n) return L.error(`restore --drill: backup is a ${s.dialect} dump but DB_DIALECT is ${n} — cross-dialect restore is never valid.`), 1;
|
|
470
|
+
L.info("restore drill: restoring into throwaway DB", {
|
|
471
|
+
dialect: n,
|
|
472
|
+
target: I(o.url)
|
|
473
|
+
}), await f.runPromise(j(O(n, { url: o.url }, a)));
|
|
474
|
+
let c = null, l = 0;
|
|
475
|
+
try {
|
|
476
|
+
let e = await G(n, { url: o.url });
|
|
477
|
+
c = g(e), l = e.tables.length;
|
|
478
|
+
} catch (e) {
|
|
479
|
+
return L.error(`restore --drill: could not introspect the restored DB — ${String(e)}`), 1;
|
|
480
|
+
}
|
|
481
|
+
let u = fe({
|
|
482
|
+
stampFingerprint: s?.schemaFingerprint ?? null,
|
|
483
|
+
restoredFingerprint: c,
|
|
484
|
+
restoredTableCount: l
|
|
485
|
+
});
|
|
486
|
+
for (let e of u.lines) u.pass ? L.info(`restore drill: ${e}`) : L.error(`restore drill: ${e}`);
|
|
487
|
+
return +!u.pass;
|
|
488
|
+
}, Ee = async (e) => {
|
|
489
|
+
let t = U(e);
|
|
490
|
+
if (!t) return L.error("usage: voltro data restore <backupDir> [--allow-live] [--api-url <url>] [--force] [--drill [--drill-url <url>]] (native pg_restore/mysql/…)"), 1;
|
|
491
|
+
if (e.includes("--drill")) return Te(t, e);
|
|
492
|
+
if (!await V(e)) return 1;
|
|
493
|
+
let n = W(), { join: r } = await import("node:path"), { readFile: i } = await import("node:fs/promises"), a = r(t, w(n)), o = ue({
|
|
494
|
+
stamp: await i(r(t, P), "utf8").then(F, () => null),
|
|
495
|
+
currentDialect: n,
|
|
496
|
+
currentFingerprint: await R(n)
|
|
497
|
+
});
|
|
498
|
+
for (let e of o.info) L.info(`backup stamp: ${e}`);
|
|
499
|
+
if (o.warn && L.warn(o.warn), o.refuse) {
|
|
500
|
+
if (!e.includes("--force")) return L.error(`restore refused: ${o.refuse} (pass --force to override)`), 1;
|
|
501
|
+
L.warn(`restore proceeding despite: ${o.refuse} (--force)`);
|
|
502
|
+
}
|
|
503
|
+
return await f.runPromise(j(O(n, $(), a))), L.info("native restore complete", {
|
|
504
|
+
dialect: n,
|
|
505
|
+
artifact: a
|
|
506
|
+
}), 0;
|
|
507
|
+
}, De = async (e) => {
|
|
508
|
+
let t = U(e);
|
|
509
|
+
if (!t) return L.error("usage: voltro data inspect <file.vbundle> [--json] [--passphrase <p>]"), 1;
|
|
510
|
+
let { resolve: n } = await import("node:path"), r = n(process.cwd(), t), i = X(e), a = () => {
|
|
511
|
+
let e = Z(r);
|
|
512
|
+
return i ? T(e, i) : e;
|
|
513
|
+
};
|
|
514
|
+
if (e.includes("--json")) {
|
|
515
|
+
let e = (await D(a(), ["manifest.json"])).get("manifest.json");
|
|
516
|
+
return e ? (console.log(e.toString("utf8")), 0) : (L.error("no manifest.json found in the bundle"), 1);
|
|
517
|
+
}
|
|
518
|
+
let o = (await D(a(), ["README.md"])).get("README.md");
|
|
519
|
+
if (o) return console.log(o.toString("utf8")), 0;
|
|
520
|
+
let s = (await D(a(), ["manifest.json"])).get("manifest.json");
|
|
521
|
+
return s ? (console.log(s.toString("utf8")), 0) : (L.error("bundle has no README.md or manifest.json"), 1);
|
|
522
|
+
}, Oe = async (e) => {
|
|
523
|
+
let t = U(e), n = U(e.filter((e) => e !== t));
|
|
524
|
+
if (!t || !n) return L.error("usage: voltro data unpack <file.vbundle> <dir> [--passphrase <p>]"), 1;
|
|
525
|
+
let { resolve: r } = await import("node:path"), i = Z(r(process.cwd(), t)), a = X(e);
|
|
526
|
+
return a && (i = T(i, a)), await N(i, r(process.cwd(), n)), L.info("unpack complete", {
|
|
527
|
+
file: t,
|
|
528
|
+
dir: n
|
|
529
|
+
}), 0;
|
|
530
|
+
}, ke = async (e) => {
|
|
531
|
+
let [t, ...n] = e;
|
|
532
|
+
return t === "export" ? Se(n) : t === "import" ? Ce(n) : t === "unpack" ? Oe(n) : t === "inspect" ? De(n) : t === "backup" ? we(n) : t === "restore" ? Ee(n) : (L.error("usage: voltro data <export|import|unpack|inspect|backup|restore> … (logical: export/import; native: backup/restore)"), t ? 2 : 1);
|
|
533
|
+
};
|
|
534
|
+
//#endregion
|
|
535
|
+
export { ke as runDataCommand };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/dataProfile.ts
|
|
2
|
+
var e = async (e) => {
|
|
3
|
+
let { resolve: t } = await import("node:path"), { existsSync: n } = await import("node:fs"), r = [
|
|
4
|
+
e,
|
|
5
|
+
`${e}.profile.ts`,
|
|
6
|
+
`data-profiles/${e}.ts`,
|
|
7
|
+
`data-profiles/${e}.profile.ts`
|
|
8
|
+
].map((e) => t(process.cwd(), e)), i = r.find((e) => n(e));
|
|
9
|
+
if (!i) throw Error(`data profile '${e}' not found (looked for: ${r.join(", ")})`);
|
|
10
|
+
let a = await import(i), o = a.default ?? a.profile;
|
|
11
|
+
if (!o) throw Error(`data profile '${i}' has no default export`);
|
|
12
|
+
return o;
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { e as t };
|