convex 1.46.0 → 1.48.0-alpha.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 +58 -1
- package/dist/browser.bundle.js +7 -1
- package/dist/browser.bundle.js.map +2 -2
- package/dist/cjs/bundler/context.js +7 -5
- package/dist/cjs/bundler/context.js.map +2 -2
- package/dist/cjs/bundler/fs.js +47 -6
- package/dist/cjs/bundler/fs.js.map +2 -2
- package/dist/cjs/bundler/index.js +5 -4
- package/dist/cjs/bundler/index.js.map +2 -2
- package/dist/cjs/cli/account.js +237 -0
- package/dist/cjs/cli/account.js.map +7 -0
- package/dist/cjs/cli/codegen.js +0 -4
- package/dist/cjs/cli/codegen.js.map +2 -2
- package/dist/cjs/cli/configure.js +28 -6
- package/dist/cjs/cli/configure.js.map +2 -2
- package/dist/cjs/cli/deploy.js +27 -2
- package/dist/cjs/cli/deploy.js.map +2 -2
- package/dist/cjs/cli/deploymentSelect.js +2 -2
- package/dist/cjs/cli/deploymentSelect.js.map +2 -2
- package/dist/cjs/cli/dev.js +6 -0
- package/dist/cjs/cli/dev.js.map +2 -2
- package/dist/cjs/cli/env.js +10 -5
- package/dist/cjs/cli/env.js.map +2 -2
- package/dist/cjs/cli/envDefault.js +7 -2
- package/dist/cjs/cli/envDefault.js.map +2 -2
- package/dist/cjs/cli/generatedApi.js.map +1 -1
- package/dist/cjs/cli/lib/api.js +2 -0
- package/dist/cjs/cli/lib/api.js.map +2 -2
- package/dist/cjs/cli/lib/checkForLargeIndexBackfill.js +113 -0
- package/dist/cjs/cli/lib/checkForLargeIndexBackfill.js.map +7 -0
- package/dist/cjs/cli/lib/checkForLargeIndexDeletion.js +36 -47
- package/dist/cjs/cli/lib/checkForLargeIndexDeletion.js.map +2 -2
- package/dist/cjs/cli/lib/checkForSlowSchemaValidation.js +58 -39
- package/dist/cjs/cli/lib/checkForSlowSchemaValidation.js.map +2 -2
- package/dist/cjs/cli/lib/checkForStagedValidatorDeletion.js +90 -0
- package/dist/cjs/cli/lib/checkForStagedValidatorDeletion.js.map +7 -0
- package/dist/cjs/cli/lib/codegen.js.map +2 -2
- package/dist/cjs/cli/lib/command.js +2 -1
- package/dist/cjs/cli/lib/command.js.map +2 -2
- package/dist/cjs/cli/lib/components/definition/bundle.js +37 -11
- package/dist/cjs/cli/lib/components/definition/bundle.js.map +2 -2
- package/dist/cjs/cli/lib/components.js +48 -5
- package/dist/cjs/cli/lib/components.js.map +2 -2
- package/dist/cjs/cli/lib/config.js +56 -17
- package/dist/cjs/cli/lib/config.js.map +2 -2
- package/dist/cjs/cli/lib/deploy2.js +3 -1
- package/dist/cjs/cli/lib/deploy2.js.map +2 -2
- package/dist/cjs/cli/lib/deployApi/evaluateSchema.js +30 -2
- package/dist/cjs/cli/lib/deployApi/evaluateSchema.js.map +2 -2
- package/dist/cjs/cli/lib/deployKeyWarning.js +43 -0
- package/dist/cjs/cli/lib/deployKeyWarning.js.map +7 -0
- package/dist/cjs/cli/lib/deployment.js +2 -0
- package/dist/cjs/cli/lib/deployment.js.map +2 -2
- package/dist/cjs/cli/lib/deploymentSelection.js +27 -18
- package/dist/cjs/cli/lib/deploymentSelection.js.map +2 -2
- package/dist/cjs/cli/lib/dev.js +5 -0
- package/dist/cjs/cli/lib/dev.js.map +2 -2
- package/dist/cjs/cli/lib/envvars.js +32 -0
- package/dist/cjs/cli/lib/envvars.js.map +2 -2
- package/dist/cjs/cli/lib/formatValidationProgress.js +47 -0
- package/dist/cjs/cli/lib/formatValidationProgress.js.map +7 -0
- package/dist/cjs/cli/lib/fsUtils.js +1 -1
- package/dist/cjs/cli/lib/fsUtils.js.map +2 -2
- package/dist/cjs/cli/lib/generateDocs.js +1 -1
- package/dist/cjs/cli/lib/generateDocs.js.map +1 -1
- package/dist/cjs/cli/lib/indexes.js.map +1 -1
- package/dist/cjs/cli/lib/login.js +28 -4
- package/dist/cjs/cli/lib/login.js.map +2 -2
- package/dist/cjs/cli/lib/mcp/requestContext.js +5 -1
- package/dist/cjs/cli/lib/mcp/requestContext.js.map +2 -2
- package/dist/cjs/cli/lib/mcp/tools/env.js +10 -3
- package/dist/cjs/cli/lib/mcp/tools/env.js.map +2 -2
- package/dist/cjs/cli/lib/profileManagement.js +196 -0
- package/dist/cjs/cli/lib/profileManagement.js.map +7 -0
- package/dist/cjs/cli/lib/profiles.js +333 -0
- package/dist/cjs/cli/lib/profiles.js.map +7 -0
- package/dist/cjs/cli/lib/run.js +4 -0
- package/dist/cjs/cli/lib/run.js.map +2 -2
- package/dist/cjs/cli/lib/schemaEvaluation.js +62 -0
- package/dist/cjs/cli/lib/schemaEvaluation.js.map +7 -0
- package/dist/cjs/cli/lib/usageLimits.js +4 -2
- package/dist/cjs/cli/lib/usageLimits.js.map +2 -2
- package/dist/cjs/cli/lib/utils/mutex.js +9 -24
- package/dist/cjs/cli/lib/utils/mutex.js.map +2 -2
- package/dist/cjs/cli/lib/utils/utils.js +66 -27
- package/dist/cjs/cli/lib/utils/utils.js.map +2 -2
- package/dist/cjs/cli/login.js +213 -114
- package/dist/cjs/cli/login.js.map +3 -3
- package/dist/cjs/cli/logout.js +113 -12
- package/dist/cjs/cli/logout.js.map +3 -3
- package/dist/cjs/cli/mcp.js +43 -10
- package/dist/cjs/cli/mcp.js.map +3 -3
- package/dist/cjs/cli/program.js +2 -1
- package/dist/cjs/cli/program.js.map +2 -2
- package/dist/cjs/cli/projectCreate.js +1 -1
- package/dist/cjs/cli/projectCreate.js.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/server/impl/actions_impl.js +8 -3
- package/dist/cjs/server/impl/actions_impl.js.map +2 -2
- package/dist/cjs/server/impl/storage_impl.js +29 -0
- package/dist/cjs/server/impl/storage_impl.js.map +2 -2
- package/dist/cjs/server/index.js +1 -0
- package/dist/cjs/server/index.js.map +2 -2
- package/dist/cjs/server/meta.js.map +1 -1
- package/dist/cjs/server/registration.js.map +1 -1
- package/dist/cjs/server/schema.js +34 -12
- package/dist/cjs/server/schema.js.map +2 -2
- package/dist/cjs/server/storage.js.map +1 -1
- package/dist/cjs/values/validators.js +1 -1
- package/dist/cjs/values/validators.js.map +2 -2
- package/dist/cjs/values/value.js +6 -0
- package/dist/cjs/values/value.js.map +2 -2
- package/dist/cjs-types/bundler/context.d.ts +5 -0
- package/dist/cjs-types/bundler/context.d.ts.map +1 -1
- package/dist/cjs-types/bundler/fs.d.ts +7 -2
- package/dist/cjs-types/bundler/fs.d.ts.map +1 -1
- package/dist/cjs-types/bundler/index.d.ts +9 -2
- package/dist/cjs-types/bundler/index.d.ts.map +1 -1
- package/dist/cjs-types/cli/account.d.ts +6 -0
- package/dist/cjs-types/cli/account.d.ts.map +1 -0
- package/dist/cjs-types/cli/codegen.d.ts.map +1 -1
- package/dist/cjs-types/cli/configure.d.ts +6 -0
- package/dist/cjs-types/cli/configure.d.ts.map +1 -1
- package/dist/cjs-types/cli/deploy.d.ts +2 -0
- package/dist/cjs-types/cli/deploy.d.ts.map +1 -1
- package/dist/cjs-types/cli/deploymentCreate.d.ts +6 -6
- package/dist/cjs-types/cli/deploymentSelect.d.ts.map +1 -1
- package/dist/cjs-types/cli/dev.d.ts +1 -0
- package/dist/cjs-types/cli/dev.d.ts.map +1 -1
- package/dist/cjs-types/cli/env.d.ts.map +1 -1
- package/dist/cjs-types/cli/envDefault.d.ts.map +1 -1
- package/dist/cjs-types/cli/generatedApi.d.ts +1 -1
- package/dist/cjs-types/cli/generatedApi.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/api.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/checkForLargeIndexBackfill.d.ts +30 -0
- package/dist/cjs-types/cli/lib/checkForLargeIndexBackfill.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/checkForLargeIndexDeletion.d.ts +5 -7
- package/dist/cjs-types/cli/lib/checkForLargeIndexDeletion.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/checkForSlowSchemaValidation.d.ts +4 -10
- package/dist/cjs-types/cli/lib/checkForSlowSchemaValidation.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/checkForStagedValidatorDeletion.d.ts +17 -0
- package/dist/cjs-types/cli/lib/checkForStagedValidatorDeletion.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/codegen.d.ts +0 -3
- package/dist/cjs-types/cli/lib/codegen.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/command.d.ts +2 -0
- package/dist/cjs-types/cli/lib/command.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/components/definition/bundle.d.ts +13 -0
- package/dist/cjs-types/cli/lib/components/definition/bundle.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/components.d.ts +4 -0
- package/dist/cjs-types/cli/lib/components.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/config.d.ts +2 -1
- package/dist/cjs-types/cli/lib/config.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/deploy2.d.ts +2 -0
- package/dist/cjs-types/cli/lib/deploy2.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/deployApi/evaluateSchema.d.ts +460 -16
- package/dist/cjs-types/cli/lib/deployApi/evaluateSchema.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/deployKeyWarning.d.ts +3 -0
- package/dist/cjs-types/cli/lib/deployKeyWarning.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/deployment.d.ts +2 -0
- package/dist/cjs-types/cli/lib/deployment.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/deploymentSelection.d.ts +2 -1
- package/dist/cjs-types/cli/lib/deploymentSelection.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/dev.d.ts +1 -0
- package/dist/cjs-types/cli/lib/dev.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/envvars.d.ts +6 -0
- package/dist/cjs-types/cli/lib/envvars.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/formatValidationProgress.d.ts +8 -0
- package/dist/cjs-types/cli/lib/formatValidationProgress.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/fsUtils.d.ts +1 -0
- package/dist/cjs-types/cli/lib/fsUtils.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/login.d.ts +3 -1
- package/dist/cjs-types/cli/lib/login.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/mcp/requestContext.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/mcp/tools/env.d.ts +8 -5
- package/dist/cjs-types/cli/lib/mcp/tools/env.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/mcp/tools/insights.d.ts +2 -2
- package/dist/cjs-types/cli/lib/profileManagement.d.ts +10 -0
- package/dist/cjs-types/cli/lib/profileManagement.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/profiles.d.ts +59 -0
- package/dist/cjs-types/cli/lib/profiles.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/run.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/schemaEvaluation.d.ts +33 -0
- package/dist/cjs-types/cli/lib/schemaEvaluation.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/usageLimits.d.ts +1 -1
- package/dist/cjs-types/cli/lib/usageLimits.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/utils/mutex.d.ts +1 -3
- package/dist/cjs-types/cli/lib/utils/mutex.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/utils/utils.d.ts +15 -2
- package/dist/cjs-types/cli/lib/utils/utils.d.ts.map +1 -1
- package/dist/cjs-types/cli/login.d.ts +21 -0
- package/dist/cjs-types/cli/login.d.ts.map +1 -1
- package/dist/cjs-types/cli/logout.d.ts +8 -1
- package/dist/cjs-types/cli/logout.d.ts.map +1 -1
- package/dist/cjs-types/cli/mcp.d.ts.map +1 -1
- package/dist/cjs-types/cli/program.d.ts.map +1 -1
- package/dist/cjs-types/index.d.ts +1 -1
- package/dist/cjs-types/index.d.ts.map +1 -1
- package/dist/cjs-types/server/impl/actions_impl.d.ts +18 -3
- package/dist/cjs-types/server/impl/actions_impl.d.ts.map +1 -1
- package/dist/cjs-types/server/impl/storage_impl.d.ts.map +1 -1
- package/dist/cjs-types/server/index.d.ts +1 -1
- package/dist/cjs-types/server/index.d.ts.map +1 -1
- package/dist/cjs-types/server/meta.d.ts +63 -0
- package/dist/cjs-types/server/meta.d.ts.map +1 -1
- package/dist/cjs-types/server/registration.d.ts +10 -0
- package/dist/cjs-types/server/registration.d.ts.map +1 -1
- package/dist/cjs-types/server/schema.d.ts +33 -0
- package/dist/cjs-types/server/schema.d.ts.map +1 -1
- package/dist/cjs-types/server/storage.d.ts.map +1 -1
- package/dist/cjs-types/values/value.d.ts.map +1 -1
- package/dist/cli.bundle.cjs +4889 -2980
- package/dist/cli.bundle.cjs.map +4 -4
- package/dist/esm/bundler/context.js +7 -5
- package/dist/esm/bundler/context.js.map +2 -2
- package/dist/esm/bundler/fs.js +47 -6
- package/dist/esm/bundler/fs.js.map +2 -2
- package/dist/esm/bundler/index.js +5 -4
- package/dist/esm/bundler/index.js.map +2 -2
- package/dist/esm/cli/account.js +221 -0
- package/dist/esm/cli/account.js.map +7 -0
- package/dist/esm/cli/codegen.js +0 -4
- package/dist/esm/cli/codegen.js.map +2 -2
- package/dist/esm/cli/configure.js +27 -6
- package/dist/esm/cli/configure.js.map +2 -2
- package/dist/esm/cli/deploy.js +27 -2
- package/dist/esm/cli/deploy.js.map +2 -2
- package/dist/esm/cli/deploymentSelect.js +6 -3
- package/dist/esm/cli/deploymentSelect.js.map +2 -2
- package/dist/esm/cli/dev.js +6 -0
- package/dist/esm/cli/dev.js.map +2 -2
- package/dist/esm/cli/env.js +11 -6
- package/dist/esm/cli/env.js.map +2 -2
- package/dist/esm/cli/envDefault.js +7 -2
- package/dist/esm/cli/envDefault.js.map +2 -2
- package/dist/esm/cli/lib/api.js +2 -0
- package/dist/esm/cli/lib/api.js.map +2 -2
- package/dist/esm/cli/lib/checkForLargeIndexBackfill.js +95 -0
- package/dist/esm/cli/lib/checkForLargeIndexBackfill.js.map +7 -0
- package/dist/esm/cli/lib/checkForLargeIndexDeletion.js +37 -48
- package/dist/esm/cli/lib/checkForLargeIndexDeletion.js.map +2 -2
- package/dist/esm/cli/lib/checkForSlowSchemaValidation.js +63 -41
- package/dist/esm/cli/lib/checkForSlowSchemaValidation.js.map +2 -2
- package/dist/esm/cli/lib/checkForStagedValidatorDeletion.js +68 -0
- package/dist/esm/cli/lib/checkForStagedValidatorDeletion.js.map +7 -0
- package/dist/esm/cli/lib/codegen.js.map +2 -2
- package/dist/esm/cli/lib/command.js +2 -1
- package/dist/esm/cli/lib/command.js.map +2 -2
- package/dist/esm/cli/lib/components/definition/bundle.js +37 -11
- package/dist/esm/cli/lib/components/definition/bundle.js.map +2 -2
- package/dist/esm/cli/lib/components.js +55 -5
- package/dist/esm/cli/lib/components.js.map +2 -2
- package/dist/esm/cli/lib/config.js +55 -17
- package/dist/esm/cli/lib/config.js.map +2 -2
- package/dist/esm/cli/lib/deploy2.js +3 -1
- package/dist/esm/cli/lib/deploy2.js.map +2 -2
- package/dist/esm/cli/lib/deployApi/evaluateSchema.js +28 -2
- package/dist/esm/cli/lib/deployApi/evaluateSchema.js.map +2 -2
- package/dist/esm/cli/lib/deployKeyWarning.js +27 -0
- package/dist/esm/cli/lib/deployKeyWarning.js.map +7 -0
- package/dist/esm/cli/lib/deployment.js +2 -2
- package/dist/esm/cli/lib/deployment.js.map +2 -2
- package/dist/esm/cli/lib/deploymentSelection.js +35 -20
- package/dist/esm/cli/lib/deploymentSelection.js.map +2 -2
- package/dist/esm/cli/lib/dev.js +5 -0
- package/dist/esm/cli/lib/dev.js.map +2 -2
- package/dist/esm/cli/lib/envvars.js +35 -1
- package/dist/esm/cli/lib/envvars.js.map +2 -2
- package/dist/esm/cli/lib/formatValidationProgress.js +24 -0
- package/dist/esm/cli/lib/formatValidationProgress.js.map +7 -0
- package/dist/esm/cli/lib/fsUtils.js +1 -1
- package/dist/esm/cli/lib/fsUtils.js.map +2 -2
- package/dist/esm/cli/lib/generateDocs.js +1 -1
- package/dist/esm/cli/lib/generateDocs.js.map +1 -1
- package/dist/esm/cli/lib/indexes.js.map +1 -1
- package/dist/esm/cli/lib/login.js +36 -4
- package/dist/esm/cli/lib/login.js.map +2 -2
- package/dist/esm/cli/lib/mcp/requestContext.js +5 -1
- package/dist/esm/cli/lib/mcp/requestContext.js.map +2 -2
- package/dist/esm/cli/lib/mcp/tools/env.js +10 -3
- package/dist/esm/cli/lib/mcp/tools/env.js.map +2 -2
- package/dist/esm/cli/lib/profileManagement.js +179 -0
- package/dist/esm/cli/lib/profileManagement.js.map +7 -0
- package/dist/esm/cli/lib/profiles.js +288 -0
- package/dist/esm/cli/lib/profiles.js.map +7 -0
- package/dist/esm/cli/lib/run.js +4 -0
- package/dist/esm/cli/lib/run.js.map +2 -2
- package/dist/esm/cli/lib/schemaEvaluation.js +39 -0
- package/dist/esm/cli/lib/schemaEvaluation.js.map +7 -0
- package/dist/esm/cli/lib/usageLimits.js +4 -2
- package/dist/esm/cli/lib/usageLimits.js.map +2 -2
- package/dist/esm/cli/lib/utils/mutex.js +9 -24
- package/dist/esm/cli/lib/utils/mutex.js.map +2 -2
- package/dist/esm/cli/lib/utils/utils.js +63 -27
- package/dist/esm/cli/lib/utils/utils.js.map +2 -2
- package/dist/esm/cli/login.js +225 -112
- package/dist/esm/cli/login.js.map +3 -3
- package/dist/esm/cli/logout.js +110 -13
- package/dist/esm/cli/logout.js.map +2 -2
- package/dist/esm/cli/mcp.js +34 -10
- package/dist/esm/cli/mcp.js.map +2 -2
- package/dist/esm/cli/program.js +2 -1
- package/dist/esm/cli/program.js.map +2 -2
- package/dist/esm/cli/projectCreate.js +1 -1
- package/dist/esm/cli/projectCreate.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/server/impl/actions_impl.js +7 -3
- package/dist/esm/server/impl/actions_impl.js.map +2 -2
- package/dist/esm/server/impl/storage_impl.js +29 -0
- package/dist/esm/server/impl/storage_impl.js.map +2 -2
- package/dist/esm/server/index.js +4 -1
- package/dist/esm/server/index.js.map +2 -2
- package/dist/esm/server/schema.js +34 -12
- package/dist/esm/server/schema.js.map +2 -2
- package/dist/esm/values/validators.js +1 -1
- package/dist/esm/values/validators.js.map +2 -2
- package/dist/esm/values/value.js +6 -0
- package/dist/esm/values/value.js.map +2 -2
- package/dist/esm-types/bundler/context.d.ts +5 -0
- package/dist/esm-types/bundler/context.d.ts.map +1 -1
- package/dist/esm-types/bundler/fs.d.ts +7 -2
- package/dist/esm-types/bundler/fs.d.ts.map +1 -1
- package/dist/esm-types/bundler/index.d.ts +9 -2
- package/dist/esm-types/bundler/index.d.ts.map +1 -1
- package/dist/esm-types/cli/account.d.ts +6 -0
- package/dist/esm-types/cli/account.d.ts.map +1 -0
- package/dist/esm-types/cli/codegen.d.ts.map +1 -1
- package/dist/esm-types/cli/configure.d.ts +6 -0
- package/dist/esm-types/cli/configure.d.ts.map +1 -1
- package/dist/esm-types/cli/deploy.d.ts +2 -0
- package/dist/esm-types/cli/deploy.d.ts.map +1 -1
- package/dist/esm-types/cli/deploymentCreate.d.ts +6 -6
- package/dist/esm-types/cli/deploymentSelect.d.ts.map +1 -1
- package/dist/esm-types/cli/dev.d.ts +1 -0
- package/dist/esm-types/cli/dev.d.ts.map +1 -1
- package/dist/esm-types/cli/env.d.ts.map +1 -1
- package/dist/esm-types/cli/envDefault.d.ts.map +1 -1
- package/dist/esm-types/cli/generatedApi.d.ts +1 -1
- package/dist/esm-types/cli/generatedApi.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/api.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/checkForLargeIndexBackfill.d.ts +30 -0
- package/dist/esm-types/cli/lib/checkForLargeIndexBackfill.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/checkForLargeIndexDeletion.d.ts +5 -7
- package/dist/esm-types/cli/lib/checkForLargeIndexDeletion.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/checkForSlowSchemaValidation.d.ts +4 -10
- package/dist/esm-types/cli/lib/checkForSlowSchemaValidation.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/checkForStagedValidatorDeletion.d.ts +17 -0
- package/dist/esm-types/cli/lib/checkForStagedValidatorDeletion.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/codegen.d.ts +0 -3
- package/dist/esm-types/cli/lib/codegen.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/command.d.ts +2 -0
- package/dist/esm-types/cli/lib/command.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/components/definition/bundle.d.ts +13 -0
- package/dist/esm-types/cli/lib/components/definition/bundle.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/components.d.ts +4 -0
- package/dist/esm-types/cli/lib/components.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/config.d.ts +2 -1
- package/dist/esm-types/cli/lib/config.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/deploy2.d.ts +2 -0
- package/dist/esm-types/cli/lib/deploy2.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/deployApi/evaluateSchema.d.ts +460 -16
- package/dist/esm-types/cli/lib/deployApi/evaluateSchema.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/deployKeyWarning.d.ts +3 -0
- package/dist/esm-types/cli/lib/deployKeyWarning.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/deployment.d.ts +2 -0
- package/dist/esm-types/cli/lib/deployment.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/deploymentSelection.d.ts +2 -1
- package/dist/esm-types/cli/lib/deploymentSelection.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/dev.d.ts +1 -0
- package/dist/esm-types/cli/lib/dev.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/envvars.d.ts +6 -0
- package/dist/esm-types/cli/lib/envvars.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/formatValidationProgress.d.ts +8 -0
- package/dist/esm-types/cli/lib/formatValidationProgress.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/fsUtils.d.ts +1 -0
- package/dist/esm-types/cli/lib/fsUtils.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/login.d.ts +3 -1
- package/dist/esm-types/cli/lib/login.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/mcp/requestContext.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/mcp/tools/env.d.ts +8 -5
- package/dist/esm-types/cli/lib/mcp/tools/env.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/mcp/tools/insights.d.ts +2 -2
- package/dist/esm-types/cli/lib/profileManagement.d.ts +10 -0
- package/dist/esm-types/cli/lib/profileManagement.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/profiles.d.ts +59 -0
- package/dist/esm-types/cli/lib/profiles.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/run.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/schemaEvaluation.d.ts +33 -0
- package/dist/esm-types/cli/lib/schemaEvaluation.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/usageLimits.d.ts +1 -1
- package/dist/esm-types/cli/lib/usageLimits.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/utils/mutex.d.ts +1 -3
- package/dist/esm-types/cli/lib/utils/mutex.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/utils/utils.d.ts +15 -2
- package/dist/esm-types/cli/lib/utils/utils.d.ts.map +1 -1
- package/dist/esm-types/cli/login.d.ts +21 -0
- package/dist/esm-types/cli/login.d.ts.map +1 -1
- package/dist/esm-types/cli/logout.d.ts +8 -1
- package/dist/esm-types/cli/logout.d.ts.map +1 -1
- package/dist/esm-types/cli/mcp.d.ts.map +1 -1
- package/dist/esm-types/cli/program.d.ts.map +1 -1
- package/dist/esm-types/index.d.ts +1 -1
- package/dist/esm-types/index.d.ts.map +1 -1
- package/dist/esm-types/server/impl/actions_impl.d.ts +18 -3
- package/dist/esm-types/server/impl/actions_impl.d.ts.map +1 -1
- package/dist/esm-types/server/impl/storage_impl.d.ts.map +1 -1
- package/dist/esm-types/server/index.d.ts +1 -1
- package/dist/esm-types/server/index.d.ts.map +1 -1
- package/dist/esm-types/server/meta.d.ts +63 -0
- package/dist/esm-types/server/meta.d.ts.map +1 -1
- package/dist/esm-types/server/registration.d.ts +10 -0
- package/dist/esm-types/server/registration.d.ts.map +1 -1
- package/dist/esm-types/server/schema.d.ts +33 -0
- package/dist/esm-types/server/schema.d.ts.map +1 -1
- package/dist/esm-types/server/storage.d.ts.map +1 -1
- package/dist/esm-types/values/value.d.ts.map +1 -1
- package/dist/react.bundle.js +7 -1
- package/dist/react.bundle.js.map +2 -2
- package/package.json +5 -5
- package/schemas/convex.schema.json +5 -5
- package/src/bundler/context.ts +9 -5
- package/src/bundler/fs.ts +54 -5
- package/src/bundler/index.ts +9 -4
- package/src/cli/account.ts +320 -0
- package/src/cli/codegen.ts +0 -2
- package/src/cli/configure.ts +45 -9
- package/src/cli/deploy.ts +36 -5
- package/src/cli/deploymentSelect.ts +7 -4
- package/src/cli/dev.ts +9 -0
- package/src/cli/env.ts +12 -6
- package/src/cli/envDefault.ts +8 -2
- package/src/cli/generatedApi.ts +1 -1
- package/src/cli/lib/api.ts +5 -1
- package/src/cli/lib/checkForLargeIndexBackfill.ts +173 -0
- package/src/cli/lib/checkForLargeIndexDeletion.ts +45 -58
- package/src/cli/lib/checkForSlowSchemaValidation.ts +76 -65
- package/src/cli/lib/checkForStagedValidatorDeletion.ts +104 -0
- package/src/cli/lib/codegen.ts +0 -3
- package/src/cli/lib/command.ts +3 -0
- package/src/cli/lib/components/definition/bundle.ts +68 -14
- package/src/cli/lib/components.ts +71 -4
- package/src/cli/lib/config.ts +85 -18
- package/src/cli/lib/deploy2.ts +10 -1
- package/src/cli/lib/deployApi/evaluateSchema.ts +35 -0
- package/src/cli/lib/deployKeyWarning.ts +43 -0
- package/src/cli/lib/deployment.ts +2 -2
- package/src/cli/lib/deploymentSelection.ts +37 -18
- package/src/cli/lib/dev.ts +14 -0
- package/src/cli/lib/envvars.ts +43 -1
- package/src/cli/lib/formatValidationProgress.ts +35 -0
- package/src/cli/lib/fsUtils.ts +5 -2
- package/src/cli/lib/generateDocs.ts +1 -1
- package/src/cli/lib/indexes.ts +1 -1
- package/src/cli/lib/login.ts +47 -3
- package/src/cli/lib/mcp/requestContext.ts +7 -1
- package/src/cli/lib/mcp/tools/env.ts +17 -3
- package/src/cli/lib/profileManagement.ts +262 -0
- package/src/cli/lib/profiles.ts +398 -0
- package/src/cli/lib/run.ts +2 -0
- package/src/cli/lib/schemaEvaluation.ts +88 -0
- package/src/cli/lib/usageLimits.ts +2 -0
- package/src/cli/lib/utils/mutex.ts +9 -27
- package/src/cli/lib/utils/utils.ts +83 -36
- package/src/cli/login.ts +293 -168
- package/src/cli/logout.ts +142 -17
- package/src/cli/mcp.ts +48 -11
- package/src/cli/program.ts +2 -0
- package/src/cli/projectCreate.ts +1 -1
- package/src/index.ts +1 -1
- package/src/server/impl/actions_impl.ts +26 -6
- package/src/server/impl/storage_impl.ts +30 -0
- package/src/server/index.ts +5 -1
- package/src/server/meta.ts +56 -2
- package/src/server/registration.ts +10 -0
- package/src/server/schema.ts +37 -15
- package/src/server/storage.ts +17 -0
- package/src/values/validators.ts +1 -1
- package/src/values/value.ts +9 -5
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { chalkStderr } from "chalk";
|
|
3
|
+
export function formatValidationProgress({
|
|
4
|
+
numDocsValidated,
|
|
5
|
+
totalDocs
|
|
6
|
+
}) {
|
|
7
|
+
const checked = numDocsValidated.toLocaleString();
|
|
8
|
+
return totalDocs === null || totalDocs === void 0 ? `${checked} documents checked` : `${checked} of approximately ${totalDocs.toLocaleString()} documents checked`;
|
|
9
|
+
}
|
|
10
|
+
export function formatDiscardedStagedValidator(validator) {
|
|
11
|
+
let status;
|
|
12
|
+
switch (validator.state.state) {
|
|
13
|
+
case "pending": {
|
|
14
|
+
status = `validating in the background (${formatValidationProgress(validator.state)})`;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
case "valid":
|
|
18
|
+
status = chalkStderr.green("validated");
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
const action = validator.replaced ? "the push stages a different validator" : "the push removes the staged validator";
|
|
22
|
+
return `${status}; ${action}`;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=formatValidationProgress.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/cli/lib/formatValidationProgress.ts"],
|
|
4
|
+
"sourcesContent": ["import { chalkStderr } from \"chalk\";\nimport { DiscardedStagedValidator } from \"./deployApi/evaluateSchema.js\";\n\nexport function formatValidationProgress({\n numDocsValidated,\n totalDocs,\n}: {\n numDocsValidated: number;\n totalDocs?: number | null | undefined;\n}): string {\n const checked = numDocsValidated.toLocaleString();\n return totalDocs === null || totalDocs === undefined\n ? `${checked} documents checked`\n : `${checked} of approximately ${totalDocs.toLocaleString()} documents checked`;\n}\n\n/** \"validated; the push removes the staged validator\" */\nexport function formatDiscardedStagedValidator(\n validator: DiscardedStagedValidator,\n): string {\n let status;\n switch (validator.state.state) {\n case \"pending\": {\n status = `validating in the background (${formatValidationProgress(validator.state)})`;\n break;\n }\n case \"valid\":\n status = chalkStderr.green(\"validated\");\n break;\n }\n const action = validator.replaced\n ? \"the push stages a different validator\"\n : \"the push removes the staged validator\";\n return `${status}; ${action}`;\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,mBAAmB;AAGrB,gBAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AACF,GAGW;AACT,QAAM,UAAU,iBAAiB,eAAe;AAChD,SAAO,cAAc,QAAQ,cAAc,SACvC,GAAG,OAAO,uBACV,GAAG,OAAO,qBAAqB,UAAU,eAAe,CAAC;AAC/D;AAGO,gBAAS,+BACd,WACQ;AACR,MAAI;AACJ,UAAQ,UAAU,MAAM,OAAO;AAAA,IAC7B,KAAK,WAAW;AACd,eAAS,iCAAiC,yBAAyB,UAAU,KAAK,CAAC;AACnF;AAAA,IACF;AAAA,IACA,KAAK;AACH,eAAS,YAAY,MAAM,WAAW;AACtC;AAAA,EACJ;AACA,QAAM,SAAS,UAAU,WACrB,0CACA;AACJ,SAAO,GAAG,MAAM,KAAK,MAAM;AAC7B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -5,7 +5,7 @@ export function recursivelyDelete(ctx, deletePath, opts) {
|
|
|
5
5
|
const dryRun = !!opts?.dryRun;
|
|
6
6
|
let st;
|
|
7
7
|
try {
|
|
8
|
-
st = ctx.fs.stat(deletePath);
|
|
8
|
+
st = opts?.followSymlinks === false ? ctx.fs.lstat(deletePath) : ctx.fs.stat(deletePath);
|
|
9
9
|
} catch (err) {
|
|
10
10
|
if (err.code === "ENOENT" && opts?.force) {
|
|
11
11
|
return;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/cli/lib/fsUtils.ts"],
|
|
4
|
-
"sourcesContent": ["import { Context } from \"../../bundler/context.js\";\nimport { logOutput } from \"../../bundler/log.js\";\nimport path from \"path\";\nimport { NodeFs } from \"../../bundler/fs.js\";\n\nexport function recursivelyDelete(\n ctx: Context,\n deletePath: string,\n opts?: { force?: boolean; dryRun?: boolean },\n) {\n const dryRun = !!opts?.dryRun;\n let st;\n try {\n st
|
|
5
|
-
"mappings": ";AACA,SAAS,iBAAiB;AAC1B,OAAO,UAAU;AAGV,gBAAS,kBACd,KACA,YACA,MACA;AACA,QAAM,SAAS,CAAC,CAAC,MAAM;AACvB,MAAI;AACJ,MAAI;AACF,
|
|
4
|
+
"sourcesContent": ["import { Context } from \"../../bundler/context.js\";\nimport { logOutput } from \"../../bundler/log.js\";\nimport path from \"path\";\nimport { NodeFs } from \"../../bundler/fs.js\";\n\nexport function recursivelyDelete(\n ctx: Context,\n deletePath: string,\n opts?: { force?: boolean; dryRun?: boolean; followSymlinks?: boolean },\n) {\n const dryRun = !!opts?.dryRun;\n let st;\n try {\n st =\n opts?.followSymlinks === false\n ? ctx.fs.lstat(deletePath)\n : ctx.fs.stat(deletePath);\n } catch (err: any) {\n if (err.code === \"ENOENT\" && opts?.force) {\n return;\n }\n // eslint-disable-next-line no-restricted-syntax\n throw err;\n }\n if (st.isDirectory()) {\n for (const entry of ctx.fs.listDir(deletePath)) {\n recursivelyDelete(ctx, path.join(deletePath, entry.name), opts);\n }\n if (dryRun) {\n logOutput(`Command would delete directory: ${deletePath}`);\n return;\n }\n try {\n ctx.fs.rmdir(deletePath);\n } catch (err: any) {\n if (err.code !== \"ENOENT\") {\n // eslint-disable-next-line no-restricted-syntax\n throw err;\n }\n }\n } else {\n if (dryRun) {\n logOutput(`Command would delete file: ${deletePath}`);\n return;\n }\n try {\n ctx.fs.unlink(deletePath);\n } catch (err: any) {\n if (err.code !== \"ENOENT\") {\n // eslint-disable-next-line no-restricted-syntax\n throw err;\n }\n }\n }\n}\n\nexport async function recursivelyCopy(\n ctx: Context,\n nodeFs: NodeFs,\n src: string,\n dest: string,\n) {\n const st = nodeFs.stat(src);\n if (st.isDirectory()) {\n nodeFs.mkdir(dest, { recursive: true });\n for (const entry of nodeFs.listDir(src)) {\n await recursivelyCopy(\n ctx,\n nodeFs,\n path.join(src, entry.name),\n path.join(dest, entry.name),\n );\n }\n } else {\n // Don't use writeUtf8File to allow copying arbitrary files\n await nodeFs.writeFileStream(dest, nodeFs.createReadStream(src, {}));\n }\n}\n"],
|
|
5
|
+
"mappings": ";AACA,SAAS,iBAAiB;AAC1B,OAAO,UAAU;AAGV,gBAAS,kBACd,KACA,YACA,MACA;AACA,QAAM,SAAS,CAAC,CAAC,MAAM;AACvB,MAAI;AACJ,MAAI;AACF,SACE,MAAM,mBAAmB,QACrB,IAAI,GAAG,MAAM,UAAU,IACvB,IAAI,GAAG,KAAK,UAAU;AAAA,EAC9B,SAAS,KAAU;AACjB,QAAI,IAAI,SAAS,YAAY,MAAM,OAAO;AACxC;AAAA,IACF;AAEA,UAAM;AAAA,EACR;AACA,MAAI,GAAG,YAAY,GAAG;AACpB,eAAW,SAAS,IAAI,GAAG,QAAQ,UAAU,GAAG;AAC9C,wBAAkB,KAAK,KAAK,KAAK,YAAY,MAAM,IAAI,GAAG,IAAI;AAAA,IAChE;AACA,QAAI,QAAQ;AACV,gBAAU,mCAAmC,UAAU,EAAE;AACzD;AAAA,IACF;AACA,QAAI;AACF,UAAI,GAAG,MAAM,UAAU;AAAA,IACzB,SAAS,KAAU;AACjB,UAAI,IAAI,SAAS,UAAU;AAEzB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI,QAAQ;AACV,gBAAU,8BAA8B,UAAU,EAAE;AACpD;AAAA,IACF;AACA,QAAI;AACF,UAAI,GAAG,OAAO,UAAU;AAAA,IAC1B,SAAS,KAAU;AACjB,UAAI,IAAI,SAAS,UAAU;AAEzB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEA,sBAAsB,gBACpB,KACA,QACA,KACA,MACA;AACA,QAAM,KAAK,OAAO,KAAK,GAAG;AAC1B,MAAI,GAAG,YAAY,GAAG;AACpB,WAAO,MAAM,MAAM,EAAE,WAAW,KAAK,CAAC;AACtC,eAAW,SAAS,OAAO,QAAQ,GAAG,GAAG;AACvC,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA,KAAK,KAAK,KAAK,MAAM,IAAI;AAAA,QACzB,KAAK,KAAK,MAAM,MAAM,IAAI;AAAA,MAC5B;AAAA,IACF;AAAA,EACF,OAAO;AAEL,UAAM,OAAO,gBAAgB,MAAM,OAAO,iBAAiB,KAAK,CAAC,CAAC,CAAC;AAAA,EACrE;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -178,7 +178,7 @@ function escapeMdx(text) {
|
|
|
178
178
|
function renderCopyableCommands(text) {
|
|
179
179
|
return text.split("\n").map(
|
|
180
180
|
(line) => /^- /.test(line) ? line.replace(
|
|
181
|
-
/`(npx convex [^`]*)`/g,
|
|
181
|
+
/`(npx convex(?:@[^\s`]+)? [^`]*)`/g,
|
|
182
182
|
(_, command) => `<CodeWithCopyButton text={${JSON.stringify(command)}} />`
|
|
183
183
|
) : line
|
|
184
184
|
).join("\n");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/cli/lib/generateDocs.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CommandUnknownOpts } from \"@commander-js/extra-typings\";\n\nexport type GeneratedDocs = Record<string, string>;\n\ntype CommandInfo = {\n command: CommandUnknownOpts;\n // Full path of command names from the root, e.g. [\"convex\", \"env\", \"set\"].\n path: string[];\n};\n\n/**\n * Generate Markdown reference docs for a Commander main command.\n *\n * Returns a map of file paths (relative, e.g. `env.mdx`) to Markdown\n * contents. One file is generated for each visible main command (a direct\n * child of the root); the root itself gets no page, so \"Command Reference\"\n * is a sidebar section with no landing page. Descendant subcommands are\n * rendered as sections inside their main command's file, with their heading\n * level reflecting their depth: a direct subcommand (`env default`) is an\n * `## h2`, a sub-subcommand (`env default set`) an `### h3`, and so on.\n *\n * Each page carries a `description` frontmatter equal to the command's\n * summary; the `/cli` page reads these back via Docusaurus metadata to render\n * the list of commands dynamically.\n */\nexport function generateDocs(root: CommandUnknownOpts): GeneratedDocs {\n const docs: GeneratedDocs = {};\n const all = collectCommands(root, [root.name()]);\n\n let mainCommandPosition = 0;\n for (const entry of all) {\n // Skip the root command (no landing page) and any descendant beyond a\n // main command (those are rendered inside their main command's file).\n if (entry.path.length !== 2) continue;\n const filePath = `${entry.path[1]}.mdx`;\n const sidebarPosition = ++mainCommandPosition;\n const summary =\n entry.command.summary() || entry.command.description() || \"\";\n // Collapse to a single line so it's a valid YAML frontmatter scalar, and\n // quote it safely (summaries contain `[BETA]`, `:`, etc.).\n const description = JSON.stringify(summary.replace(/\\s+/g, \" \").trim());\n\n const lines: string[] = [];\n const sidebarLabel = `npx ${entry.path.join(\" \")}`;\n lines.push(\"---\");\n lines.push(`sidebar_position: ${sidebarPosition}`);\n // Set an explicit `title` so the Docusaurus <title> (and browser tab) reads\n // the full command, e.g. `npx convex dev | \u2026`. Without it Docusaurus\n // derives the title from the doc id (the file name), which would be just\n // `dev`.\n lines.push(`title: \"${sidebarLabel}\"`);\n lines.push(`sidebar_label: \"${sidebarLabel}\"`);\n lines.push(`description: ${description}`);\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(\n \"{/* @generated from the command definitions, do not edit manually (run `just regenerate-cli-docs` to regenerate) */}\",\n );\n lines.push(\"\");\n lines.push(renderCommand(entry, all, { headingLevel: 1 }));\n\n const descendants = all.filter(\n (e) =>\n e.path.length > entry.path.length &&\n entry.path.every((p, i) => e.path[i] === p),\n );\n for (const d of descendants) {\n // Render the heading hierarchically by depth below the root: a direct\n // subcommand (`env default`, path length 3) is an h2, a sub-subcommand\n // (`env default set`, path length 4) is an h3, and so on. This nests\n // sub-subcommands under their parent group instead of flattening every\n // descendant to the same h2 level.\n lines.push(\n renderCommand(d, all, {\n headingLevel: d.path.length - 1,\n includeSubcommandsList: false,\n }),\n );\n }\n\n docs[filePath] = lines.join(\"\\n\");\n }\n\n return docs;\n}\n\nfunction collectCommands(\n command: CommandUnknownOpts,\n path: string[],\n): CommandInfo[] {\n const result: CommandInfo[] = [{ command, path }];\n for (const sub of command.commands) {\n // Skip hidden commands and Commander's built-in help command.\n if ((sub as any)._hidden) continue;\n if (sub.name() === \"help\") continue;\n result.push(...collectCommands(sub, [...path, sub.name()]));\n }\n return result;\n}\n\nfunction displayName(path: string[]): string {\n return `npx ${path.join(\" \")}`;\n}\n\n// Build the usage suffix (everything after the command name) for the Syntax\n// code block. We derive the argument portion from the command's registered\n// arguments rather than trusting a manual `.usage()` override, so the Syntax\n// line always agrees with the Arguments section below. For example `env set`\n// overrides `.usage()` to show `<name> <value>` (pretending the args are\n// required) for nicer `--help` output, even though it registers them as\n// optional `[name] [value]`; reproducing the override verbatim would make the\n// generated page contradict itself. Commands with no registered arguments keep\n// their `.usage()` string verbatim (e.g. the root's `<command> [options]`).\nfunction commandUsage(command: CommandUnknownOpts): string {\n const args = (command as any).registeredArguments ?? [];\n if (args.length === 0) {\n return command.usage();\n }\n // Mirror Commander's default usage order: options, then a subcommand\n // placeholder, then the positional arguments. `[options]` is always present\n // because the built-in `--help` option is always registered.\n const parts = [\"[options]\"];\n if (command.commands.length > 0) {\n parts.push(\"[command]\");\n }\n for (const arg of args) {\n const name = `${arg._name}${arg.variadic ? \"...\" : \"\"}`;\n parts.push(arg.required ? `<${name}>` : `[${name}]`);\n }\n return parts.join(\" \");\n}\n\n// Anchor id for a descendant command rendered as an h2 section inside its\n// main command's file. Built from the path segments below the main command,\n// joined with `-`, so sub-subcommands stay unique. For example, both\n// `deployment create` and `deployment token create` would collide on `#create`\n// if we used only the leaf name; instead they become `#create` and\n// `#token-create`.\nfunction anchorSlug(path: string[]): string {\n return path.slice(2).join(\"-\");\n}\n\n// Link target for a subcommand listed inside a command's \"Subcommands\"\n// section. From the root index, main commands live in sibling files. From a\n// main command page, descendants are rendered as h2 sections in the same\n// file, anchored by their path below the main command.\nfunction subcommandLink(parentPath: string[], subPath: string[]): string {\n if (parentPath.length === 1) {\n return `./${subPath[1]}`;\n }\n return `#${anchorSlug(subPath)}`;\n}\n\nfunction renderCommand(\n entry: CommandInfo,\n all: CommandInfo[],\n options: { headingLevel: number; includeSubcommandsList?: boolean },\n): string {\n const { headingLevel, includeSubcommandsList = true } = options;\n const h1 = \"#\".repeat(headingLevel);\n const h2 = \"#\".repeat(headingLevel + 1);\n\n const { command, path } = entry;\n const display = displayName(path);\n const description = renderCopyableCommands(\n escapeMdx(\n formatExampleLines(\n replaceBullets(command.description() || command.summary() || \"\"),\n ),\n ),\n );\n\n const lines: string[] = [];\n // For nested subcommand sections, pin the heading id to the path below the\n // main command so anchors like `#set` and `#token-create` stay unique even\n // when leaf names collide across different parents.\n const headingSuffix = headingLevel > 1 ? ` \\\\{#${anchorSlug(path)}}` : \"\";\n lines.push(`${h1} \\`${display}\\`${headingSuffix}`);\n lines.push(\"\");\n if (description) {\n lines.push(description);\n lines.push(\"\");\n }\n\n const usage = commandUsage(command);\n lines.push(`${h2} Syntax`);\n lines.push(\"\");\n lines.push(\"```sh\");\n lines.push(`${display} ${usage}`.trim());\n lines.push(\"```\");\n lines.push(\"\");\n\n const aliases = command.aliases();\n if (aliases.length > 0) {\n lines.push(`${h2} Aliases`);\n lines.push(\"\");\n for (const alias of aliases) {\n lines.push(`- \\`${alias}\\``);\n }\n lines.push(\"\");\n }\n\n const args = (command as any).registeredArguments ?? [];\n if (args.length > 0) {\n lines.push(`${h2} Arguments`);\n lines.push(\"\");\n lines.push(\"<dl>\");\n for (const arg of args) {\n const name = arg.required ? `<${arg._name}>` : `[${arg._name}]`;\n const desc = escapeMdx(replaceBullets(arg.description || \"\"));\n lines.push(`<dt>\\`${name}\\`</dt>`);\n lines.push(`<dd>`);\n lines.push(\"\");\n lines.push(desc);\n lines.push(\"\");\n lines.push(`</dd>`);\n }\n lines.push(\"</dl>\");\n lines.push(\"\");\n }\n\n const opts = command.options.filter((o: any) => !o.hidden);\n if (opts.length > 0) {\n lines.push(`${h2} Options`);\n lines.push(\"\");\n lines.push(\"<dl>\");\n for (const opt of opts) {\n const flags = (opt as any).flags as string;\n const desc = escapeMdx(replaceBullets(opt.description || \"\"));\n lines.push(`<dt>\\`${flags}\\`</dt>`);\n lines.push(`<dd>`);\n lines.push(\"\");\n lines.push(desc);\n lines.push(\"\");\n lines.push(`</dd>`);\n }\n lines.push(\"</dl>\");\n lines.push(\"\");\n }\n\n if (includeSubcommandsList) {\n const subEntries = all.filter(\n (e) =>\n e.path.length === path.length + 1 &&\n path.every((p, i) => e.path[i] === p),\n );\n if (subEntries.length > 0) {\n lines.push(`${h2} Subcommands`);\n lines.push(\"\");\n for (const sub of subEntries) {\n const subDisplay = displayName(sub.path);\n const target = subcommandLink(path, sub.path);\n const subDesc = indentContinuation(\n escapeMdx(sub.command.summary() || sub.command.description() || \"\"),\n );\n lines.push(`- [\\`${subDisplay}\\`](${target}) \u2014 ${subDesc}`.trimEnd());\n }\n lines.push(\"\");\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n// Escape characters that MDX would otherwise parse as JSX. Backslash-escaping\n// `<` and `{` keeps placeholder text like `<team_slug>` rendering as literal\n// text instead of being interpreted as a tag or expression.\n//\n// MDX only parses `<` and `{` specially in prose \u2014 inside an inline code span\n// (backticks) both are already literal, and a backslash there renders verbatim\n// (e.g. `` `\\<nameOrToken>` `` shows the backslash). So leave code spans\n// untouched and escape only the surrounding prose.\nfunction escapeMdx(text: string): string {\n return text\n .split(/(`[^`]*`)/)\n .map((segment, i) =>\n // Odd indices are the captured code spans; even indices are prose.\n i % 2 === 1 ? segment : segment.replace(/[<{]/g, (c) => `\\\\${c}`),\n )\n .join(\"\");\n}\n\n// Turn inline code spans that are full `npx convex ...` commands into a\n// CodeWithCopyButton component so readers can copy them with one click. The\n// component is registered globally in the docs site's MDXComponents, so no\n// import is needed in the generated page. This runs after escapeMdx, which\n// leaves code spans verbatim, so the command text inside the backticks is\n// unescaped and drops straight into the `text` attribute.\n//\n// We pass the command as a JSX expression containing a JSON-encoded string\n// (`text={\"...\"}`) rather than a plain attribute (`text=\"...\"`) because\n// commands routinely contain double quotes (e.g. JSON arguments like\n// `'{\"body\": \"hello\"}'`), which would otherwise terminate the attribute value\n// and produce invalid MDX. JSON.stringify escapes quotes and backslashes for\n// us.\nfunction renderCopyableCommands(text: string): string {\n return text\n .split(\"\\n\")\n .map((line) =>\n /^- /.test(line)\n ? line.replace(\n /`(npx convex [^`]*)`/g,\n (_, command) =>\n `<CodeWithCopyButton text={${JSON.stringify(command)}} />`,\n )\n : line,\n )\n .join(\"\\n\");\n}\n\n// Replace \"\u2022\" bullet points with markdown \"-\" bullet points. Every line that is\n// (maybe leading spaces +) \"\u2022 \" becomes the same spaces + \"- \". This runs before\n// formatExampleLines and renderCopyableCommands so that `npx convex ...` commands\n// in bulleted help text are recognized as list items and get a copy button.\nexport function replaceBullets(text: string): string {\n return text.replace(/^( *)\u2022 /gm, \"$1- \");\n}\n\n// Convert indented example lines (e.g., from CLI help text) into markdown lists\n// so they render with proper line breaks instead of collapsing into one line.\n// Consecutive indented lines are gathered into a block; any line indented by at\n// least two spaces belongs to the block, regardless of how deeply it nests.\n//\n// How much the block is dedented depends on what precedes it:\n// - When the block follows a list item, its indentation encodes real nesting\n// (a sub-list under that item), so it is preserved verbatim. This keeps a\n// 3-level list like the deploy command's preview-key description intact\n// instead of flattening the 2-space sub-item to a top-level bullet.\n// - When the block follows prose (or starts the text), the indentation is\n// just help-text formatting, so the block is dedented by its smallest\n// indent to the left margin. Otherwise an indented list wouldn't interrupt\n// the preceding paragraph and would collapse into it.\nfunction formatExampleLines(text: string): string {\n const lines = text.split(\"\\n\");\n const result: string[] = [];\n let blockLines: string[] = [];\n\n const flushBlock = () => {\n if (blockLines.length === 0) {\n return;\n }\n const prev = result[result.length - 1];\n const followsListItem = prev !== undefined && isListItem(prev);\n const dedent = followsListItem\n ? 0\n : Math.min(...blockLines.map(indentWidth));\n for (const blockLine of blockLines) {\n result.push(toListItem(blockLine.substring(dedent)));\n }\n blockLines = [];\n };\n\n for (const line of lines) {\n // Any line indented by at least two spaces (and not blank) is part of an\n // example block, regardless of nesting depth.\n if (/^ {2,}\\S/.test(line)) {\n blockLines.push(line);\n } else {\n flushBlock();\n result.push(line);\n }\n }\n flushBlock();\n\n return result.join(\"\\n\");\n}\n\nfunction indentWidth(line: string): number {\n return line.length - line.trimStart().length;\n}\n\nfunction isListItem(line: string): boolean {\n const content = line.trimStart();\n return content.startsWith(\"- \") || /^\\d+\\.\\s/.test(content);\n}\n\n// Render an example line as a markdown list item, preserving any leading indent\n// so nested items stay nested. Lines that are already list items \u2014 either a\n// bullet (`- `) or an ordered-list item (`1. `) \u2014 are kept verbatim so they\n// render as their intended list type. Prefixing an ordered-list item with `- `\n// would nest it inside a bullet, which renders as roman numerals instead of the\n// numbered steps.\nfunction toListItem(line: string): string {\n if (isListItem(line)) {\n return line;\n }\n const indent = line.slice(0, indentWidth(line));\n return `${indent}- ${line.trimStart()}`;\n}\n\nfunction indentContinuation(text: string): string {\n return text.replace(/\\n/g, \"\\n \");\n}\n"],
|
|
4
|
+
"sourcesContent": ["import type { CommandUnknownOpts } from \"@commander-js/extra-typings\";\n\nexport type GeneratedDocs = Record<string, string>;\n\ntype CommandInfo = {\n command: CommandUnknownOpts;\n // Full path of command names from the root, e.g. [\"convex\", \"env\", \"set\"].\n path: string[];\n};\n\n/**\n * Generate Markdown reference docs for a Commander main command.\n *\n * Returns a map of file paths (relative, e.g. `env.mdx`) to Markdown\n * contents. One file is generated for each visible main command (a direct\n * child of the root); the root itself gets no page, so \"Command Reference\"\n * is a sidebar section with no landing page. Descendant subcommands are\n * rendered as sections inside their main command's file, with their heading\n * level reflecting their depth: a direct subcommand (`env default`) is an\n * `## h2`, a sub-subcommand (`env default set`) an `### h3`, and so on.\n *\n * Each page carries a `description` frontmatter equal to the command's\n * summary; the `/cli` page reads these back via Docusaurus metadata to render\n * the list of commands dynamically.\n */\nexport function generateDocs(root: CommandUnknownOpts): GeneratedDocs {\n const docs: GeneratedDocs = {};\n const all = collectCommands(root, [root.name()]);\n\n let mainCommandPosition = 0;\n for (const entry of all) {\n // Skip the root command (no landing page) and any descendant beyond a\n // main command (those are rendered inside their main command's file).\n if (entry.path.length !== 2) continue;\n const filePath = `${entry.path[1]}.mdx`;\n const sidebarPosition = ++mainCommandPosition;\n const summary =\n entry.command.summary() || entry.command.description() || \"\";\n // Collapse to a single line so it's a valid YAML frontmatter scalar, and\n // quote it safely (summaries contain `[BETA]`, `:`, etc.).\n const description = JSON.stringify(summary.replace(/\\s+/g, \" \").trim());\n\n const lines: string[] = [];\n const sidebarLabel = `npx ${entry.path.join(\" \")}`;\n lines.push(\"---\");\n lines.push(`sidebar_position: ${sidebarPosition}`);\n // Set an explicit `title` so the Docusaurus <title> (and browser tab) reads\n // the full command, e.g. `npx convex dev | \u2026`. Without it Docusaurus\n // derives the title from the doc id (the file name), which would be just\n // `dev`.\n lines.push(`title: \"${sidebarLabel}\"`);\n lines.push(`sidebar_label: \"${sidebarLabel}\"`);\n lines.push(`description: ${description}`);\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(\n \"{/* @generated from the command definitions, do not edit manually (run `just regenerate-cli-docs` to regenerate) */}\",\n );\n lines.push(\"\");\n lines.push(renderCommand(entry, all, { headingLevel: 1 }));\n\n const descendants = all.filter(\n (e) =>\n e.path.length > entry.path.length &&\n entry.path.every((p, i) => e.path[i] === p),\n );\n for (const d of descendants) {\n // Render the heading hierarchically by depth below the root: a direct\n // subcommand (`env default`, path length 3) is an h2, a sub-subcommand\n // (`env default set`, path length 4) is an h3, and so on. This nests\n // sub-subcommands under their parent group instead of flattening every\n // descendant to the same h2 level.\n lines.push(\n renderCommand(d, all, {\n headingLevel: d.path.length - 1,\n includeSubcommandsList: false,\n }),\n );\n }\n\n docs[filePath] = lines.join(\"\\n\");\n }\n\n return docs;\n}\n\nfunction collectCommands(\n command: CommandUnknownOpts,\n path: string[],\n): CommandInfo[] {\n const result: CommandInfo[] = [{ command, path }];\n for (const sub of command.commands) {\n // Skip hidden commands and Commander's built-in help command.\n if ((sub as any)._hidden) continue;\n if (sub.name() === \"help\") continue;\n result.push(...collectCommands(sub, [...path, sub.name()]));\n }\n return result;\n}\n\nfunction displayName(path: string[]): string {\n return `npx ${path.join(\" \")}`;\n}\n\n// Build the usage suffix (everything after the command name) for the Syntax\n// code block. We derive the argument portion from the command's registered\n// arguments rather than trusting a manual `.usage()` override, so the Syntax\n// line always agrees with the Arguments section below. For example `env set`\n// overrides `.usage()` to show `<name> <value>` (pretending the args are\n// required) for nicer `--help` output, even though it registers them as\n// optional `[name] [value]`; reproducing the override verbatim would make the\n// generated page contradict itself. Commands with no registered arguments keep\n// their `.usage()` string verbatim (e.g. the root's `<command> [options]`).\nfunction commandUsage(command: CommandUnknownOpts): string {\n const args = (command as any).registeredArguments ?? [];\n if (args.length === 0) {\n return command.usage();\n }\n // Mirror Commander's default usage order: options, then a subcommand\n // placeholder, then the positional arguments. `[options]` is always present\n // because the built-in `--help` option is always registered.\n const parts = [\"[options]\"];\n if (command.commands.length > 0) {\n parts.push(\"[command]\");\n }\n for (const arg of args) {\n const name = `${arg._name}${arg.variadic ? \"...\" : \"\"}`;\n parts.push(arg.required ? `<${name}>` : `[${name}]`);\n }\n return parts.join(\" \");\n}\n\n// Anchor id for a descendant command rendered as an h2 section inside its\n// main command's file. Built from the path segments below the main command,\n// joined with `-`, so sub-subcommands stay unique. For example, both\n// `deployment create` and `deployment token create` would collide on `#create`\n// if we used only the leaf name; instead they become `#create` and\n// `#token-create`.\nfunction anchorSlug(path: string[]): string {\n return path.slice(2).join(\"-\");\n}\n\n// Link target for a subcommand listed inside a command's \"Subcommands\"\n// section. From the root index, main commands live in sibling files. From a\n// main command page, descendants are rendered as h2 sections in the same\n// file, anchored by their path below the main command.\nfunction subcommandLink(parentPath: string[], subPath: string[]): string {\n if (parentPath.length === 1) {\n return `./${subPath[1]}`;\n }\n return `#${anchorSlug(subPath)}`;\n}\n\nfunction renderCommand(\n entry: CommandInfo,\n all: CommandInfo[],\n options: { headingLevel: number; includeSubcommandsList?: boolean },\n): string {\n const { headingLevel, includeSubcommandsList = true } = options;\n const h1 = \"#\".repeat(headingLevel);\n const h2 = \"#\".repeat(headingLevel + 1);\n\n const { command, path } = entry;\n const display = displayName(path);\n const description = renderCopyableCommands(\n escapeMdx(\n formatExampleLines(\n replaceBullets(command.description() || command.summary() || \"\"),\n ),\n ),\n );\n\n const lines: string[] = [];\n // For nested subcommand sections, pin the heading id to the path below the\n // main command so anchors like `#set` and `#token-create` stay unique even\n // when leaf names collide across different parents.\n const headingSuffix = headingLevel > 1 ? ` \\\\{#${anchorSlug(path)}}` : \"\";\n lines.push(`${h1} \\`${display}\\`${headingSuffix}`);\n lines.push(\"\");\n if (description) {\n lines.push(description);\n lines.push(\"\");\n }\n\n const usage = commandUsage(command);\n lines.push(`${h2} Syntax`);\n lines.push(\"\");\n lines.push(\"```sh\");\n lines.push(`${display} ${usage}`.trim());\n lines.push(\"```\");\n lines.push(\"\");\n\n const aliases = command.aliases();\n if (aliases.length > 0) {\n lines.push(`${h2} Aliases`);\n lines.push(\"\");\n for (const alias of aliases) {\n lines.push(`- \\`${alias}\\``);\n }\n lines.push(\"\");\n }\n\n const args = (command as any).registeredArguments ?? [];\n if (args.length > 0) {\n lines.push(`${h2} Arguments`);\n lines.push(\"\");\n lines.push(\"<dl>\");\n for (const arg of args) {\n const name = arg.required ? `<${arg._name}>` : `[${arg._name}]`;\n const desc = escapeMdx(replaceBullets(arg.description || \"\"));\n lines.push(`<dt>\\`${name}\\`</dt>`);\n lines.push(`<dd>`);\n lines.push(\"\");\n lines.push(desc);\n lines.push(\"\");\n lines.push(`</dd>`);\n }\n lines.push(\"</dl>\");\n lines.push(\"\");\n }\n\n const opts = command.options.filter((o: any) => !o.hidden);\n if (opts.length > 0) {\n lines.push(`${h2} Options`);\n lines.push(\"\");\n lines.push(\"<dl>\");\n for (const opt of opts) {\n const flags = (opt as any).flags as string;\n const desc = escapeMdx(replaceBullets(opt.description || \"\"));\n lines.push(`<dt>\\`${flags}\\`</dt>`);\n lines.push(`<dd>`);\n lines.push(\"\");\n lines.push(desc);\n lines.push(\"\");\n lines.push(`</dd>`);\n }\n lines.push(\"</dl>\");\n lines.push(\"\");\n }\n\n if (includeSubcommandsList) {\n const subEntries = all.filter(\n (e) =>\n e.path.length === path.length + 1 &&\n path.every((p, i) => e.path[i] === p),\n );\n if (subEntries.length > 0) {\n lines.push(`${h2} Subcommands`);\n lines.push(\"\");\n for (const sub of subEntries) {\n const subDisplay = displayName(sub.path);\n const target = subcommandLink(path, sub.path);\n const subDesc = indentContinuation(\n escapeMdx(sub.command.summary() || sub.command.description() || \"\"),\n );\n lines.push(`- [\\`${subDisplay}\\`](${target}) \u2014 ${subDesc}`.trimEnd());\n }\n lines.push(\"\");\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n// Escape characters that MDX would otherwise parse as JSX. Backslash-escaping\n// `<` and `{` keeps placeholder text like `<team_slug>` rendering as literal\n// text instead of being interpreted as a tag or expression.\n//\n// MDX only parses `<` and `{` specially in prose \u2014 inside an inline code span\n// (backticks) both are already literal, and a backslash there renders verbatim\n// (e.g. `` `\\<nameOrToken>` `` shows the backslash). So leave code spans\n// untouched and escape only the surrounding prose.\nfunction escapeMdx(text: string): string {\n return text\n .split(/(`[^`]*`)/)\n .map((segment, i) =>\n // Odd indices are the captured code spans; even indices are prose.\n i % 2 === 1 ? segment : segment.replace(/[<{]/g, (c) => `\\\\${c}`),\n )\n .join(\"\");\n}\n\n// Turn inline code spans that are full `npx convex ...` commands into a\n// CodeWithCopyButton component so readers can copy them with one click. The\n// component is registered globally in the docs site's MDXComponents, so no\n// import is needed in the generated page. This runs after escapeMdx, which\n// leaves code spans verbatim, so the command text inside the backticks is\n// unescaped and drops straight into the `text` attribute.\n//\n// We pass the command as a JSX expression containing a JSON-encoded string\n// (`text={\"...\"}`) rather than a plain attribute (`text=\"...\"`) because\n// commands routinely contain double quotes (e.g. JSON arguments like\n// `'{\"body\": \"hello\"}'`), which would otherwise terminate the attribute value\n// and produce invalid MDX. JSON.stringify escapes quotes and backslashes for\n// us.\nfunction renderCopyableCommands(text: string): string {\n return text\n .split(\"\\n\")\n .map((line) =>\n /^- /.test(line)\n ? line.replace(\n /`(npx convex(?:@[^\\s`]+)? [^`]*)`/g,\n (_, command) =>\n `<CodeWithCopyButton text={${JSON.stringify(command)}} />`,\n )\n : line,\n )\n .join(\"\\n\");\n}\n\n// Replace \"\u2022\" bullet points with markdown \"-\" bullet points. Every line that is\n// (maybe leading spaces +) \"\u2022 \" becomes the same spaces + \"- \". This runs before\n// formatExampleLines and renderCopyableCommands so that `npx convex ...` commands\n// in bulleted help text are recognized as list items and get a copy button.\nexport function replaceBullets(text: string): string {\n return text.replace(/^( *)\u2022 /gm, \"$1- \");\n}\n\n// Convert indented example lines (e.g., from CLI help text) into markdown lists\n// so they render with proper line breaks instead of collapsing into one line.\n// Consecutive indented lines are gathered into a block; any line indented by at\n// least two spaces belongs to the block, regardless of how deeply it nests.\n//\n// How much the block is dedented depends on what precedes it:\n// - When the block follows a list item, its indentation encodes real nesting\n// (a sub-list under that item), so it is preserved verbatim. This keeps a\n// 3-level list like the deploy command's preview-key description intact\n// instead of flattening the 2-space sub-item to a top-level bullet.\n// - When the block follows prose (or starts the text), the indentation is\n// just help-text formatting, so the block is dedented by its smallest\n// indent to the left margin. Otherwise an indented list wouldn't interrupt\n// the preceding paragraph and would collapse into it.\nfunction formatExampleLines(text: string): string {\n const lines = text.split(\"\\n\");\n const result: string[] = [];\n let blockLines: string[] = [];\n\n const flushBlock = () => {\n if (blockLines.length === 0) {\n return;\n }\n const prev = result[result.length - 1];\n const followsListItem = prev !== undefined && isListItem(prev);\n const dedent = followsListItem\n ? 0\n : Math.min(...blockLines.map(indentWidth));\n for (const blockLine of blockLines) {\n result.push(toListItem(blockLine.substring(dedent)));\n }\n blockLines = [];\n };\n\n for (const line of lines) {\n // Any line indented by at least two spaces (and not blank) is part of an\n // example block, regardless of nesting depth.\n if (/^ {2,}\\S/.test(line)) {\n blockLines.push(line);\n } else {\n flushBlock();\n result.push(line);\n }\n }\n flushBlock();\n\n return result.join(\"\\n\");\n}\n\nfunction indentWidth(line: string): number {\n return line.length - line.trimStart().length;\n}\n\nfunction isListItem(line: string): boolean {\n const content = line.trimStart();\n return content.startsWith(\"- \") || /^\\d+\\.\\s/.test(content);\n}\n\n// Render an example line as a markdown list item, preserving any leading indent\n// so nested items stay nested. Lines that are already list items \u2014 either a\n// bullet (`- `) or an ordered-list item (`1. `) \u2014 are kept verbatim so they\n// render as their intended list type. Prefixing an ordered-list item with `- `\n// would nest it inside a bullet, which renders as roman numerals instead of the\n// numbered steps.\nfunction toListItem(line: string): string {\n if (isListItem(line)) {\n return line;\n }\n const indent = line.slice(0, indentWidth(line));\n return `${indent}- ${line.trimStart()}`;\n}\n\nfunction indentContinuation(text: string): string {\n return text.replace(/\\n/g, \"\\n \");\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/cli/lib/indexes.ts"],
|
|
4
|
-
"sourcesContent": ["import { chalkStderr } from \"chalk\";\nimport { deploymentDashboardUrlPage } from \"./dashboard.js\";\nimport { DeveloperIndexConfig } from \"./deployApi/finishPush.js\";\n\nexport type IndexMetadata = {\n table: string;\n name: string;\n fields:\n | string[]\n | {\n searchField: string;\n filterFields: string[];\n }\n | {\n dimensions: number;\n vectorField: string;\n filterFields: string[];\n };\n backfill: {\n state: \"in_progress\" | \"done\";\n };\n staged: boolean;\n};\n\nexport type LargeIndexDeletionCheck =\n // Don\u2019t verify whether large indexes have been deleted\n | \"no verification\"\n // If large indexes are being deleted, ask for confirmation (and fail in non-interactive envs)\n | \"ask for confirmation\"\n // If large indexes are being deleted, confirm (the user has used --
|
|
4
|
+
"sourcesContent": ["import { chalkStderr } from \"chalk\";\nimport { deploymentDashboardUrlPage } from \"./dashboard.js\";\nimport { DeveloperIndexConfig } from \"./deployApi/finishPush.js\";\n\nexport type IndexMetadata = {\n table: string;\n name: string;\n fields:\n | string[]\n | {\n searchField: string;\n filterFields: string[];\n }\n | {\n dimensions: number;\n vectorField: string;\n filterFields: string[];\n };\n backfill: {\n state: \"in_progress\" | \"done\";\n };\n staged: boolean;\n};\n\nexport type LargeIndexDeletionCheck =\n // Don\u2019t verify whether large indexes have been deleted\n | \"no verification\"\n // If large indexes are being deleted, ask for confirmation (and fail in non-interactive envs)\n | \"ask for confirmation\"\n // If large indexes are being deleted, confirm (the user has used --skip-large-indexes-check)\n | \"has confirmation\";\n\nexport function addProgressLinkIfSlow(\n msg: string,\n deploymentName: string | null,\n start: number,\n): string {\n if (Date.now() - start > 10_000) {\n const dashboardUrl = deploymentDashboardUrlPage(\n deploymentName,\n `/schema?showSchema=true`,\n );\n msg = msg.concat(`\\nSee progress here: ${dashboardUrl}`);\n }\n return msg;\n}\n\nexport function formatIndex(index: DeveloperIndexConfig) {\n const [tableName, indexName] = index.name.split(\".\");\n return `${tableName}.${chalkStderr.bold(indexName)} ${chalkStderr.gray(formatIndexFields(index))}${index.staged ? chalkStderr.blue(\" (staged)\") : \"\"}`;\n}\n\nfunction formatIndexFields(index: DeveloperIndexConfig) {\n switch (index.type) {\n case \"database\":\n return (\n \" \" + index.fields.map((f) => chalkStderr.underline(f)).join(\", \")\n );\n case \"search\":\n return `${chalkStderr.cyan(\"(text)\")} ${chalkStderr.underline(index.searchField)}${formatFilterFields(index.filterFields)}`;\n case \"vector\":\n return `${chalkStderr.cyan(\"(vector)\")} ${chalkStderr.underline(index.vectorField)} (${index.dimensions} dimensions)${formatFilterFields(index.filterFields)}`;\n default:\n index satisfies never;\n return \"\";\n }\n}\n\nfunction formatFilterFields(filterFields: string[]) {\n if (filterFields.length === 0) {\n return \"\";\n }\n return `, filter${filterFields.length === 1 ? \"\" : \"s\"} on ${filterFields.map((f) => chalkStderr.underline(f)).join(\", \")}`;\n}\n"],
|
|
5
5
|
"mappings": ";AAAA,SAAS,mBAAmB;AAC5B,SAAS,kCAAkC;AA+BpC,gBAAS,sBACd,KACA,gBACA,OACQ;AACR,MAAI,KAAK,IAAI,IAAI,QAAQ,KAAQ;AAC/B,UAAM,eAAe;AAAA,MACnB;AAAA,MACA;AAAA,IACF;AACA,UAAM,IAAI,OAAO;AAAA,qBAAwB,YAAY,EAAE;AAAA,EACzD;AACA,SAAO;AACT;AAEO,gBAAS,YAAY,OAA6B;AACvD,QAAM,CAAC,WAAW,SAAS,IAAI,MAAM,KAAK,MAAM,GAAG;AACnD,SAAO,GAAG,SAAS,IAAI,YAAY,KAAK,SAAS,CAAC,IAAI,YAAY,KAAK,kBAAkB,KAAK,CAAC,CAAC,GAAG,MAAM,SAAS,YAAY,KAAK,YAAY,IAAI,EAAE;AACvJ;AAEA,SAAS,kBAAkB,OAA6B;AACtD,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aACE,OAAO,MAAM,OAAO,IAAI,CAAC,MAAM,YAAY,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI;AAAA,IAEtE,KAAK;AACH,aAAO,GAAG,YAAY,KAAK,QAAQ,CAAC,MAAM,YAAY,UAAU,MAAM,WAAW,CAAC,GAAG,mBAAmB,MAAM,YAAY,CAAC;AAAA,IAC7H,KAAK;AACH,aAAO,GAAG,YAAY,KAAK,UAAU,CAAC,MAAM,YAAY,UAAU,MAAM,WAAW,CAAC,KAAK,MAAM,UAAU,eAAe,mBAAmB,MAAM,YAAY,CAAC;AAAA,IAChK;AACE;AACA,aAAO;AAAA,EACX;AACF;AAEA,SAAS,mBAAmB,cAAwB;AAClD,MAAI,aAAa,WAAW,GAAG;AAC7B,WAAO;AAAA,EACT;AACA,SAAO,WAAW,aAAa,WAAW,IAAI,KAAK,GAAG,OAAO,aAAa,IAAI,CAAC,MAAM,YAAY,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AAC3H;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -32,6 +32,16 @@ import {
|
|
|
32
32
|
modifyGlobalConfig
|
|
33
33
|
} from "./utils/globalConfig.js";
|
|
34
34
|
import { updateBigBrainAuthAfterLogin } from "./deploymentSelection.js";
|
|
35
|
+
import {
|
|
36
|
+
getProfileSelection,
|
|
37
|
+
profileConfigPath,
|
|
38
|
+
writeProfileCredentials,
|
|
39
|
+
readProfileCredentials
|
|
40
|
+
} from "./profiles.js";
|
|
41
|
+
import {
|
|
42
|
+
profileLoginMetadata,
|
|
43
|
+
revokeReplacedProfileToken
|
|
44
|
+
} from "./profileManagement.js";
|
|
35
45
|
custom.setHttpOptionsDefaults({
|
|
36
46
|
timeout: parseInt(process.env.OPENID_CLIENT_TIMEOUT || "10000")
|
|
37
47
|
});
|
|
@@ -198,8 +208,11 @@ export async function performLogin(ctx, {
|
|
|
198
208
|
deviceName: deviceNameOverride,
|
|
199
209
|
anonymousId,
|
|
200
210
|
vercel,
|
|
201
|
-
vercelOverride
|
|
211
|
+
vercelOverride,
|
|
212
|
+
profile: selectedProfile
|
|
202
213
|
} = {}) {
|
|
214
|
+
const auth = ctx.bigBrainAuth();
|
|
215
|
+
const profile = selectedProfile !== void 0 ? selectedProfile : auth?.kind === "accessToken" && auth.profile !== void 0 ? auth.profile : await getProfileSelection(ctx);
|
|
203
216
|
loginFlow = loginFlow || "auto";
|
|
204
217
|
let deviceName = deviceNameOverride ?? "";
|
|
205
218
|
if (!deviceName && process.platform === "darwin") {
|
|
@@ -272,6 +285,8 @@ export async function performLogin(ctx, {
|
|
|
272
285
|
printedMessage: null
|
|
273
286
|
});
|
|
274
287
|
}
|
|
288
|
+
const previous = profile === null ? null : await readProfileCredentials(ctx, profile, true);
|
|
289
|
+
const metadata = profile === null ? {} : await profileLoginMetadata(ctx, profile, accessToken, previous);
|
|
275
290
|
ctx._updateBigBrainAuth({
|
|
276
291
|
accessToken,
|
|
277
292
|
kind: "accessToken",
|
|
@@ -289,8 +304,18 @@ export async function performLogin(ctx, {
|
|
|
289
304
|
const newAccessToken = response.data.accessToken;
|
|
290
305
|
const globalConfig = { accessToken: newAccessToken };
|
|
291
306
|
try {
|
|
292
|
-
|
|
293
|
-
|
|
307
|
+
if (profile !== null) {
|
|
308
|
+
await writeProfileCredentials(
|
|
309
|
+
ctx,
|
|
310
|
+
profile.name,
|
|
311
|
+
newAccessToken,
|
|
312
|
+
metadata,
|
|
313
|
+
previous
|
|
314
|
+
);
|
|
315
|
+
} else {
|
|
316
|
+
await modifyGlobalConfig(ctx, globalConfig);
|
|
317
|
+
}
|
|
318
|
+
const path = profile !== null ? profileConfigPath(profile.name) : globalConfigPath();
|
|
294
319
|
logFinishedStep(`Saved credentials to ${formatPathForPrinting(path)}`);
|
|
295
320
|
} catch (err) {
|
|
296
321
|
return await ctx.crash({
|
|
@@ -300,8 +325,15 @@ export async function performLogin(ctx, {
|
|
|
300
325
|
printedMessage: null
|
|
301
326
|
});
|
|
302
327
|
}
|
|
328
|
+
if (profile !== null) {
|
|
329
|
+
await revokeReplacedProfileToken(
|
|
330
|
+
ctx,
|
|
331
|
+
previous?.accessToken,
|
|
332
|
+
newAccessToken
|
|
333
|
+
);
|
|
334
|
+
}
|
|
303
335
|
logVerbose(`performLogin: updating big brain auth after login`);
|
|
304
|
-
await updateBigBrainAuthAfterLogin(ctx, newAccessToken);
|
|
336
|
+
await updateBigBrainAuthAfterLogin(ctx, newAccessToken, profile ?? void 0);
|
|
305
337
|
logVerbose(`performLogin: checking opt ins, acceptOptIns: ${acceptOptIns}`);
|
|
306
338
|
const shouldContinue = await optins(ctx, acceptOptIns ?? false);
|
|
307
339
|
if (!shouldContinue) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/cli/lib/login.ts"],
|
|
4
|
-
"sourcesContent": ["import { errors, BaseClient, custom } from \"openid-client\";\nimport {\n bigBrainAPI,\n bigBrainFetch,\n logAndHandleFetchError,\n throwingFetch,\n isWebContainer,\n typedPlatformClient,\n} from \"./utils/utils.js\";\nimport open from \"open\";\nimport { chalkStderr } from \"chalk\";\nimport { provisionHost } from \"./config.js\";\nimport { version } from \"../version.js\";\nimport { Context } from \"../../bundler/context.js\";\nimport {\n changeSpinner,\n logError,\n logFailure,\n logFinishedStep,\n logMessage,\n logOutput,\n logVerbose,\n showSpinner,\n} from \"../../bundler/log.js\";\nimport { Issuer } from \"openid-client\";\nimport { hostname } from \"os\";\nimport { execSync } from \"child_process\";\nimport { promptString, promptYesNo } from \"./utils/prompts.js\";\nimport {\n formatPathForPrinting,\n globalConfigPath,\n modifyGlobalConfig,\n} from \"./utils/globalConfig.js\";\nimport { updateBigBrainAuthAfterLogin } from \"./deploymentSelection.js\";\n\n// Per https://github.com/panva/node-openid-client/tree/main/docs#customizing\ncustom.setHttpOptionsDefaults({\n timeout: parseInt(process.env.OPENID_CLIENT_TIMEOUT || \"10000\"),\n});\n\n/**\n * Whether Big Brain accepts this credential. Takes the header explicitly so\n * callers can check a credential other than the one `ctx` resolved to.\n */\nexport async function isAuthorizedHeader(\n ctx: Context,\n header: string,\n): Promise<boolean> {\n try {\n const resp = await fetch(`${provisionHost}/api/authorize`, {\n method: \"HEAD\",\n headers: {\n Authorization: header,\n \"Convex-Client\": `npm-cli-${version}`,\n },\n });\n // Don't throw an error if this request returns a non-200 status.\n // Big Brain responds with a variety of error codes -- 401 if the token is correctly-formed but not valid, and either 400 or 500 if the token is ill-formed.\n // We only care if this check returns a 200 code (so we can skip logging in again) -- any other errors should be silently skipped and we'll run the whole login flow again.\n return resp.status === 200;\n } catch (e: any) {\n // This `catch` block should only be hit if a network error was encountered\n logError(\n `Unexpected error when authorizing - are you connected to the internet?`,\n );\n return await logAndHandleFetchError(ctx, e);\n }\n}\n\nexport async function checkAuthorization(\n ctx: Context,\n acceptOptIns: boolean,\n): Promise<boolean> {\n const header = ctx.bigBrainAuth()?.header ?? null;\n if (header === null) {\n return false;\n }\n if (!(await isAuthorizedHeader(ctx, header))) {\n return false;\n }\n\n // Check that we have optin as well\n const shouldContinue = await optins(ctx, acceptOptIns);\n if (!shouldContinue) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n return true;\n}\n\nasync function performDeviceAuthorization(\n ctx: Context,\n authClient: BaseClient,\n shouldOpen: boolean,\n vercel?: boolean,\n vercelOverride?: string,\n): Promise<string> {\n // Device authorization flow follows this guide: https://github.com/auth0/auth0-device-flow-cli-sample/blob/9f0f3b76a6cd56ea8d99e76769187ea5102d519d/cli.js\n // License: MIT License\n // Copyright (c) 2019 Auth0 Samples\n /*\n The MIT License (MIT)\n\n Copyright (c) 2019 Auth0 Samples\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n */\n\n // Device Authorization Request - https://tools.ietf.org/html/rfc8628#section-3.1\n // Get authentication URL\n let handle;\n try {\n handle = await authClient.deviceAuthorization();\n } catch {\n // We couldn't get verification URL from the auth provider, proceed with manual auth\n return promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n }\n\n // Device Authorization Response - https://tools.ietf.org/html/rfc8628#section-3.2\n // Open authentication URL\n const { verification_uri_complete, user_code, expires_in } = handle;\n\n // Construct Vercel URL if --vercel flag is used\n const urlToOpen = vercel\n ? `https://vercel.com/sso/integrations/${vercelOverride || \"convex\"}?url=${verification_uri_complete}`\n : verification_uri_complete;\n\n logMessage(\n `Visit ${urlToOpen} to finish logging in.\\n` +\n `You should see the following code which expires in ${\n expires_in % 60 === 0\n ? `${expires_in / 60} minutes`\n : `${expires_in} seconds`\n }: ${user_code}`,\n );\n if (shouldOpen) {\n shouldOpen = await promptYesNo(ctx, {\n message: `Open the browser?`,\n default: true,\n });\n }\n\n if (shouldOpen) {\n showSpinner(`Opening ${urlToOpen} in your browser to log in...\\n`);\n try {\n const p = await open(urlToOpen);\n p.once(\"error\", () => {\n changeSpinner(`Manually open ${urlToOpen} in your browser to log in.`);\n });\n changeSpinner(\"Waiting for the confirmation...\");\n } catch {\n logError(chalkStderr.red(`Unable to open browser.`));\n changeSpinner(`Manually open ${urlToOpen} in your browser to log in.`);\n }\n } else {\n showSpinner(`Open ${urlToOpen} in your browser to log in.`);\n }\n\n // Device Access Token Request - https://tools.ietf.org/html/rfc8628#section-3.4\n // Device Access Token Response - https://tools.ietf.org/html/rfc8628#section-3.5\n try {\n const tokens = await handle.poll();\n if (typeof tokens.access_token === \"string\") {\n return tokens.access_token;\n } else {\n // Unexpected error\n // eslint-disable-next-line no-restricted-syntax\n throw Error(\"Access token is missing\");\n }\n } catch (err: any) {\n switch (err.error) {\n case \"access_denied\": // end-user declined the device confirmation prompt, consent or rules failed\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"Access denied.\",\n errForSentry: err,\n });\n case \"expired_token\": // end-user did not complete the interaction in time\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"Device flow expired.\",\n errForSentry: err,\n });\n default: {\n const message =\n err instanceof errors.OPError\n ? `Error = ${err.error}; error_description = ${err.error_description}`\n : `Login failed with error: ${err}`;\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: message,\n errForSentry: err,\n });\n }\n }\n }\n}\n\nasync function performPasswordAuthentication(\n ctx: Context,\n clientId: string,\n username: string,\n password: string,\n): Promise<string> {\n if (!process.env.WORKOS_API_SECRET) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"WORKOS_API_SECRET environment variable is not set\",\n });\n }\n\n // Unfortunately, `openid-client` doesn't support the resource owner password credentials flow so we need to manually send the requests.\n const options: Parameters<typeof throwingFetch>[1] = {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n grant_type: \"password\",\n email: username,\n password: password,\n client_id: clientId,\n client_secret: process.env.WORKOS_API_SECRET,\n }),\n };\n\n try {\n const response = await throwingFetch(\n \"https://apiauth.convex.dev/user_management/authenticate\",\n options,\n );\n const data = await response.json();\n if (typeof data.access_token === \"string\") {\n return data.access_token;\n } else {\n // Unexpected error\n // eslint-disable-next-line no-restricted-syntax\n throw Error(\"Access token is missing\");\n }\n } catch (err: any) {\n logFailure(`Password flow failed: ${err}`);\n if (err.response) {\n logError(chalkStderr.red(`${JSON.stringify(err.response.data)}`));\n }\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n errForSentry: err,\n printedMessage: null,\n });\n }\n}\n\nexport async function performLogin(\n ctx: Context,\n {\n overrideAuthUrl,\n overrideAuthClient,\n overrideAuthUsername,\n overrideAuthPassword,\n overrideAccessToken,\n loginFlow,\n open,\n acceptOptIns,\n dumpAccessToken,\n deviceName: deviceNameOverride,\n anonymousId,\n vercel,\n vercelOverride,\n }: {\n overrideAuthUrl?: string | undefined;\n overrideAuthClient?: string | undefined;\n overrideAuthUsername?: string | undefined;\n overrideAuthPassword?: string | undefined;\n overrideAccessToken?: string | undefined;\n loginFlow?: \"auto\" | \"paste\" | \"poll\" | undefined;\n // default `true`\n open?: boolean | undefined;\n // default `false`\n acceptOptIns?: boolean | undefined;\n dumpAccessToken?: boolean | undefined;\n deviceName?: string | undefined;\n anonymousId?: string | undefined;\n vercel?: boolean | undefined;\n vercelOverride?: string | undefined;\n } = {},\n) {\n loginFlow = loginFlow || \"auto\";\n // Get access token from big-brain\n // Default the device name to the hostname, but allow the user to change this if the terminal is interactive.\n // On Macs, the `hostname()` may be a weirdly-truncated form of the computer name. Attempt to read the \"real\" name before falling back to hostname.\n let deviceName = deviceNameOverride ?? \"\";\n if (!deviceName && process.platform === \"darwin\") {\n try {\n deviceName = execSync(\"scutil --get ComputerName\").toString().trim();\n } catch {\n // Just fall back to the hostname default below.\n }\n }\n if (!deviceName) {\n deviceName = hostname();\n }\n if (!deviceNameOverride) {\n logMessage(\n chalkStderr.bold(\n `Welcome to developing with Convex, let's get you logged in.`,\n ),\n );\n deviceName = await promptString(ctx, {\n message: \"Device name:\",\n default: deviceName,\n });\n }\n\n const issuer = overrideAuthUrl ?? \"https://auth.convex.dev\";\n const clientId = overrideAuthClient ?? \"HFtA247jp9iNs08NTLIB7JsNPMmRIyfi\";\n let accessToken: string;\n\n if (overrideAccessToken) {\n // Access token was supplied directly.\n accessToken = overrideAccessToken;\n } else if (overrideAuthUsername && overrideAuthPassword) {\n // Username/Password auth\n accessToken = await performPasswordAuthentication(\n ctx,\n clientId,\n overrideAuthUsername,\n overrideAuthPassword,\n );\n } else if (\n loginFlow === \"paste\" ||\n (loginFlow === \"auto\" && isWebContainer())\n ) {\n accessToken = await promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n } else {\n // Device authorization flow. Contact OIDC issuer.\n let authIssuer;\n try {\n authIssuer = await Issuer.discover(issuer);\n } catch {\n // Couldn't contact https://auth.convex.dev/.well-known/openid-configuration,\n // proceed with manual auth.\n authIssuer = undefined;\n }\n if (authIssuer) {\n const authClient = new authIssuer.Client({\n client_id: clientId,\n token_endpoint_auth_method: \"none\",\n id_token_signed_response_alg: \"RS256\",\n });\n accessToken = await performDeviceAuthorization(\n ctx,\n authClient,\n open ?? true,\n vercel,\n vercelOverride,\n );\n } else {\n accessToken = await promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n }\n }\n\n if (dumpAccessToken) {\n logOutput(`${accessToken}`);\n return await ctx.crash({\n exitCode: 0,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n\n // Exchange the WorkOS access token for a Convex personal access token.\n ctx._updateBigBrainAuth({\n accessToken: accessToken,\n kind: \"accessToken\",\n header: `Bearer ${accessToken}`,\n });\n const response = await typedPlatformClient(ctx).POST(\n \"/create_personal_access_token\",\n {\n // `anonymousId` links a prior anonymous session to this account. It's\n // intentionally absent from the generated platform API types,\n // so cast to pass it through.\n body: { name: deviceName, anonymousId } as { name: string },\n },\n );\n const newAccessToken = response.data!.accessToken;\n const globalConfig = { accessToken: newAccessToken };\n try {\n await modifyGlobalConfig(ctx, globalConfig);\n const path = globalConfigPath();\n logFinishedStep(`Saved credentials to ${formatPathForPrinting(path)}`);\n } catch (err: unknown) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem data\",\n errForSentry: err,\n printedMessage: null,\n });\n }\n\n logVerbose(`performLogin: updating big brain auth after login`);\n await updateBigBrainAuthAfterLogin(ctx, newAccessToken);\n\n logVerbose(`performLogin: checking opt ins, acceptOptIns: ${acceptOptIns}`);\n // Do opt in to TOS and Privacy Policy stuff\n const shouldContinue = await optins(ctx, acceptOptIns ?? false);\n if (!shouldContinue) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n\n if (vercel) {\n await promptJoinVercelTeams(ctx);\n }\n}\n\ntype PotentialVercelTeam = {\n teamId: number;\n teamName: string;\n teamSlug: string;\n planId: string;\n planName: string;\n pricingNotice: string | null;\n};\n\n// After `--vercel` login, surface any Vercel-marketplace teams the user has\n// access to but isn't yet a member of, and prompt to join each.\nasync function promptJoinVercelTeams(ctx: Context): Promise<void> {\n const fetch = bigBrainFetch(ctx);\n let teams: PotentialVercelTeam[];\n try {\n const res = await fetch(\n new URL(\"vercel/potential_teams\", `${provisionHost}/`),\n );\n if (!res.ok) {\n logVerbose(\n `vercel/potential_teams returned ${res.status}; skipping team-join prompt`,\n );\n return;\n }\n teams = await res.json();\n } catch (err) {\n logVerbose(`Failed to fetch potential Vercel teams: ${String(err)}`);\n return;\n }\n if (teams.length === 0) return;\n\n for (const [index, team] of teams.entries()) {\n const displayName = team.teamName.replace(/ \\(Vercel\\)$/, \"\");\n const counter = teams.length > 1 ? `[${index + 1}/${teams.length}] ` : \"\";\n const lines = [\n chalkStderr.bold(`${counter}You've been invited to join ${displayName}`) +\n ` (${team.planName}) through the Vercel marketplace.`,\n ];\n if (team.pricingNotice) {\n lines.push(chalkStderr.yellow(team.pricingNotice));\n }\n lines.push(`Join \"${displayName}\"?`);\n const join = await promptYesNo(ctx, {\n message: `${lines.join(\"\\n\")}`,\n default: true,\n });\n if (!join) continue;\n try {\n await fetch(\n new URL(\n `vercel/potential_teams/${team.teamId}/join`,\n `${provisionHost}/`,\n ),\n { method: \"POST\" },\n );\n logFinishedStep(`Joined ${displayName}`);\n } catch (err) {\n logFailure(`Failed to join ${displayName}: ${String(err)}`);\n }\n }\n}\n\n/// There are fields like version, but we keep them opaque\ntype OptIn = Record<string, unknown>;\n\ntype OptInToAccept = {\n optIn: OptIn;\n message: string;\n};\n\ntype AcceptOptInsArgs = {\n optInsAccepted: OptIn[];\n};\n\n// Returns whether we can proceed or not.\nasync function optins(ctx: Context, acceptOptIns: boolean): Promise<boolean> {\n const bbAuth = ctx.bigBrainAuth();\n if (bbAuth === null) {\n // This should never happen, but if we're not even logged in, we can't proceed.\n return false;\n }\n switch (bbAuth.kind) {\n case \"accessToken\":\n break;\n case \"deploymentKey\":\n case \"projectKey\":\n case \"previewDeployKey\":\n // If we have a key configured as auth, we do not need to check opt ins.\n return true;\n default: {\n bbAuth satisfies never;\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n errForSentry: `Unexpected auth kind ${(bbAuth as any).kind}`,\n printedMessage: \"Hit an unexpected error while logging in.\",\n });\n }\n }\n const data = await bigBrainAPI({\n ctx,\n method: \"POST\",\n path: \"check_opt_ins\",\n });\n if (data.optInsToAccept.length === 0) {\n return true;\n }\n for (const optInToAccept of data.optInsToAccept) {\n const confirmed =\n acceptOptIns ||\n (await promptYesNo(ctx, {\n message: optInToAccept.message,\n }));\n if (!confirmed) {\n logFailure(\"Please accept the Terms of Service to use Convex.\");\n return Promise.resolve(false);\n }\n }\n\n const optInsAccepted = data.optInsToAccept.map((o: OptInToAccept) => o.optIn);\n const args: AcceptOptInsArgs = { optInsAccepted };\n await bigBrainAPI({\n ctx,\n method: \"POST\",\n path: \"accept_opt_ins\",\n data: args,\n });\n return true;\n}\n\nexport async function ensureLoggedIn(\n ctx: Context,\n options?: {\n message?: string | undefined;\n overrideAuthUrl?: string | undefined;\n overrideAuthClient?: string | undefined;\n overrideAuthUsername?: string | undefined;\n overrideAuthPassword?: string | undefined;\n },\n) {\n const isLoggedIn = await checkAuthorization(ctx, false);\n if (!isLoggedIn) {\n if (options?.message) {\n logMessage(options.message);\n }\n await performLogin(ctx, {\n acceptOptIns: false,\n overrideAuthUrl: options?.overrideAuthUrl,\n overrideAuthClient: options?.overrideAuthClient,\n overrideAuthUsername: options?.overrideAuthUsername,\n overrideAuthPassword: options?.overrideAuthPassword,\n });\n }\n}\n"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,QAAoB,cAAc;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,OAAO,UAAU;AACjB,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAC9B,SAAS,eAAe;AAExB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AACvB,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AACzB,SAAS,cAAc,mBAAmB;AAC1C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,oCAAoC;
|
|
4
|
+
"sourcesContent": ["import { errors, BaseClient, custom } from \"openid-client\";\nimport {\n bigBrainAPI,\n bigBrainFetch,\n logAndHandleFetchError,\n throwingFetch,\n isWebContainer,\n typedPlatformClient,\n} from \"./utils/utils.js\";\nimport open from \"open\";\nimport { chalkStderr } from \"chalk\";\nimport { provisionHost } from \"./config.js\";\nimport { version } from \"../version.js\";\nimport { Context } from \"../../bundler/context.js\";\nimport {\n changeSpinner,\n logError,\n logFailure,\n logFinishedStep,\n logMessage,\n logOutput,\n logVerbose,\n showSpinner,\n} from \"../../bundler/log.js\";\nimport { Issuer } from \"openid-client\";\nimport { hostname } from \"os\";\nimport { execSync } from \"child_process\";\nimport { promptString, promptYesNo } from \"./utils/prompts.js\";\nimport {\n formatPathForPrinting,\n globalConfigPath,\n modifyGlobalConfig,\n} from \"./utils/globalConfig.js\";\nimport { updateBigBrainAuthAfterLogin } from \"./deploymentSelection.js\";\nimport {\n getProfileSelection,\n ProfileSelection,\n profileConfigPath,\n writeProfileCredentials,\n readProfileCredentials,\n} from \"./profiles.js\";\nimport {\n profileLoginMetadata,\n revokeReplacedProfileToken,\n} from \"./profileManagement.js\";\n\n// Per https://github.com/panva/node-openid-client/tree/main/docs#customizing\ncustom.setHttpOptionsDefaults({\n timeout: parseInt(process.env.OPENID_CLIENT_TIMEOUT || \"10000\"),\n});\n\n/**\n * Whether Big Brain accepts this credential. Takes the header explicitly so\n * callers can check a credential other than the one `ctx` resolved to.\n */\nexport async function isAuthorizedHeader(\n ctx: Context,\n header: string,\n): Promise<boolean> {\n try {\n const resp = await fetch(`${provisionHost}/api/authorize`, {\n method: \"HEAD\",\n headers: {\n Authorization: header,\n \"Convex-Client\": `npm-cli-${version}`,\n },\n });\n // Don't throw an error if this request returns a non-200 status.\n // Big Brain responds with a variety of error codes -- 401 if the token is correctly-formed but not valid, and either 400 or 500 if the token is ill-formed.\n // We only care if this check returns a 200 code (so we can skip logging in again) -- any other errors should be silently skipped and we'll run the whole login flow again.\n return resp.status === 200;\n } catch (e: any) {\n // This `catch` block should only be hit if a network error was encountered\n logError(\n `Unexpected error when authorizing - are you connected to the internet?`,\n );\n return await logAndHandleFetchError(ctx, e);\n }\n}\n\nexport async function checkAuthorization(\n ctx: Context,\n acceptOptIns: boolean,\n): Promise<boolean> {\n const header = ctx.bigBrainAuth()?.header ?? null;\n if (header === null) {\n return false;\n }\n if (!(await isAuthorizedHeader(ctx, header))) {\n return false;\n }\n\n // Check that we have optin as well\n const shouldContinue = await optins(ctx, acceptOptIns);\n if (!shouldContinue) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n return true;\n}\n\nasync function performDeviceAuthorization(\n ctx: Context,\n authClient: BaseClient,\n shouldOpen: boolean,\n vercel?: boolean,\n vercelOverride?: string,\n): Promise<string> {\n // Device authorization flow follows this guide: https://github.com/auth0/auth0-device-flow-cli-sample/blob/9f0f3b76a6cd56ea8d99e76769187ea5102d519d/cli.js\n // License: MIT License\n // Copyright (c) 2019 Auth0 Samples\n /*\n The MIT License (MIT)\n\n Copyright (c) 2019 Auth0 Samples\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n */\n\n // Device Authorization Request - https://tools.ietf.org/html/rfc8628#section-3.1\n // Get authentication URL\n let handle;\n try {\n handle = await authClient.deviceAuthorization();\n } catch {\n // We couldn't get verification URL from the auth provider, proceed with manual auth\n return promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n }\n\n // Device Authorization Response - https://tools.ietf.org/html/rfc8628#section-3.2\n // Open authentication URL\n const { verification_uri_complete, user_code, expires_in } = handle;\n\n // Construct Vercel URL if --vercel flag is used\n const urlToOpen = vercel\n ? `https://vercel.com/sso/integrations/${vercelOverride || \"convex\"}?url=${verification_uri_complete}`\n : verification_uri_complete;\n\n logMessage(\n `Visit ${urlToOpen} to finish logging in.\\n` +\n `You should see the following code which expires in ${\n expires_in % 60 === 0\n ? `${expires_in / 60} minutes`\n : `${expires_in} seconds`\n }: ${user_code}`,\n );\n if (shouldOpen) {\n shouldOpen = await promptYesNo(ctx, {\n message: `Open the browser?`,\n default: true,\n });\n }\n\n if (shouldOpen) {\n showSpinner(`Opening ${urlToOpen} in your browser to log in...\\n`);\n try {\n const p = await open(urlToOpen);\n p.once(\"error\", () => {\n changeSpinner(`Manually open ${urlToOpen} in your browser to log in.`);\n });\n changeSpinner(\"Waiting for the confirmation...\");\n } catch {\n logError(chalkStderr.red(`Unable to open browser.`));\n changeSpinner(`Manually open ${urlToOpen} in your browser to log in.`);\n }\n } else {\n showSpinner(`Open ${urlToOpen} in your browser to log in.`);\n }\n\n // Device Access Token Request - https://tools.ietf.org/html/rfc8628#section-3.4\n // Device Access Token Response - https://tools.ietf.org/html/rfc8628#section-3.5\n try {\n const tokens = await handle.poll();\n if (typeof tokens.access_token === \"string\") {\n return tokens.access_token;\n } else {\n // Unexpected error\n // eslint-disable-next-line no-restricted-syntax\n throw Error(\"Access token is missing\");\n }\n } catch (err: any) {\n switch (err.error) {\n case \"access_denied\": // end-user declined the device confirmation prompt, consent or rules failed\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"Access denied.\",\n errForSentry: err,\n });\n case \"expired_token\": // end-user did not complete the interaction in time\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"Device flow expired.\",\n errForSentry: err,\n });\n default: {\n const message =\n err instanceof errors.OPError\n ? `Error = ${err.error}; error_description = ${err.error_description}`\n : `Login failed with error: ${err}`;\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: message,\n errForSentry: err,\n });\n }\n }\n }\n}\n\nasync function performPasswordAuthentication(\n ctx: Context,\n clientId: string,\n username: string,\n password: string,\n): Promise<string> {\n if (!process.env.WORKOS_API_SECRET) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"WORKOS_API_SECRET environment variable is not set\",\n });\n }\n\n // Unfortunately, `openid-client` doesn't support the resource owner password credentials flow so we need to manually send the requests.\n const options: Parameters<typeof throwingFetch>[1] = {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n grant_type: \"password\",\n email: username,\n password: password,\n client_id: clientId,\n client_secret: process.env.WORKOS_API_SECRET,\n }),\n };\n\n try {\n const response = await throwingFetch(\n \"https://apiauth.convex.dev/user_management/authenticate\",\n options,\n );\n const data = await response.json();\n if (typeof data.access_token === \"string\") {\n return data.access_token;\n } else {\n // Unexpected error\n // eslint-disable-next-line no-restricted-syntax\n throw Error(\"Access token is missing\");\n }\n } catch (err: any) {\n logFailure(`Password flow failed: ${err}`);\n if (err.response) {\n logError(chalkStderr.red(`${JSON.stringify(err.response.data)}`));\n }\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n errForSentry: err,\n printedMessage: null,\n });\n }\n}\n\nexport async function performLogin(\n ctx: Context,\n {\n overrideAuthUrl,\n overrideAuthClient,\n overrideAuthUsername,\n overrideAuthPassword,\n overrideAccessToken,\n loginFlow,\n open,\n acceptOptIns,\n dumpAccessToken,\n deviceName: deviceNameOverride,\n anonymousId,\n vercel,\n vercelOverride,\n profile: selectedProfile,\n }: {\n overrideAuthUrl?: string | undefined;\n overrideAuthClient?: string | undefined;\n overrideAuthUsername?: string | undefined;\n overrideAuthPassword?: string | undefined;\n overrideAccessToken?: string | undefined;\n loginFlow?: \"auto\" | \"paste\" | \"poll\" | undefined;\n // default `true`\n open?: boolean | undefined;\n // default `false`\n acceptOptIns?: boolean | undefined;\n dumpAccessToken?: boolean | undefined;\n deviceName?: string | undefined;\n anonymousId?: string | undefined;\n vercel?: boolean | undefined;\n vercelOverride?: string | undefined;\n profile?: ProfileSelection | null;\n } = {},\n) {\n const auth = ctx.bigBrainAuth();\n const profile =\n selectedProfile !== undefined\n ? selectedProfile\n : auth?.kind === \"accessToken\" && auth.profile !== undefined\n ? auth.profile\n : await getProfileSelection(ctx);\n loginFlow = loginFlow || \"auto\";\n // Get access token from big-brain\n // Default the device name to the hostname, but allow the user to change this if the terminal is interactive.\n // On Macs, the `hostname()` may be a weirdly-truncated form of the computer name. Attempt to read the \"real\" name before falling back to hostname.\n let deviceName = deviceNameOverride ?? \"\";\n if (!deviceName && process.platform === \"darwin\") {\n try {\n deviceName = execSync(\"scutil --get ComputerName\").toString().trim();\n } catch {\n // Just fall back to the hostname default below.\n }\n }\n if (!deviceName) {\n deviceName = hostname();\n }\n if (!deviceNameOverride) {\n logMessage(\n chalkStderr.bold(\n `Welcome to developing with Convex, let's get you logged in.`,\n ),\n );\n deviceName = await promptString(ctx, {\n message: \"Device name:\",\n default: deviceName,\n });\n }\n\n const issuer = overrideAuthUrl ?? \"https://auth.convex.dev\";\n const clientId = overrideAuthClient ?? \"HFtA247jp9iNs08NTLIB7JsNPMmRIyfi\";\n let accessToken: string;\n\n if (overrideAccessToken) {\n // Access token was supplied directly.\n accessToken = overrideAccessToken;\n } else if (overrideAuthUsername && overrideAuthPassword) {\n // Username/Password auth\n accessToken = await performPasswordAuthentication(\n ctx,\n clientId,\n overrideAuthUsername,\n overrideAuthPassword,\n );\n } else if (\n loginFlow === \"paste\" ||\n (loginFlow === \"auto\" && isWebContainer())\n ) {\n accessToken = await promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n } else {\n // Device authorization flow. Contact OIDC issuer.\n let authIssuer;\n try {\n authIssuer = await Issuer.discover(issuer);\n } catch {\n // Couldn't contact https://auth.convex.dev/.well-known/openid-configuration,\n // proceed with manual auth.\n authIssuer = undefined;\n }\n if (authIssuer) {\n const authClient = new authIssuer.Client({\n client_id: clientId,\n token_endpoint_auth_method: \"none\",\n id_token_signed_response_alg: \"RS256\",\n });\n accessToken = await performDeviceAuthorization(\n ctx,\n authClient,\n open ?? true,\n vercel,\n vercelOverride,\n );\n } else {\n accessToken = await promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n }\n }\n\n if (dumpAccessToken) {\n logOutput(`${accessToken}`);\n return await ctx.crash({\n exitCode: 0,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n\n // Exchange the WorkOS access token for a Convex personal access token.\n const previous =\n profile === null ? null : await readProfileCredentials(ctx, profile, true);\n const metadata =\n profile === null\n ? {}\n : await profileLoginMetadata(ctx, profile, accessToken, previous);\n ctx._updateBigBrainAuth({\n accessToken: accessToken,\n kind: \"accessToken\",\n header: `Bearer ${accessToken}`,\n });\n const response = await typedPlatformClient(ctx).POST(\n \"/create_personal_access_token\",\n {\n // `anonymousId` links a prior anonymous session to this account. It's\n // intentionally absent from the generated platform API types,\n // so cast to pass it through.\n body: { name: deviceName, anonymousId } as { name: string },\n },\n );\n const newAccessToken = response.data!.accessToken;\n const globalConfig = { accessToken: newAccessToken };\n try {\n if (profile !== null) {\n await writeProfileCredentials(\n ctx,\n profile.name,\n newAccessToken,\n metadata,\n previous,\n );\n } else {\n await modifyGlobalConfig(ctx, globalConfig);\n }\n const path =\n profile !== null ? profileConfigPath(profile.name) : globalConfigPath();\n logFinishedStep(`Saved credentials to ${formatPathForPrinting(path)}`);\n } catch (err: unknown) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem data\",\n errForSentry: err,\n printedMessage: null,\n });\n }\n\n if (profile !== null) {\n await revokeReplacedProfileToken(\n ctx,\n previous?.accessToken,\n newAccessToken,\n );\n }\n logVerbose(`performLogin: updating big brain auth after login`);\n await updateBigBrainAuthAfterLogin(ctx, newAccessToken, profile ?? undefined);\n\n logVerbose(`performLogin: checking opt ins, acceptOptIns: ${acceptOptIns}`);\n // Do opt in to TOS and Privacy Policy stuff\n const shouldContinue = await optins(ctx, acceptOptIns ?? false);\n if (!shouldContinue) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n\n if (vercel) {\n await promptJoinVercelTeams(ctx);\n }\n}\n\ntype PotentialVercelTeam = {\n teamId: number;\n teamName: string;\n teamSlug: string;\n planId: string;\n planName: string;\n pricingNotice: string | null;\n};\n\n// After `--vercel` login, surface any Vercel-marketplace teams the user has\n// access to but isn't yet a member of, and prompt to join each.\nasync function promptJoinVercelTeams(ctx: Context): Promise<void> {\n const fetch = bigBrainFetch(ctx);\n let teams: PotentialVercelTeam[];\n try {\n const res = await fetch(\n new URL(\"vercel/potential_teams\", `${provisionHost}/`),\n );\n if (!res.ok) {\n logVerbose(\n `vercel/potential_teams returned ${res.status}; skipping team-join prompt`,\n );\n return;\n }\n teams = await res.json();\n } catch (err) {\n logVerbose(`Failed to fetch potential Vercel teams: ${String(err)}`);\n return;\n }\n if (teams.length === 0) return;\n\n for (const [index, team] of teams.entries()) {\n const displayName = team.teamName.replace(/ \\(Vercel\\)$/, \"\");\n const counter = teams.length > 1 ? `[${index + 1}/${teams.length}] ` : \"\";\n const lines = [\n chalkStderr.bold(`${counter}You've been invited to join ${displayName}`) +\n ` (${team.planName}) through the Vercel marketplace.`,\n ];\n if (team.pricingNotice) {\n lines.push(chalkStderr.yellow(team.pricingNotice));\n }\n lines.push(`Join \"${displayName}\"?`);\n const join = await promptYesNo(ctx, {\n message: `${lines.join(\"\\n\")}`,\n default: true,\n });\n if (!join) continue;\n try {\n await fetch(\n new URL(\n `vercel/potential_teams/${team.teamId}/join`,\n `${provisionHost}/`,\n ),\n { method: \"POST\" },\n );\n logFinishedStep(`Joined ${displayName}`);\n } catch (err) {\n logFailure(`Failed to join ${displayName}: ${String(err)}`);\n }\n }\n}\n\n/// There are fields like version, but we keep them opaque\ntype OptIn = Record<string, unknown>;\n\ntype OptInToAccept = {\n optIn: OptIn;\n message: string;\n};\n\ntype AcceptOptInsArgs = {\n optInsAccepted: OptIn[];\n};\n\n// Returns whether we can proceed or not.\nasync function optins(ctx: Context, acceptOptIns: boolean): Promise<boolean> {\n const bbAuth = ctx.bigBrainAuth();\n if (bbAuth === null) {\n // This should never happen, but if we're not even logged in, we can't proceed.\n return false;\n }\n switch (bbAuth.kind) {\n case \"accessToken\":\n break;\n case \"deploymentKey\":\n case \"projectKey\":\n case \"previewDeployKey\":\n // If we have a key configured as auth, we do not need to check opt ins.\n return true;\n default: {\n bbAuth satisfies never;\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n errForSentry: `Unexpected auth kind ${(bbAuth as any).kind}`,\n printedMessage: \"Hit an unexpected error while logging in.\",\n });\n }\n }\n const data = await bigBrainAPI({\n ctx,\n method: \"POST\",\n path: \"check_opt_ins\",\n });\n if (data.optInsToAccept.length === 0) {\n return true;\n }\n for (const optInToAccept of data.optInsToAccept) {\n const confirmed =\n acceptOptIns ||\n (await promptYesNo(ctx, {\n message: optInToAccept.message,\n }));\n if (!confirmed) {\n logFailure(\"Please accept the Terms of Service to use Convex.\");\n return Promise.resolve(false);\n }\n }\n\n const optInsAccepted = data.optInsToAccept.map((o: OptInToAccept) => o.optIn);\n const args: AcceptOptInsArgs = { optInsAccepted };\n await bigBrainAPI({\n ctx,\n method: \"POST\",\n path: \"accept_opt_ins\",\n data: args,\n });\n return true;\n}\n\nexport async function ensureLoggedIn(\n ctx: Context,\n options?: {\n message?: string | undefined;\n overrideAuthUrl?: string | undefined;\n overrideAuthClient?: string | undefined;\n overrideAuthUsername?: string | undefined;\n overrideAuthPassword?: string | undefined;\n },\n) {\n const isLoggedIn = await checkAuthorization(ctx, false);\n if (!isLoggedIn) {\n if (options?.message) {\n logMessage(options.message);\n }\n await performLogin(ctx, {\n acceptOptIns: false,\n overrideAuthUrl: options?.overrideAuthUrl,\n overrideAuthClient: options?.overrideAuthClient,\n overrideAuthUsername: options?.overrideAuthUsername,\n overrideAuthPassword: options?.overrideAuthPassword,\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["open", "fetch"]
|
|
7
7
|
}
|
|
@@ -98,7 +98,11 @@ export function encodeDeploymentSelector(projectDir, deployment) {
|
|
|
98
98
|
projectDir,
|
|
99
99
|
deployment
|
|
100
100
|
};
|
|
101
|
-
|
|
101
|
+
const serialized = JSON.stringify(payload).replace(
|
|
102
|
+
/[\u0080-\uffff]/g,
|
|
103
|
+
(character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`
|
|
104
|
+
);
|
|
105
|
+
return `${deployment.kind}:${btoa(serialized)}`;
|
|
102
106
|
}
|
|
103
107
|
const payloadSchema = z.object({
|
|
104
108
|
projectDir: z.string(),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/cli/lib/mcp/requestContext.ts"],
|
|
4
|
-
"sourcesContent": ["import { BigBrainAuth, Context, ErrorType } from \"../../../bundler/context.js\";\nimport { Filesystem, nodeFs } from \"../../../bundler/fs.js\";\nimport { Ora } from \"ora\";\nimport {\n DeploymentSelectionWithinProject,\n deploymentSelectionWithinProjectSchema,\n DeploymentSelectionOptions,\n} from \"../api.js\";\nimport { z } from \"zod\";\nimport {\n DeploymentSelection,\n getDeploymentSelection,\n} from \"../deploymentSelection.js\";\n\nexport interface McpOptions extends DeploymentSelectionOptions {\n projectDir?: string;\n disableTools?: string;\n dangerouslyEnableProductionDeployments?: boolean;\n cautiouslyAllowProductionPii?: boolean;\n}\n\nexport class RequestContext implements Context {\n fs: Filesystem;\n deprecationMessagePrinted = false;\n spinner: Ora | undefined;\n _cleanupFns: Record<string, (exitCode: number, err?: any) => Promise<void>> =\n {};\n _bigBrainAuth: BigBrainAuth | null = null;\n constructor(public options: McpOptions) {\n this.fs = nodeFs;\n this.deprecationMessagePrinted = false;\n }\n\n async crash(args: {\n exitCode: number;\n errorType?: ErrorType;\n errForSentry?: any;\n printedMessage: string | null;\n }): Promise<never> {\n const cleanupFns = this._cleanupFns;\n this._cleanupFns = {};\n for (const fn of Object.values(cleanupFns)) {\n await fn(args.exitCode, args.errForSentry);\n }\n // eslint-disable-next-line no-restricted-syntax\n throw new RequestCrash(args.exitCode, args.errorType, args.printedMessage);\n }\n\n flushAndExit() {\n // eslint-disable-next-line no-restricted-syntax\n throw new Error(\"Not implemented\");\n }\n\n registerCleanup(fn: (exitCode: number, err?: any) => Promise<void>): string {\n const handle = crypto.randomUUID();\n this._cleanupFns[handle] = fn;\n return handle;\n }\n\n removeCleanup(handle: string) {\n const value = this._cleanupFns[handle];\n delete this._cleanupFns[handle];\n return value ?? null;\n }\n\n bigBrainAuth(): BigBrainAuth | null {\n return this._bigBrainAuth;\n }\n\n _updateBigBrainAuth(auth: BigBrainAuth | null): void {\n this._bigBrainAuth = auth;\n }\n\n async decodeDeploymentSelector(encoded: string) {\n const { projectDir, deployment } = decodeDeploymentSelector(encoded);\n if (\n deployment.kind === \"prod\" &&\n !this.options.dangerouslyEnableProductionDeployments\n ) {\n return await this.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage:\n \"This tool cannot be used with production deployments. Use a read-only tool like `insights` instead, or enable production access with --dangerously-enable-production-deployments.\",\n });\n }\n return { projectDir, deployment };\n }\n\n /** Decode a deployment selector without checking the production guard. Use for read-only tools that don't expose PII (e.g. insights). */\n decodeDeploymentSelectorUnchecked(encoded: string) {\n return decodeDeploymentSelector(encoded);\n }\n\n /** Decode a deployment selector for read-only tools that may expose PII (e.g. data, logs, queries). Requires --cautiously-allow-production-pii. */\n async decodeDeploymentSelectorReadOnly(encoded: string) {\n const { projectDir, deployment } = decodeDeploymentSelector(encoded);\n if (\n deployment.kind === \"prod\" &&\n !this.options.dangerouslyEnableProductionDeployments &&\n !this.options.cautiouslyAllowProductionPii\n ) {\n return await this.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage:\n \"This read-only tool may expose PII from production. Enable with --cautiously-allow-production-pii, or use --dangerously-enable-production-deployments for full access.\",\n });\n }\n return { projectDir, deployment };\n }\n\n get productionDeploymentsDisabled() {\n return !this.options.dangerouslyEnableProductionDeployments;\n }\n\n get productionPiiAllowed() {\n return (\n this.options.dangerouslyEnableProductionDeployments ||\n this.options.cautiouslyAllowProductionPii\n );\n }\n}\n\nexport class RequestCrash {\n printedMessage: string;\n constructor(\n private exitCode: number,\n private errorType: ErrorType | undefined,\n printedMessage: string | null,\n ) {\n this.printedMessage = printedMessage ?? \"Unknown error\";\n }\n\n toString(): string {\n return this.printedMessage;\n }\n}\n\n// Unfortunately, MCP clients don't seem to handle nested JSON objects very\n// well (even though this is within spec). To work around this, encode the\n// deployment selectors as an obfuscated string that the MCP client can\n// opaquely pass around.\nexport function encodeDeploymentSelector(\n projectDir: string,\n deployment: DeploymentSelectionWithinProject,\n) {\n const payload = {\n projectDir,\n deployment,\n };\n return `${deployment.kind}:${btoa(
|
|
5
|
-
"mappings": ";;;;AACA,SAAqB,cAAc;AAEnC;AAAA,EAEE;AAAA,OAEK;AACP,SAAS,SAAS;AAClB;AAAA,EAEE;AAAA,OACK;AASA,aAAM,eAAkC;AAAA,EAO7C,YAAmB,SAAqB;AAArB;AANnB;AACA,qDAA4B;AAC5B;AACA,uCACE,CAAC;AACH,yCAAqC;AAEnC,SAAK,KAAK;AACV,SAAK,4BAA4B;AAAA,EACnC;AAAA,EAEA,MAAM,MAAM,MAKO;AACjB,UAAM,aAAa,KAAK;AACxB,SAAK,cAAc,CAAC;AACpB,eAAW,MAAM,OAAO,OAAO,UAAU,GAAG;AAC1C,YAAM,GAAG,KAAK,UAAU,KAAK,YAAY;AAAA,IAC3C;AAEA,UAAM,IAAI,aAAa,KAAK,UAAU,KAAK,WAAW,KAAK,cAAc;AAAA,EAC3E;AAAA,EAEA,eAAe;AAEb,UAAM,IAAI,MAAM,iBAAiB;AAAA,EACnC;AAAA,EAEA,gBAAgB,IAA4D;AAC1E,UAAM,SAAS,OAAO,WAAW;AACjC,SAAK,YAAY,MAAM,IAAI;AAC3B,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,QAAgB;AAC5B,UAAM,QAAQ,KAAK,YAAY,MAAM;AACrC,WAAO,KAAK,YAAY,MAAM;AAC9B,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,eAAoC;AAClC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,oBAAoB,MAAiC;AACnD,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,MAAM,yBAAyB,SAAiB;AAC9C,UAAM,EAAE,YAAY,WAAW,IAAI,yBAAyB,OAAO;AACnE,QACE,WAAW,SAAS,UACpB,CAAC,KAAK,QAAQ,wCACd;AACA,aAAO,MAAM,KAAK,MAAM;AAAA,QACtB,UAAU;AAAA,QACV,WAAW;AAAA,QACX,gBACE;AAAA,MACJ,CAAC;AAAA,IACH;AACA,WAAO,EAAE,YAAY,WAAW;AAAA,EAClC;AAAA;AAAA,EAGA,kCAAkC,SAAiB;AACjD,WAAO,yBAAyB,OAAO;AAAA,EACzC;AAAA;AAAA,EAGA,MAAM,iCAAiC,SAAiB;AACtD,UAAM,EAAE,YAAY,WAAW,IAAI,yBAAyB,OAAO;AACnE,QACE,WAAW,SAAS,UACpB,CAAC,KAAK,QAAQ,0CACd,CAAC,KAAK,QAAQ,8BACd;AACA,aAAO,MAAM,KAAK,MAAM;AAAA,QACtB,UAAU;AAAA,QACV,WAAW;AAAA,QACX,gBACE;AAAA,MACJ,CAAC;AAAA,IACH;AACA,WAAO,EAAE,YAAY,WAAW;AAAA,EAClC;AAAA,EAEA,IAAI,gCAAgC;AAClC,WAAO,CAAC,KAAK,QAAQ;AAAA,EACvB;AAAA,EAEA,IAAI,uBAAuB;AACzB,WACE,KAAK,QAAQ,0CACb,KAAK,QAAQ;AAAA,EAEjB;AACF;AAEO,aAAM,aAAa;AAAA,EAExB,YACU,UACA,WACR,gBACA;AAHQ;AACA;AAHV;AAME,SAAK,iBAAiB,kBAAkB;AAAA,EAC1C;AAAA,EAEA,WAAmB;AACjB,WAAO,KAAK;AAAA,EACd;AACF;AAMO,gBAAS,yBACd,YACA,YACA;AACA,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,EACF;AACA,SAAO,GAAG,WAAW,IAAI,IAAI,KAAK,
|
|
4
|
+
"sourcesContent": ["import { BigBrainAuth, Context, ErrorType } from \"../../../bundler/context.js\";\nimport { Filesystem, nodeFs } from \"../../../bundler/fs.js\";\nimport { Ora } from \"ora\";\nimport {\n DeploymentSelectionWithinProject,\n deploymentSelectionWithinProjectSchema,\n DeploymentSelectionOptions,\n} from \"../api.js\";\nimport { z } from \"zod\";\nimport {\n DeploymentSelection,\n getDeploymentSelection,\n} from \"../deploymentSelection.js\";\n\nexport interface McpOptions extends DeploymentSelectionOptions {\n projectDir?: string;\n disableTools?: string;\n dangerouslyEnableProductionDeployments?: boolean;\n cautiouslyAllowProductionPii?: boolean;\n}\n\nexport class RequestContext implements Context {\n fs: Filesystem;\n deprecationMessagePrinted = false;\n spinner: Ora | undefined;\n _cleanupFns: Record<string, (exitCode: number, err?: any) => Promise<void>> =\n {};\n _bigBrainAuth: BigBrainAuth | null = null;\n constructor(public options: McpOptions) {\n this.fs = nodeFs;\n this.deprecationMessagePrinted = false;\n }\n\n async crash(args: {\n exitCode: number;\n errorType?: ErrorType;\n errForSentry?: any;\n printedMessage: string | null;\n }): Promise<never> {\n const cleanupFns = this._cleanupFns;\n this._cleanupFns = {};\n for (const fn of Object.values(cleanupFns)) {\n await fn(args.exitCode, args.errForSentry);\n }\n // eslint-disable-next-line no-restricted-syntax\n throw new RequestCrash(args.exitCode, args.errorType, args.printedMessage);\n }\n\n flushAndExit() {\n // eslint-disable-next-line no-restricted-syntax\n throw new Error(\"Not implemented\");\n }\n\n registerCleanup(fn: (exitCode: number, err?: any) => Promise<void>): string {\n const handle = crypto.randomUUID();\n this._cleanupFns[handle] = fn;\n return handle;\n }\n\n removeCleanup(handle: string) {\n const value = this._cleanupFns[handle];\n delete this._cleanupFns[handle];\n return value ?? null;\n }\n\n bigBrainAuth(): BigBrainAuth | null {\n return this._bigBrainAuth;\n }\n\n _updateBigBrainAuth(auth: BigBrainAuth | null): void {\n this._bigBrainAuth = auth;\n }\n\n async decodeDeploymentSelector(encoded: string) {\n const { projectDir, deployment } = decodeDeploymentSelector(encoded);\n if (\n deployment.kind === \"prod\" &&\n !this.options.dangerouslyEnableProductionDeployments\n ) {\n return await this.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage:\n \"This tool cannot be used with production deployments. Use a read-only tool like `insights` instead, or enable production access with --dangerously-enable-production-deployments.\",\n });\n }\n return { projectDir, deployment };\n }\n\n /** Decode a deployment selector without checking the production guard. Use for read-only tools that don't expose PII (e.g. insights). */\n decodeDeploymentSelectorUnchecked(encoded: string) {\n return decodeDeploymentSelector(encoded);\n }\n\n /** Decode a deployment selector for read-only tools that may expose PII (e.g. data, logs, queries). Requires --cautiously-allow-production-pii. */\n async decodeDeploymentSelectorReadOnly(encoded: string) {\n const { projectDir, deployment } = decodeDeploymentSelector(encoded);\n if (\n deployment.kind === \"prod\" &&\n !this.options.dangerouslyEnableProductionDeployments &&\n !this.options.cautiouslyAllowProductionPii\n ) {\n return await this.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage:\n \"This read-only tool may expose PII from production. Enable with --cautiously-allow-production-pii, or use --dangerously-enable-production-deployments for full access.\",\n });\n }\n return { projectDir, deployment };\n }\n\n get productionDeploymentsDisabled() {\n return !this.options.dangerouslyEnableProductionDeployments;\n }\n\n get productionPiiAllowed() {\n return (\n this.options.dangerouslyEnableProductionDeployments ||\n this.options.cautiouslyAllowProductionPii\n );\n }\n}\n\nexport class RequestCrash {\n printedMessage: string;\n constructor(\n private exitCode: number,\n private errorType: ErrorType | undefined,\n printedMessage: string | null,\n ) {\n this.printedMessage = printedMessage ?? \"Unknown error\";\n }\n\n toString(): string {\n return this.printedMessage;\n }\n}\n\n// Unfortunately, MCP clients don't seem to handle nested JSON objects very\n// well (even though this is within spec). To work around this, encode the\n// deployment selectors as an obfuscated string that the MCP client can\n// opaquely pass around.\nexport function encodeDeploymentSelector(\n projectDir: string,\n deployment: DeploymentSelectionWithinProject,\n) {\n const payload = {\n projectDir,\n deployment,\n };\n // ASCII JSON escapes support Unicode paths with the existing Latin-1 decoder.\n const serialized = JSON.stringify(payload).replace(\n /[\\u0080-\\uffff]/g,\n (character) =>\n `\\\\u${character.charCodeAt(0).toString(16).padStart(4, \"0\")}`,\n );\n return `${deployment.kind}:${btoa(serialized)}`;\n}\n\nconst payloadSchema = z.object({\n projectDir: z.string(),\n deployment: deploymentSelectionWithinProjectSchema,\n});\n\nfunction decodeDeploymentSelector(encoded: string) {\n const [_, serializedPayload] = encoded.split(\":\");\n return payloadSchema.parse(JSON.parse(atob(serializedPayload)));\n}\n\n/**\n * Get the deployment selection for MCP tools. The agent can pass different\n * values of `selectionWithinProject` into a tool, so we overwrite the\n * `selectionWithinProject` of the `DeploymentSelection` if it exists.\n */\nexport async function getMcpDeploymentSelection(\n ctx: RequestContext,\n decodedDeploymentSelector: DeploymentSelectionWithinProject,\n): Promise<DeploymentSelection> {\n const initialSelection = await getDeploymentSelection(ctx, ctx.options);\n const hasSelectionWithinProject =\n initialSelection.kind !== \"existingDeployment\";\n return {\n ...initialSelection,\n ...(hasSelectionWithinProject && {\n selectionWithinProject: decodedDeploymentSelector,\n }),\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -7,19 +7,22 @@ import { getMcpDeploymentSelection } from "../requestContext.js";
|
|
|
7
7
|
const envListInputSchema = z.object({
|
|
8
8
|
deploymentSelector: z.string().describe(
|
|
9
9
|
"Deployment selector (from the status tool) to list environment variables from."
|
|
10
|
+
),
|
|
11
|
+
includeValues: z.boolean().optional().describe(
|
|
12
|
+
"Also return each variable's value. Values are often secrets like API keys, so leave this off unless you need every value, and use envGet to read a single variable instead."
|
|
10
13
|
)
|
|
11
14
|
});
|
|
12
15
|
const envListOutputSchema = z.object({
|
|
13
16
|
variables: z.array(
|
|
14
17
|
z.object({
|
|
15
18
|
name: z.string(),
|
|
16
|
-
value: z.string()
|
|
19
|
+
value: z.string().optional().describe("Only present when includeValues is true.")
|
|
17
20
|
})
|
|
18
21
|
)
|
|
19
22
|
});
|
|
20
23
|
export const EnvListTool = {
|
|
21
24
|
name: "envList",
|
|
22
|
-
description: "List all environment variables in your Convex deployment.",
|
|
25
|
+
description: "List the names of all environment variables in your Convex deployment. Values are left out unless includeValues is true.",
|
|
23
26
|
inputSchema: envListInputSchema,
|
|
24
27
|
outputSchema: envListOutputSchema,
|
|
25
28
|
handler: async (ctx, args) => {
|
|
@@ -42,7 +45,11 @@ export const EnvListTool = {
|
|
|
42
45
|
componentPath: void 0,
|
|
43
46
|
args: {}
|
|
44
47
|
});
|
|
45
|
-
return {
|
|
48
|
+
return {
|
|
49
|
+
variables: variables.map(
|
|
50
|
+
({ name, value }) => args.includeValues ? { name, value } : { name }
|
|
51
|
+
)
|
|
52
|
+
};
|
|
46
53
|
}
|
|
47
54
|
};
|
|
48
55
|
const envGetInputSchema = z.object({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/cli/lib/mcp/tools/env.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from \"zod\";\nimport { ConvexTool } from \"./index.js\";\nimport { loadSelectedDeploymentCredentials } from \"../../api.js\";\nimport { deploymentEnvBackend, envSet, envRemove, EnvVar } from \"../../env.js\";\nimport { runSystemQuery } from \"../../run.js\";\nimport { getMcpDeploymentSelection } from \"../requestContext.js\";\n\n// List Environment Variables\nconst envListInputSchema = z.object({\n deploymentSelector: z\n .string()\n .describe(\n \"Deployment selector (from the status tool) to list environment variables from.\",\n ),\n});\n\nconst envListOutputSchema = z.object({\n variables: z.array(\n z.object({\n name: z.string(),\n value: z.string(),\n }),\n ),\n});\n\nexport const EnvListTool: ConvexTool<\n typeof envListInputSchema,\n typeof envListOutputSchema\n> = {\n name: \"envList\",\n description
|
|
5
|
-
"mappings": ";AAAA,SAAS,SAAS;AAElB,SAAS,yCAAyC;AAClD,SAAS,sBAAsB,QAAQ,iBAAyB;AAChE,SAAS,sBAAsB;AAC/B,SAAS,iCAAiC;AAG1C,MAAM,qBAAqB,EAAE,OAAO;AAAA,EAClC,oBAAoB,EACjB,OAAO,EACP;AAAA,IACC;AAAA,EACF;AACJ,CAAC;AAED,MAAM,sBAAsB,EAAE,OAAO;AAAA,EACnC,WAAW,EAAE;AAAA,IACX,EAAE,OAAO;AAAA,MACP,MAAM,EAAE,OAAO;AAAA,MACf,OAAO,
|
|
4
|
+
"sourcesContent": ["import { z } from \"zod\";\nimport { ConvexTool } from \"./index.js\";\nimport { loadSelectedDeploymentCredentials } from \"../../api.js\";\nimport { deploymentEnvBackend, envSet, envRemove, EnvVar } from \"../../env.js\";\nimport { runSystemQuery } from \"../../run.js\";\nimport { getMcpDeploymentSelection } from \"../requestContext.js\";\n\n// List Environment Variables\nconst envListInputSchema = z.object({\n deploymentSelector: z\n .string()\n .describe(\n \"Deployment selector (from the status tool) to list environment variables from.\",\n ),\n includeValues: z\n .boolean()\n .optional()\n .describe(\n \"Also return each variable's value. Values are often secrets like API keys, so leave this off unless you need every value, and use envGet to read a single variable instead.\",\n ),\n});\n\nconst envListOutputSchema = z.object({\n variables: z.array(\n z.object({\n name: z.string(),\n value: z\n .string()\n .optional()\n .describe(\"Only present when includeValues is true.\"),\n }),\n ),\n});\n\nexport const EnvListTool: ConvexTool<\n typeof envListInputSchema,\n typeof envListOutputSchema\n> = {\n name: \"envList\",\n description:\n \"List the names of all environment variables in your Convex deployment. Values are left out unless includeValues is true.\",\n inputSchema: envListInputSchema,\n outputSchema: envListOutputSchema,\n handler: async (ctx, args) => {\n const { projectDir, deployment } = await ctx.decodeDeploymentSelector(\n args.deploymentSelector,\n );\n process.chdir(projectDir);\n const deploymentSelection = await getMcpDeploymentSelection(\n ctx,\n deployment,\n );\n const credentials = await loadSelectedDeploymentCredentials(\n ctx,\n deploymentSelection,\n );\n const variables = (await runSystemQuery(ctx, {\n deploymentUrl: credentials.url,\n adminKey: credentials.adminKey,\n functionName: \"_system/cli/queryEnvironmentVariables\",\n componentPath: undefined,\n args: {},\n })) as EnvVar[];\n return {\n variables: variables.map(({ name, value }) =>\n args.includeValues ? { name, value } : { name },\n ),\n };\n },\n};\n\n// Get Environment Variable\nconst envGetInputSchema = z.object({\n deploymentSelector: z\n .string()\n .describe(\n \"Deployment selector (from the status tool) to get environment variable from.\",\n ),\n name: z\n .string()\n .describe(\"The name of the environment variable to retrieve.\"),\n});\n\nconst envGetOutputSchema = z.object({\n value: z.union([z.string(), z.null()]),\n});\n\nexport const EnvGetTool: ConvexTool<\n typeof envGetInputSchema,\n typeof envGetOutputSchema\n> = {\n name: \"envGet\",\n description:\n \"Get a specific environment variable from your Convex deployment.\",\n inputSchema: envGetInputSchema,\n outputSchema: envGetOutputSchema,\n handler: async (ctx, args) => {\n const { projectDir, deployment } = await ctx.decodeDeploymentSelector(\n args.deploymentSelector,\n );\n process.chdir(projectDir);\n const deploymentSelection = await getMcpDeploymentSelection(\n ctx,\n deployment,\n );\n const credentials = await loadSelectedDeploymentCredentials(\n ctx,\n deploymentSelection,\n );\n const envVar = (await runSystemQuery(ctx, {\n deploymentUrl: credentials.url,\n adminKey: credentials.adminKey,\n functionName: \"_system/cli/queryEnvironmentVariables:get\",\n componentPath: undefined,\n args: { name: args.name },\n })) as { name: string; value: string } | null;\n return { value: envVar?.value ?? null };\n },\n};\n\n// Set Environment Variable\nconst envSetInputSchema = z.object({\n deploymentSelector: z\n .string()\n .describe(\n \"Deployment selector (from the status tool) to set environment variable on.\",\n ),\n name: z.string().describe(\"The name of the environment variable to set.\"),\n value: z.string().describe(\"The value to set for the environment variable.\"),\n});\n\nconst envSetOutputSchema = z.object({\n success: z.boolean(),\n});\n\nexport const EnvSetTool: ConvexTool<\n typeof envSetInputSchema,\n typeof envSetOutputSchema\n> = {\n name: \"envSet\",\n description: \"Set an environment variable in your Convex deployment.\",\n inputSchema: envSetInputSchema,\n outputSchema: envSetOutputSchema,\n handler: async (ctx, args) => {\n const { projectDir, deployment } = await ctx.decodeDeploymentSelector(\n args.deploymentSelector,\n );\n process.chdir(projectDir);\n const deploymentSelection = await getMcpDeploymentSelection(\n ctx,\n deployment,\n );\n const credentials = await loadSelectedDeploymentCredentials(\n ctx,\n deploymentSelection,\n );\n const deploymentInfo = {\n deploymentUrl: credentials.url,\n adminKey: credentials.adminKey,\n deploymentNotice: \"\",\n };\n const backend = deploymentEnvBackend(ctx, deploymentInfo);\n await envSet(ctx, backend, args.name, args.value);\n return { success: true };\n },\n};\n\n// Remove Environment Variable\nconst envRemoveInputSchema = z.object({\n deploymentSelector: z\n .string()\n .describe(\n \"Deployment selector (from the status tool) to remove environment variable from.\",\n ),\n name: z.string().describe(\"The name of the environment variable to remove.\"),\n});\n\nconst envRemoveOutputSchema = z.object({\n success: z.boolean(),\n});\n\nexport const EnvRemoveTool: ConvexTool<\n typeof envRemoveInputSchema,\n typeof envRemoveOutputSchema\n> = {\n name: \"envRemove\",\n description: \"Remove an environment variable from your Convex deployment.\",\n inputSchema: envRemoveInputSchema,\n outputSchema: envRemoveOutputSchema,\n handler: async (ctx, args) => {\n const { projectDir, deployment } = await ctx.decodeDeploymentSelector(\n args.deploymentSelector,\n );\n process.chdir(projectDir);\n const deploymentSelection = await getMcpDeploymentSelection(\n ctx,\n deployment,\n );\n const credentials = await loadSelectedDeploymentCredentials(\n ctx,\n deploymentSelection,\n );\n const deploymentInfo = {\n deploymentUrl: credentials.url,\n adminKey: credentials.adminKey,\n deploymentNotice: \"\",\n };\n const backend = deploymentEnvBackend(ctx, deploymentInfo);\n await envRemove(ctx, backend, args.name);\n return { success: true };\n },\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|