@voltro/cli 0.33.0 → 0.35.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 +1968 -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-B8aoJvuw.js +2 -0
- package/dist/{apiBuild-h9VHtnlw.js → apiBuild-DYD_ONLD.js} +46 -46
- package/dist/{appGraph-gQ_6GkQQ.js → appGraph-KGDPTuTy.js} +1 -1
- package/dist/appGraph-zuMGKVYX.js +2 -0
- 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-CD8K4XOr.js +711 -0
- package/dist/cacheCommand-DA4OH9xt.js +42 -0
- package/dist/capabilitiesCommand-nq_pz5xd.js +123 -0
- package/dist/checkCommand-Ct9xkTrS.js +232 -0
- package/dist/checkCommand-DKpDLlqu.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-D5wsCmA_.js +54 -0
- package/dist/codegen-CYM3Zqrf.js +605 -0
- package/dist/codegen-ChBi_hVa.js +2 -0
- package/dist/codegenCommand-C4YoQIc2.js +30 -0
- package/dist/codemodRunner-BnFq3Fgu.js +5384 -0
- package/dist/commandRunner-BLAEFLjp.js +47 -0
- package/dist/commands-BE8E7zF3.js +816 -0
- package/dist/connectionConfig-UFlIEiys.js +66 -0
- package/dist/dashboardCommand-D7SgZGaN.js +25 -0
- package/dist/dataCommand-BhYwDgg-.js +537 -0
- package/dist/dataProfile-dW-PsfLB.js +15 -0
- package/dist/dbCommand-DS4b97Is.js +2 -0
- package/dist/{dbCommand-DTLKAfbA.js → dbCommand-O8HA63s2.js} +552 -402
- package/dist/{dev-C_P8FLSx.js → dev-C7sFZq3m.js} +3670 -3169
- package/dist/dev-D2BikO7a.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-CM4Ch9C7.js +2 -0
- package/dist/{checkCommand-xGhRFFg2.js → doctorCommand-DnimF5IM.js} +523 -1278
- package/dist/dormancyCommand-QewYug_s.js +69 -0
- package/dist/e2eCmd-BRabZww-.js +147 -0
- package/dist/embeddingsCommand-BfiLS_QI.js +73 -0
- package/dist/envCommand-CCGPRQY1.js +60 -0
- package/dist/evalCommand-6RUfPen4.js +118 -0
- package/dist/evolveCommand-CHsLCtDf.js +281 -0
- package/dist/fileTaxonomy-CJfgOllU.js +457 -0
- package/dist/frameworkTableAssembly-YyVe32Cb.js +2 -0
- package/dist/frameworkTableAssembly-oMPBKqlE.js +511 -0
- package/dist/generateCommand-DbgcUpGw.js +147 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +4 -3
- package/dist/infoCommand-DwOgK1t6.js +60 -0
- package/dist/{inspect-BUUjt773.js → inspect-CjTYzAs_.js} +113 -41
- package/dist/inspect-P4pxoMaV.js +2 -0
- package/dist/inspectCmd-EHFZ9yYu.js +224 -0
- package/dist/inspectFetch-EMuhTG_9.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-D36xK7Zu.js +260 -0
- package/dist/manifestBuild-COkJoyAr.js +2 -0
- package/dist/{manifestBuild-BLrVuSlM.js → manifestBuild-hpPLaGxV.js} +1 -1
- package/dist/metaCommands-7MJfZ5cf.js +196 -0
- package/dist/migrate-BV7I-ZHZ.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/probeCommand-CZfaaUOZ.js +122 -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-CH3eUiMw.js +91 -0
- package/dist/scheduleCmd-DQRu6BZC.js +149 -0
- package/dist/scheduleManifestCmd-D2x0CTTY.js +249 -0
- package/dist/schemaIr-UJybUUZW.js +103 -0
- package/dist/{sdkgen-C81QIkiL.js → sdkgen-BLkvGRfX.js} +111 -209
- package/dist/seedRunner-ZmLSqNe2.js +333 -0
- package/dist/serveCommand-CbDHU6l-.js +2 -0
- package/dist/serveCommand-iwlUBNS1.js +1766 -0
- package/dist/serveEntry.js +5 -5
- package/dist/serverlessCommand-CfJZy6dS.js +482 -0
- package/dist/start-BgN62boB.js +3 -0
- package/dist/start-T4VesWiM.js +1087 -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-DStmCJPi.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-BlMZhWgO.js +2 -0
- package/dist/updateCommand-x0pI_x-B.js +585 -0
- package/dist/webDev-BcykISYQ2.js +2 -0
- package/dist/{inspectMetrics-1xzTKAFx.js → webDev-Dybxew86.js} +988 -1560
- package/dist/webhookDiscovery-CrGAfhIG.js +2 -0
- package/dist/webhookDiscovery-D7VaeMlz.js +51 -0
- package/dist/webhooksCommand-DlAgS2Iw.js +267 -0
- package/dist/workflowsCmd-BGF-mRZ5.js +608 -0
- package/package.json +209 -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 +23 -6
- package/templates/agent-docs/ai.md +370 -0
- package/templates/agent-docs/authentication.md +313 -31
- package/templates/agent-docs/caching.md +6 -0
- package/templates/agent-docs/cli.md +853 -50
- package/templates/agent-docs/data.md +608 -12
- package/templates/agent-docs/database/migrations.md +223 -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 +284 -25
- package/templates/agent-docs/introduction.md +88 -17
- package/templates/agent-docs/local-first-mobile.md +79 -4
- package/templates/agent-docs/multi-tenancy.md +188 -42
- package/templates/agent-docs/observability.md +58 -3
- package/templates/agent-docs/plugins/ai-flows.md +247 -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 +32 -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 +162 -8
- package/templates/agent-docs/plugins/sso-saml.md +47 -8
- package/templates/agent-docs/plugins/storage.md +11 -0
- package/templates/agent-docs/plugins/webhooks.md +105 -0
- package/templates/agent-docs/plugins.md +152 -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 +27 -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 +98 -136
- package/templates/agent-docs/workflows.md +231 -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/appGraph-CvQCte0z.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-BwIrO5nv.js +0 -638
- 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,51 @@
|
|
|
1
|
+
import { n as e } from "./appModuleLoader-C9r9mxZt.js";
|
|
2
|
+
import { asOutgoingEvent as t, isWebhookDescriptor as n } from "@voltro/plugin-webhooks";
|
|
3
|
+
//#region src/webhookDiscovery.ts
|
|
4
|
+
var r = /\.webhook\.tsx?$/, i = async (t, r) => {
|
|
5
|
+
let i = [], a = [], o = [];
|
|
6
|
+
for (let i of t) {
|
|
7
|
+
let t;
|
|
8
|
+
try {
|
|
9
|
+
t = await e(i);
|
|
10
|
+
} catch (e) {
|
|
11
|
+
r.warn("webhook: failed to import", { file: i }, e);
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
let s = (t.default && n(t.default) ? t.default : void 0) ?? Object.values(t).find(n);
|
|
15
|
+
if (!s) {
|
|
16
|
+
r.warn("webhook: no descriptor default-exported", { file: i });
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
switch (s._tag) {
|
|
20
|
+
case "incomingWebhook":
|
|
21
|
+
a.push({
|
|
22
|
+
file: i,
|
|
23
|
+
descriptor: s
|
|
24
|
+
});
|
|
25
|
+
break;
|
|
26
|
+
case "webhookProvider":
|
|
27
|
+
o.push({
|
|
28
|
+
file: i,
|
|
29
|
+
descriptor: s
|
|
30
|
+
});
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
outgoing: i,
|
|
36
|
+
incoming: a,
|
|
37
|
+
providers: o
|
|
38
|
+
};
|
|
39
|
+
}, a = (e) => {
|
|
40
|
+
let n = [];
|
|
41
|
+
for (let { file: r, descriptor: i } of e) {
|
|
42
|
+
let e = t(i);
|
|
43
|
+
e !== void 0 && n.push({
|
|
44
|
+
file: r,
|
|
45
|
+
descriptor: e
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return n;
|
|
49
|
+
}, o = (e, t) => e > 0 || a(t).length > 0;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { a as i, o as n, i as r, r as t };
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { i as e, n as t } from "./cliArgs-D4p8n7EE.js";
|
|
2
|
+
import { t as n } from "./cliRuntime-Dh7UDinH.js";
|
|
3
|
+
import { i as r, n as i, r as a } from "./schemaIr-UJybUUZW.js";
|
|
4
|
+
import { isAbsolute as o, join as s, resolve as c } from "node:path";
|
|
5
|
+
import { promises as l } from "node:fs";
|
|
6
|
+
import { createLogger as u } from "@voltro/logger";
|
|
7
|
+
import { Effect as d, JSONSchema as f } from "effect";
|
|
8
|
+
//#region src/webhookConsumer.ts
|
|
9
|
+
var p = (e) => {
|
|
10
|
+
switch (e.kind) {
|
|
11
|
+
case "string": return "string";
|
|
12
|
+
case "integer":
|
|
13
|
+
case "number": return "number";
|
|
14
|
+
case "boolean": return "boolean";
|
|
15
|
+
case "unknown": return "unknown";
|
|
16
|
+
case "array": return `ReadonlyArray<${p(e.element)}>`;
|
|
17
|
+
case "optional": return `${p(e.inner)} | undefined`;
|
|
18
|
+
case "ref": return e.name;
|
|
19
|
+
}
|
|
20
|
+
}, m = (e) => `export type ${e.name} =\n${e.values.map((e) => ` | ${JSON.stringify(e)}`).join("\n")}`, h = (e) => {
|
|
21
|
+
let t = e.fields.map((e) => {
|
|
22
|
+
let t = e.type.kind === "optional", n = p(t ? e.type.inner : e.type);
|
|
23
|
+
return ` readonly ${/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e.jsonName) ? e.jsonName : JSON.stringify(e.jsonName)}${t ? "?" : ""}: ${n}`;
|
|
24
|
+
});
|
|
25
|
+
return `export interface ${e.name} {\n${t.join("\n")}\n}`;
|
|
26
|
+
}, g = (e) => a(e.replace(/[^A-Za-z0-9]+/g, " ").trim()) || "Event", _ = "// Generated by `voltro webhooks consumer`. Do not edit.\n//\n// Standard Webhooks v1.0.0 verification. Zero dependencies; `node:crypto` only.\n\nimport { createHmac, timingSafeEqual } from 'node:crypto'\n\nconst PREFIX = 'whsec_'\nconst DEFAULT_TOLERANCE_SECONDS = 300\n\nexport class WebhookVerificationError extends Error {\n constructor(reason) {\n super(`webhook verification failed: ${reason}`)\n this.name = 'WebhookVerificationError'\n this.reason = reason\n }\n}\n\nconst keyBytes = (secret) => {\n if (typeof secret !== 'string' || !secret.startsWith(PREFIX)) {\n throw new WebhookVerificationError(\n 'the signing secret must be the \"whsec_\" + base64 form the producer issued',\n )\n }\n return Buffer.from(secret.slice(PREFIX.length), 'base64')\n}\n\nconst constantTimeEq = (a, b) => {\n const ba = Buffer.from(a, 'utf8')\n const bb = Buffer.from(b, 'utf8')\n if (ba.length !== bb.length) {\n timingSafeEqual(ba, Buffer.alloc(ba.length))\n return false\n }\n return timingSafeEqual(ba, bb)\n}\n\n// Accepts a Headers instance, a Node `req.headers`, or a plain object.\nconst headerValue = (headers, name) => {\n if (headers && typeof headers.get === 'function') return headers.get(name) ?? undefined\n if (!headers || typeof headers !== 'object') return undefined\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() !== name) continue\n return Array.isArray(v) ? v[0] : v == null ? undefined : String(v)\n }\n return undefined\n}\n\n/**\n * Verify one delivery.\n *\n * `body` MUST be the RAW request bytes — the exact string or Buffer that\n * arrived. Re-serialising a parsed JSON object changes key order and whitespace\n * and the signature will not match. This is the single most common integration\n * failure; see the README for the per-framework raw-body recipe.\n */\nexport const createVerifier = (options) => {\n const secrets = (Array.isArray(options?.secret) ? options.secret : [options?.secret]).filter(Boolean)\n if (secrets.length === 0) throw new WebhookVerificationError('at least one secret is required')\n const tolerance = options?.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS\n\n const verify = (body, headers, now) => {\n const id = headerValue(headers, 'webhook-id')\n const timestampRaw = headerValue(headers, 'webhook-timestamp')\n const signatureHeader = headerValue(headers, 'webhook-signature')\n if (!id) throw new WebhookVerificationError('missing webhook-id')\n if (!timestampRaw) throw new WebhookVerificationError('missing webhook-timestamp')\n if (!signatureHeader) throw new WebhookVerificationError('missing webhook-signature')\n if (id.includes('.')) throw new WebhookVerificationError('webhook-id contains the \".\" field delimiter')\n\n const timestamp = Number(timestampRaw)\n if (!Number.isInteger(timestamp)) throw new WebhookVerificationError('webhook-timestamp is not an integer')\n const nowSeconds = now ?? Math.floor(Date.now() / 1000)\n const skew = Math.abs(nowSeconds - timestamp)\n if (skew > tolerance) {\n throw new WebhookVerificationError(`timestamp outside the ${tolerance}s tolerance (off by ${skew}s)`)\n }\n\n const raw = Buffer.isBuffer(body) ? body : Buffer.from(String(body), 'utf8')\n const signed = Buffer.concat([Buffer.from(`${id}.${timestamp}.`, 'utf8'), raw])\n const offered = signatureHeader.split(' ').map((t) => t.trim()).filter(Boolean)\n\n let matched = false\n for (const secret of secrets) {\n const mac = createHmac('sha256', keyBytes(secret))\n mac.update(signed)\n const expected = `v1,${mac.digest('base64')}`\n for (const token of offered) {\n if (!token.startsWith('v1,')) continue\n if (constantTimeEq(expected, token)) { matched = true; break }\n }\n if (matched) break\n }\n if (!matched) throw new WebhookVerificationError('signature mismatch')\n\n let payload\n try {\n payload = JSON.parse(raw.toString('utf8'))\n } catch (err) {\n throw new WebhookVerificationError(`body is not valid JSON: ${err.message}`)\n }\n\n return {\n id,\n timestamp,\n event: headerValue(headers, 'x-voltro-event') ?? null,\n payload,\n }\n }\n\n return { verify }\n}\n", v = (e, t, n) => {
|
|
27
|
+
let r = [...n.map(m), ...t.map(h)], i = [], a = [];
|
|
28
|
+
for (let t of e) {
|
|
29
|
+
let e = `${g(t.name)}Payload`;
|
|
30
|
+
a.push(` | { readonly event: '${t.name}'; readonly payload: ${e} }`), t.description !== void 0 && i.push(`/** ${t.description} */`);
|
|
31
|
+
}
|
|
32
|
+
return `// Generated by \`voltro webhooks consumer\`. Do not edit.
|
|
33
|
+
//
|
|
34
|
+
// TYPES ONLY — no decoder ships with this package. The types describe what the
|
|
35
|
+
// producer sends; the SIGNATURE is what proves a delivery came from them. If
|
|
36
|
+
// you want runtime validation on top, use your own validator against these
|
|
37
|
+
// shapes.
|
|
38
|
+
|
|
39
|
+
${r.join("\n\n")}
|
|
40
|
+
|
|
41
|
+
/** Every event this producer can deliver, discriminated on \`event\`. */
|
|
42
|
+
export type WebhookEvent =
|
|
43
|
+
${a.length > 0 ? a.join("\n") : " never"}
|
|
44
|
+
|
|
45
|
+
export declare class WebhookVerificationError extends Error {
|
|
46
|
+
readonly reason: string
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface VerifiedWebhook {
|
|
50
|
+
/** \`webhook-id\` — the producer's message id. USE THIS AS YOUR IDEMPOTENCY
|
|
51
|
+
* KEY: retries of the same delivery repeat it, and a redelivery is expected
|
|
52
|
+
* rather than exceptional. */
|
|
53
|
+
readonly id: string
|
|
54
|
+
/** \`webhook-timestamp\`, unix seconds. */
|
|
55
|
+
readonly timestamp: number
|
|
56
|
+
/** The event name, from \`x-voltro-event\`. \`null\` if the header is absent. */
|
|
57
|
+
readonly event: string | null
|
|
58
|
+
/** The decoded body. */
|
|
59
|
+
readonly payload: unknown
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface VerifierOptions {
|
|
63
|
+
/** The endpoint's signing secret (\`whsec_…\`). Pass an ARRAY during a secret
|
|
64
|
+
* rotation — each is tried, so both old and new deliveries verify. */
|
|
65
|
+
readonly secret: string | ReadonlyArray<string>
|
|
66
|
+
/** Replay tolerance in seconds. Default 300. */
|
|
67
|
+
readonly toleranceSeconds?: number
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface Verifier {
|
|
71
|
+
/**
|
|
72
|
+
* Verify a delivery. Throws \`WebhookVerificationError\` on any failure.
|
|
73
|
+
*
|
|
74
|
+
* \`body\` MUST be the RAW bytes. Re-serialising a parsed object changes key
|
|
75
|
+
* order and whitespace, and the signature will not match.
|
|
76
|
+
*/
|
|
77
|
+
verify(body: string | Uint8Array, headers: unknown, nowSeconds?: number): VerifiedWebhook
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export declare const createVerifier: (options: VerifierOptions) => Verifier
|
|
81
|
+
`;
|
|
82
|
+
}, y = (e, t) => {
|
|
83
|
+
let n = e.appName ?? "the producer", r = t.length > 0 ? t.map((e) => `| \`${e.name}\` | ${e.description ?? "—"} | v${e.version ?? 1} |`).join("\n") : "| _(no outbound events declared)_ | | |";
|
|
84
|
+
return `# ${e.packageName}
|
|
85
|
+
|
|
86
|
+
Webhook verification for **${n}**, generated from its own event schema by
|
|
87
|
+
\`voltro webhooks consumer\`.
|
|
88
|
+
|
|
89
|
+
- **Zero runtime dependencies.** \`node:crypto\` only.
|
|
90
|
+
- **Standard Webhooks v1.0.0** — the same spec every conformant producer signs
|
|
91
|
+
to, so this is not a vendor-specific verifier.
|
|
92
|
+
- **Node 18+** (or any runtime that provides \`node:crypto\`). Deliberately NOT
|
|
93
|
+
Web Crypto: its HMAC is async, which would make \`verify()\` return a Promise
|
|
94
|
+
and force every handler using it to be async too.
|
|
95
|
+
|
|
96
|
+
## Install
|
|
97
|
+
|
|
98
|
+
Copy this directory into your service, or publish it to your private registry.
|
|
99
|
+
|
|
100
|
+
## Verify
|
|
101
|
+
|
|
102
|
+
\`\`\`js
|
|
103
|
+
import { createVerifier, WebhookVerificationError } from '${e.packageName}'
|
|
104
|
+
|
|
105
|
+
const verifier = createVerifier({ secret: process.env.WEBHOOK_SECRET })
|
|
106
|
+
|
|
107
|
+
app.post('/webhooks/${n.toLowerCase().replace(/[^a-z0-9]+/g, "-")}', (req, res) => {
|
|
108
|
+
let delivery
|
|
109
|
+
try {
|
|
110
|
+
delivery = verifier.verify(req.rawBody, req.headers) // ← RAW bytes
|
|
111
|
+
} catch (err) {
|
|
112
|
+
if (err instanceof WebhookVerificationError) return res.status(401).send(err.reason)
|
|
113
|
+
throw err
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// \`delivery.id\` is your idempotency key — retries repeat it.
|
|
117
|
+
if (alreadyProcessed(delivery.id)) return res.sendStatus(200)
|
|
118
|
+
|
|
119
|
+
switch (delivery.event) {
|
|
120
|
+
${t.slice(0, 3).map((e) => ` case '${e.name}': /* delivery.payload */ break`).join("\n") || " default: break"}
|
|
121
|
+
}
|
|
122
|
+
res.sendStatus(200)
|
|
123
|
+
})
|
|
124
|
+
\`\`\`
|
|
125
|
+
|
|
126
|
+
### The raw body is the whole trap
|
|
127
|
+
|
|
128
|
+
The signature covers **the exact bytes that arrived**. A JSON body-parser
|
|
129
|
+
re-serialises, changing key order and whitespace, and the signature then never
|
|
130
|
+
matches. Every framework has a way to keep the raw bytes:
|
|
131
|
+
|
|
132
|
+
| framework | how |
|
|
133
|
+
|---|---|
|
|
134
|
+
| Express | \`express.json({ verify: (req, _res, buf) => { req.rawBody = buf } })\` |
|
|
135
|
+
| Fastify | \`fastify.addContentTypeParser('application/json', { parseAs: 'buffer' }, (_req, body, done) => done(null, body))\` |
|
|
136
|
+
| Next.js (app router) | \`await req.text()\` |
|
|
137
|
+
| Hono | \`await c.req.text()\` |
|
|
138
|
+
|
|
139
|
+
## What the producer sends
|
|
140
|
+
|
|
141
|
+
| header | meaning |
|
|
142
|
+
|---|---|
|
|
143
|
+
| \`webhook-id\` | unique message id — **your idempotency key** |
|
|
144
|
+
| \`webhook-timestamp\` | unix seconds; rejected outside the tolerance (default 300s) |
|
|
145
|
+
| \`webhook-signature\` | \`v1,<base64>\`, space-delimited during a secret rotation |
|
|
146
|
+
| \`x-voltro-event\` | the event name |
|
|
147
|
+
| \`x-voltro-attempt\` | 1-based attempt counter |
|
|
148
|
+
|
|
149
|
+
Answer **2xx** to accept. Anything else is a failure and will be retried; a
|
|
150
|
+
\`410 Gone\` tells the producer to disable your endpoint permanently.
|
|
151
|
+
|
|
152
|
+
## Events
|
|
153
|
+
|
|
154
|
+
| event | description | payload version |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
${r}
|
|
157
|
+
|
|
158
|
+
Payload types are in \`index.d.ts\`. They are **types only** — no decoder ships
|
|
159
|
+
here. The types describe what the producer sends; the signature is what proves
|
|
160
|
+
it came from them.
|
|
161
|
+
|
|
162
|
+
## Rotating the secret
|
|
163
|
+
|
|
164
|
+
Pass both keys while the rotation is in flight:
|
|
165
|
+
|
|
166
|
+
\`\`\`js
|
|
167
|
+
createVerifier({ secret: [process.env.WEBHOOK_SECRET, process.env.WEBHOOK_SECRET_PREVIOUS] })
|
|
168
|
+
\`\`\`
|
|
169
|
+
`;
|
|
170
|
+
}, b = (e, t) => {
|
|
171
|
+
let n = i();
|
|
172
|
+
for (let t of e) r(t.payload, `${g(t.name)}Payload`, n);
|
|
173
|
+
let a = [...n.models.values()], o = [...n.enums.values()];
|
|
174
|
+
return [
|
|
175
|
+
{
|
|
176
|
+
path: "package.json",
|
|
177
|
+
content: `${JSON.stringify({
|
|
178
|
+
name: t.packageName,
|
|
179
|
+
version: "0.0.0",
|
|
180
|
+
description: `Webhook verification for ${t.appName ?? "a Voltro app"} — generated, zero-dependency.`,
|
|
181
|
+
type: "module",
|
|
182
|
+
main: "./index.js",
|
|
183
|
+
types: "./index.d.ts",
|
|
184
|
+
exports: { ".": {
|
|
185
|
+
types: "./index.d.ts",
|
|
186
|
+
import: "./index.js",
|
|
187
|
+
default: "./index.js"
|
|
188
|
+
} },
|
|
189
|
+
files: [
|
|
190
|
+
"index.js",
|
|
191
|
+
"index.d.ts",
|
|
192
|
+
"README.md"
|
|
193
|
+
],
|
|
194
|
+
engines: { node: ">=18" },
|
|
195
|
+
private: !0
|
|
196
|
+
}, null, 2)}\n`
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
path: "index.js",
|
|
200
|
+
content: _
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
path: "index.d.ts",
|
|
204
|
+
content: v(e, a, o)
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
path: "README.md",
|
|
208
|
+
content: y(t, e)
|
|
209
|
+
}
|
|
210
|
+
];
|
|
211
|
+
}, x = (e) => {
|
|
212
|
+
let t;
|
|
213
|
+
try {
|
|
214
|
+
t = f.make(e.payload);
|
|
215
|
+
} catch {
|
|
216
|
+
t = void 0;
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
name: e.id,
|
|
220
|
+
...e.description === void 0 ? {} : { description: e.description },
|
|
221
|
+
...e.version === void 0 ? {} : { version: e.version },
|
|
222
|
+
...t === void 0 ? {} : { payload: t }
|
|
223
|
+
};
|
|
224
|
+
}, S = u({ scope: "voltro:webhooks" }), C = ["--out", "--name"], w = async (e) => {
|
|
225
|
+
let { walk: t, loadDiscovered: n } = await import("./dev-D2BikO7a.js"), { outgoingFromEvents: r } = await import("./webhookDiscovery-CrGAfhIG.js");
|
|
226
|
+
return r((await n(await t(e))).events.map((e) => ({
|
|
227
|
+
file: e.file,
|
|
228
|
+
descriptor: e.descriptor
|
|
229
|
+
}))).map((e) => x(e.descriptor));
|
|
230
|
+
}, T = (t, n) => {
|
|
231
|
+
let r = e(t, [...C]).find((e) => e !== "consumer" && e !== "events");
|
|
232
|
+
return r ? o(r) ? r : s(n, r) : n;
|
|
233
|
+
}, E = async (e, n) => {
|
|
234
|
+
let r = T(e, n), i = await w(r);
|
|
235
|
+
if (i.length === 0) return console.error("voltro webhooks consumer: this app declares no outbound events, so there is nothing for a\n subscriber to verify. Add a `webhook:` block to a defineEvent(), e.g.\n\n export const orderPaid = defineEvent({\n name: 'orders.paid',\n key: Schema.Struct({ orderId: Schema.String }),\n payload: Schema.Struct({ total: Schema.Number }),\n webhook: { description: 'An order was paid' },\n })\n"), 1;
|
|
236
|
+
let a = await O(r), o = t(e, "--name") ?? `${(a ?? "voltro-app").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")}-webhooks`, u = c(r, t(e, "--out") ?? "webhook-consumer"), d = b(i, {
|
|
237
|
+
packageName: o,
|
|
238
|
+
...a === void 0 ? {} : { appName: a }
|
|
239
|
+
});
|
|
240
|
+
await l.mkdir(u, { recursive: !0 });
|
|
241
|
+
for (let e of d) await l.writeFile(s(u, e.path), e.content, "utf8");
|
|
242
|
+
return S.info("generated the consumer verification package", {
|
|
243
|
+
outDir: u,
|
|
244
|
+
packageName: o,
|
|
245
|
+
events: i.length,
|
|
246
|
+
dependencies: 0
|
|
247
|
+
}), console.log(`\nHand ${u} to whoever receives your webhooks.\n ${i.length} event(s) · zero runtime dependencies · Standard Webhooks v1.0.0\n`), 0;
|
|
248
|
+
}, D = async (e, t) => {
|
|
249
|
+
let n = await w(T(e, t));
|
|
250
|
+
if (e.includes("--json")) return console.log(JSON.stringify({ events: n }, null, 2)), 0;
|
|
251
|
+
if (n.length === 0) return console.log("No outbound events declared (a defineEvent() with a `webhook:` block)."), 0;
|
|
252
|
+
console.log(`\n${n.length} outbound event(s):\n`);
|
|
253
|
+
for (let e of n) console.log(` ${e.name} (v${e.version ?? 1})${e.description ? ` — ${e.description}` : ""}`);
|
|
254
|
+
return console.log(""), 0;
|
|
255
|
+
}, O = async (e) => {
|
|
256
|
+
try {
|
|
257
|
+
let t = await l.readFile(s(e, "package.json"), "utf8"), n = JSON.parse(t).name;
|
|
258
|
+
return typeof n == "string" ? n : void 0;
|
|
259
|
+
} catch {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
}, k = async (e, t = process.cwd()) => {
|
|
263
|
+
let r = e[0];
|
|
264
|
+
return r === "consumer" ? n(d.promise(() => E(e.slice(1), t))) : r === "events" ? n(d.promise(() => D(e.slice(1), t))) : (console.error("usage: voltro webhooks <consumer|events> [path] [--out <dir>] [--name <pkg>]\n consumer generate the zero-dependency verification package a subscriber installs\n events list the outbound events a subscriber can register for"), 1);
|
|
265
|
+
};
|
|
266
|
+
//#endregion
|
|
267
|
+
export { k as runWebhooksCommand };
|