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
|
@@ -47,6 +47,8 @@ var import_child_process = require("child_process");
|
|
|
47
47
|
var import_prompts = require("./utils/prompts.js");
|
|
48
48
|
var import_globalConfig = require("./utils/globalConfig.js");
|
|
49
49
|
var import_deploymentSelection = require("./deploymentSelection.js");
|
|
50
|
+
var import_profiles = require("./profiles.js");
|
|
51
|
+
var import_profileManagement = require("./profileManagement.js");
|
|
50
52
|
import_openid_client.custom.setHttpOptionsDefaults({
|
|
51
53
|
timeout: parseInt(process.env.OPENID_CLIENT_TIMEOUT || "10000")
|
|
52
54
|
});
|
|
@@ -213,8 +215,11 @@ async function performLogin(ctx, {
|
|
|
213
215
|
deviceName: deviceNameOverride,
|
|
214
216
|
anonymousId,
|
|
215
217
|
vercel,
|
|
216
|
-
vercelOverride
|
|
218
|
+
vercelOverride,
|
|
219
|
+
profile: selectedProfile
|
|
217
220
|
} = {}) {
|
|
221
|
+
const auth = ctx.bigBrainAuth();
|
|
222
|
+
const profile = selectedProfile !== void 0 ? selectedProfile : auth?.kind === "accessToken" && auth.profile !== void 0 ? auth.profile : await (0, import_profiles.getProfileSelection)(ctx);
|
|
218
223
|
loginFlow = loginFlow || "auto";
|
|
219
224
|
let deviceName = deviceNameOverride ?? "";
|
|
220
225
|
if (!deviceName && process.platform === "darwin") {
|
|
@@ -287,6 +292,8 @@ async function performLogin(ctx, {
|
|
|
287
292
|
printedMessage: null
|
|
288
293
|
});
|
|
289
294
|
}
|
|
295
|
+
const previous = profile === null ? null : await (0, import_profiles.readProfileCredentials)(ctx, profile, true);
|
|
296
|
+
const metadata = profile === null ? {} : await (0, import_profileManagement.profileLoginMetadata)(ctx, profile, accessToken, previous);
|
|
290
297
|
ctx._updateBigBrainAuth({
|
|
291
298
|
accessToken,
|
|
292
299
|
kind: "accessToken",
|
|
@@ -304,8 +311,18 @@ async function performLogin(ctx, {
|
|
|
304
311
|
const newAccessToken = response.data.accessToken;
|
|
305
312
|
const globalConfig = { accessToken: newAccessToken };
|
|
306
313
|
try {
|
|
307
|
-
|
|
308
|
-
|
|
314
|
+
if (profile !== null) {
|
|
315
|
+
await (0, import_profiles.writeProfileCredentials)(
|
|
316
|
+
ctx,
|
|
317
|
+
profile.name,
|
|
318
|
+
newAccessToken,
|
|
319
|
+
metadata,
|
|
320
|
+
previous
|
|
321
|
+
);
|
|
322
|
+
} else {
|
|
323
|
+
await (0, import_globalConfig.modifyGlobalConfig)(ctx, globalConfig);
|
|
324
|
+
}
|
|
325
|
+
const path = profile !== null ? (0, import_profiles.profileConfigPath)(profile.name) : (0, import_globalConfig.globalConfigPath)();
|
|
309
326
|
(0, import_log.logFinishedStep)(`Saved credentials to ${(0, import_globalConfig.formatPathForPrinting)(path)}`);
|
|
310
327
|
} catch (err) {
|
|
311
328
|
return await ctx.crash({
|
|
@@ -315,8 +332,15 @@ async function performLogin(ctx, {
|
|
|
315
332
|
printedMessage: null
|
|
316
333
|
});
|
|
317
334
|
}
|
|
335
|
+
if (profile !== null) {
|
|
336
|
+
await (0, import_profileManagement.revokeReplacedProfileToken)(
|
|
337
|
+
ctx,
|
|
338
|
+
previous?.accessToken,
|
|
339
|
+
newAccessToken
|
|
340
|
+
);
|
|
341
|
+
}
|
|
318
342
|
(0, import_log.logVerbose)(`performLogin: updating big brain auth after login`);
|
|
319
|
-
await (0, import_deploymentSelection.updateBigBrainAuthAfterLogin)(ctx, newAccessToken);
|
|
343
|
+
await (0, import_deploymentSelection.updateBigBrainAuthAfterLogin)(ctx, newAccessToken, profile ?? void 0);
|
|
320
344
|
(0, import_log.logVerbose)(`performLogin: checking opt ins, acceptOptIns: ${acceptOptIns}`);
|
|
321
345
|
const shouldContinue = await optins(ctx, acceptOptIns ?? false);
|
|
322
346
|
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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAA2C;AAC3C,mBAOO;AACP,kBAAiB;AACjB,mBAA4B;AAC5B,oBAA8B;AAC9B,qBAAwB;AAExB,iBASO;AACP,IAAAA,wBAAuB;AACvB,gBAAyB;AACzB,2BAAyB;AACzB,qBAA0C;AAC1C,0BAIO;AACP,iCAA6C;
|
|
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": ["import_openid_client", "open", "fetch"]
|
|
7
7
|
}
|
|
@@ -118,7 +118,11 @@ function encodeDeploymentSelector(projectDir, deployment) {
|
|
|
118
118
|
projectDir,
|
|
119
119
|
deployment
|
|
120
120
|
};
|
|
121
|
-
|
|
121
|
+
const serialized = JSON.stringify(payload).replace(
|
|
122
|
+
/[\u0080-\uffff]/g,
|
|
123
|
+
(character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`
|
|
124
|
+
);
|
|
125
|
+
return `${deployment.kind}:${btoa(serialized)}`;
|
|
122
126
|
}
|
|
123
127
|
const payloadSchema = import_zod.z.object({
|
|
124
128
|
projectDir: import_zod.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": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,gBAAmC;AAEnC,iBAIO;AACP,iBAAkB;AAClB,iCAGO;AASA,MAAM,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,MAAM,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,SAAS,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
|
}
|
|
@@ -32,19 +32,22 @@ var import_requestContext = require("../requestContext.js");
|
|
|
32
32
|
const envListInputSchema = import_zod.z.object({
|
|
33
33
|
deploymentSelector: import_zod.z.string().describe(
|
|
34
34
|
"Deployment selector (from the status tool) to list environment variables from."
|
|
35
|
+
),
|
|
36
|
+
includeValues: import_zod.z.boolean().optional().describe(
|
|
37
|
+
"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."
|
|
35
38
|
)
|
|
36
39
|
});
|
|
37
40
|
const envListOutputSchema = import_zod.z.object({
|
|
38
41
|
variables: import_zod.z.array(
|
|
39
42
|
import_zod.z.object({
|
|
40
43
|
name: import_zod.z.string(),
|
|
41
|
-
value: import_zod.z.string()
|
|
44
|
+
value: import_zod.z.string().optional().describe("Only present when includeValues is true.")
|
|
42
45
|
})
|
|
43
46
|
)
|
|
44
47
|
});
|
|
45
48
|
const EnvListTool = {
|
|
46
49
|
name: "envList",
|
|
47
|
-
description: "List all environment variables in your Convex deployment.",
|
|
50
|
+
description: "List the names of all environment variables in your Convex deployment. Values are left out unless includeValues is true.",
|
|
48
51
|
inputSchema: envListInputSchema,
|
|
49
52
|
outputSchema: envListOutputSchema,
|
|
50
53
|
handler: async (ctx, args) => {
|
|
@@ -67,7 +70,11 @@ const EnvListTool = {
|
|
|
67
70
|
componentPath: void 0,
|
|
68
71
|
args: {}
|
|
69
72
|
});
|
|
70
|
-
return {
|
|
73
|
+
return {
|
|
74
|
+
variables: variables.map(
|
|
75
|
+
({ name, value }) => args.includeValues ? { name, value } : { name }
|
|
76
|
+
)
|
|
77
|
+
};
|
|
71
78
|
}
|
|
72
79
|
};
|
|
73
80
|
const envGetInputSchema = import_zod.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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAkB;AAElB,iBAAkD;AAClD,iBAAgE;AAChE,iBAA+B;AAC/B,4BAA0C;AAG1C,MAAM,qBAAqB,aAAE,OAAO;AAAA,EAClC,oBAAoB,aACjB,OAAO,EACP;AAAA,IACC;AAAA,EACF;AACJ,CAAC;AAED,MAAM,sBAAsB,aAAE,OAAO;AAAA,EACnC,WAAW,aAAE;AAAA,IACX,aAAE,OAAO;AAAA,MACP,MAAM,aAAE,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
|
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var profileManagement_exports = {};
|
|
20
|
+
__export(profileManagement_exports, {
|
|
21
|
+
bindProfileToDirectory: () => bindProfileToDirectory,
|
|
22
|
+
deploymentAccess: () => deploymentAccess,
|
|
23
|
+
profileApi: () => profileApi,
|
|
24
|
+
profileLoginMetadata: () => profileLoginMetadata,
|
|
25
|
+
projectAccess: () => projectAccess,
|
|
26
|
+
revokeReplacedProfileToken: () => revokeReplacedProfileToken
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(profileManagement_exports);
|
|
29
|
+
var import_log = require("../../bundler/log.js");
|
|
30
|
+
var import_config = require("./config.js");
|
|
31
|
+
var import_version = require("../version.js");
|
|
32
|
+
var import_deployment = require("./deployment.js");
|
|
33
|
+
var import_utils = require("./utils/utils.js");
|
|
34
|
+
var import_prompts = require("./utils/prompts.js");
|
|
35
|
+
var import_envvars = require("./envvars.js");
|
|
36
|
+
var import_profiles = require("./profiles.js");
|
|
37
|
+
async function profileApi(token, pathname, body) {
|
|
38
|
+
return await fetch(`${import_config.provisionHost}${pathname}`, {
|
|
39
|
+
method: body === void 0 ? "GET" : "POST",
|
|
40
|
+
headers: {
|
|
41
|
+
Authorization: `Bearer ${token}`,
|
|
42
|
+
"Convex-Client": `npm-cli-${import_version.version}`,
|
|
43
|
+
...body === void 0 ? {} : { "Content-Type": "application/json" }
|
|
44
|
+
},
|
|
45
|
+
...body === void 0 ? {} : { body: JSON.stringify(body) },
|
|
46
|
+
signal: AbortSignal.timeout(1e4)
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async function deploymentAccess(token, deploymentName) {
|
|
50
|
+
try {
|
|
51
|
+
const response = await profileApi(
|
|
52
|
+
token,
|
|
53
|
+
`/v1/deployments/${encodeURIComponent(deploymentName)}`
|
|
54
|
+
);
|
|
55
|
+
if (response.ok) return "yes";
|
|
56
|
+
return [401, 403, 404].includes(response.status) ? "no" : "unknown";
|
|
57
|
+
} catch {
|
|
58
|
+
return "unknown";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function projectAccess(token, target) {
|
|
62
|
+
if (target.kind === "deploymentName")
|
|
63
|
+
return deploymentAccess(token, target.deploymentName);
|
|
64
|
+
if (target.kind !== "teamAndProjectSlugs") return "unknown";
|
|
65
|
+
try {
|
|
66
|
+
const response = await profileApi(
|
|
67
|
+
token,
|
|
68
|
+
`/v1/teams/${encodeURIComponent(target.teamSlug)}/projects/${encodeURIComponent(target.projectSlug)}`
|
|
69
|
+
);
|
|
70
|
+
if (response.ok) return "yes";
|
|
71
|
+
return [401, 403, 404].includes(response.status) ? "no" : "unknown";
|
|
72
|
+
} catch {
|
|
73
|
+
return "unknown";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function configuredCloudDeployment() {
|
|
77
|
+
const configured = process.env[import_utils.CONVEX_DEPLOYMENT_ENV_VAR_NAME]?.trim();
|
|
78
|
+
if (!configured || (0, import_deployment.getDeploymentTypeFromConfiguredDeployment)(configured) === "local")
|
|
79
|
+
return null;
|
|
80
|
+
const name = (0, import_deployment.stripDeploymentTypePrefix)(configured);
|
|
81
|
+
return (0, import_deployment.isAnonymousDeployment)(name) ? null : name;
|
|
82
|
+
}
|
|
83
|
+
async function bindProfileToDirectory(ctx, name, force = false, target) {
|
|
84
|
+
const credentials = await (0, import_profiles.readProfileCredentials)(ctx, {
|
|
85
|
+
name,
|
|
86
|
+
source: "account selection"
|
|
87
|
+
});
|
|
88
|
+
(0, import_envvars.loadProjectEnvironmentVariables)();
|
|
89
|
+
const deployment = configuredCloudDeployment();
|
|
90
|
+
const selectedTarget = target ?? (deployment === null ? null : {
|
|
91
|
+
kind: "deploymentName",
|
|
92
|
+
deploymentName: deployment,
|
|
93
|
+
deploymentType: null
|
|
94
|
+
});
|
|
95
|
+
if (!force && selectedTarget !== null) {
|
|
96
|
+
const label = selectedTarget.kind === "teamAndProjectSlugs" ? `project "${selectedTarget.teamSlug}/${selectedTarget.projectSlug}"` : `deployment "${selectedTarget.kind === "deploymentName" ? selectedTarget.deploymentName : "configured"}"`;
|
|
97
|
+
const access = await projectAccess(
|
|
98
|
+
credentials.accessToken,
|
|
99
|
+
selectedTarget
|
|
100
|
+
);
|
|
101
|
+
if (access !== "yes") {
|
|
102
|
+
(0, import_log.logWarning)(
|
|
103
|
+
access === "no" ? `Account "${name}" cannot access ${label}.` : `Could not verify whether account "${name}" can access ${label}.`
|
|
104
|
+
);
|
|
105
|
+
if (!process.stdin.isTTY || !await (0, import_prompts.promptYesNo)(ctx, {
|
|
106
|
+
message: `Use account "${name}" here anyway?`,
|
|
107
|
+
default: false
|
|
108
|
+
})) {
|
|
109
|
+
(0, import_log.logMessage)(
|
|
110
|
+
`Directory selection unchanged. To select this account anyway, run \`npx convex account select ${name} --force\`.`
|
|
111
|
+
);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
await (0, import_profiles.writeProfileDirectory)(ctx, name);
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
async function profileLoginMetadata(ctx, profile, loginToken, previous) {
|
|
120
|
+
let identity = null;
|
|
121
|
+
try {
|
|
122
|
+
const response = await profileApi(loginToken, "/api/dashboard/profile");
|
|
123
|
+
if (response.ok) {
|
|
124
|
+
const data = await response.json();
|
|
125
|
+
if ((typeof data.id === "number" || typeof data.id === "string") && typeof data.email === "string") {
|
|
126
|
+
identity = { memberId: String(data.id), email: data.email };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
} catch {
|
|
130
|
+
}
|
|
131
|
+
const sameAccount = previous !== null && (previous.memberId === void 0 || identity === null) ? await tokensBelongToSameAccount(previous.accessToken, loginToken) : null;
|
|
132
|
+
if (previous !== null && (previous.memberId === void 0 || identity === null ? sameAccount !== true : identity.memberId !== previous.memberId)) {
|
|
133
|
+
return await ctx.crash({
|
|
134
|
+
exitCode: 1,
|
|
135
|
+
errorType: "fatal",
|
|
136
|
+
printedMessage: sameAccount === null && (previous.memberId === void 0 || identity === null) ? `Could not verify the identity of saved account "${profile.name}". To replace this saved login, run \`npx convex logout --account ${profile.name}\` followed by \`npx convex login --account ${profile.name}\`. Choose the intended account when logging in.` : `The login does not match saved account "${profile.name}". Log in with the matching account, or choose another name with \`npx convex login --account <name>\`.`
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
...identity ?? (previous?.memberId === void 0 ? {} : { memberId: previous.memberId, email: previous.email })
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
async function tokensBelongToSameAccount(older, newer) {
|
|
144
|
+
try {
|
|
145
|
+
const responses = await Promise.all(
|
|
146
|
+
[older, newer].map(
|
|
147
|
+
(token) => profileApi(token, "/v1/list_personal_access_tokens?limit=100")
|
|
148
|
+
)
|
|
149
|
+
);
|
|
150
|
+
if (responses.some((response) => !response.ok)) return null;
|
|
151
|
+
const lists = await Promise.all(
|
|
152
|
+
responses.map((response) => response.json())
|
|
153
|
+
);
|
|
154
|
+
if (lists.some(
|
|
155
|
+
(list) => !Array.isArray(list.items) || list.items.length === 0
|
|
156
|
+
))
|
|
157
|
+
return null;
|
|
158
|
+
const ids = new Set(
|
|
159
|
+
lists[0].items.map((token) => String(token.id))
|
|
160
|
+
);
|
|
161
|
+
if (lists[1].items.some((token) => ids.has(String(token.id))))
|
|
162
|
+
return true;
|
|
163
|
+
return lists.some((list) => list.pagination?.hasMore !== false) ? null : false;
|
|
164
|
+
} catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
async function revokeReplacedProfileToken(ctx, previous, accessToken) {
|
|
169
|
+
if (previous === void 0 || previous === accessToken) return;
|
|
170
|
+
const settings = await (0, import_profiles.readProfileSettings)(ctx);
|
|
171
|
+
if (settings.revokeReplacedTokens === false || settings.accessToken === previous)
|
|
172
|
+
return;
|
|
173
|
+
for (const name of (0, import_profiles.savedProfileNames)(ctx)) {
|
|
174
|
+
const token = (0, import_profiles.readProfileToken)(ctx, name);
|
|
175
|
+
if (token === null) {
|
|
176
|
+
(0, import_log.logWarning)(
|
|
177
|
+
`The new login was saved, but account "${name}" could not be read. Skipping revocation of the replaced token.`
|
|
178
|
+
);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (token === previous) return;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
const response = await profileApi(
|
|
185
|
+
accessToken,
|
|
186
|
+
"/v1/delete_personal_access_token",
|
|
187
|
+
{ id: previous }
|
|
188
|
+
);
|
|
189
|
+
if (response.ok) return;
|
|
190
|
+
} catch {
|
|
191
|
+
}
|
|
192
|
+
(0, import_log.logWarning)(
|
|
193
|
+
"The new login was saved, but the replaced token could not be revoked. You can remove it in the dashboard's account settings."
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=profileManagement.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/cli/lib/profileManagement.ts"],
|
|
4
|
+
"sourcesContent": ["import { ProjectSelection } from \"./deploymentSelection.js\";\nimport { Context } from \"../../bundler/context.js\";\nimport { logMessage, logWarning } from \"../../bundler/log.js\";\nimport { provisionHost } from \"./config.js\";\nimport { version } from \"../version.js\";\nimport {\n isAnonymousDeployment,\n getDeploymentTypeFromConfiguredDeployment,\n stripDeploymentTypePrefix,\n} from \"./deployment.js\";\nimport { CONVEX_DEPLOYMENT_ENV_VAR_NAME } from \"./utils/utils.js\";\nimport { promptYesNo } from \"./utils/prompts.js\";\nimport { loadProjectEnvironmentVariables } from \"./envvars.js\";\nimport {\n ProfileCredentials,\n ProfileSelection,\n readProfileCredentials,\n readProfileSettings,\n readProfileToken,\n savedProfileNames,\n writeProfileDirectory,\n} from \"./profiles.js\";\n\nexport async function profileApi(\n token: string,\n pathname: string,\n body?: unknown,\n) {\n return await fetch(`${provisionHost}${pathname}`, {\n method: body === undefined ? \"GET\" : \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Convex-Client\": `npm-cli-${version}`,\n ...(body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n },\n ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n signal: AbortSignal.timeout(10_000),\n });\n}\n\nexport async function deploymentAccess(\n token: string,\n deploymentName: string,\n): Promise<\"yes\" | \"no\" | \"unknown\"> {\n try {\n const response = await profileApi(\n token,\n `/v1/deployments/${encodeURIComponent(deploymentName)}`,\n );\n if (response.ok) return \"yes\";\n return [401, 403, 404].includes(response.status) ? \"no\" : \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nexport async function projectAccess(\n token: string,\n target: ProjectSelection,\n): Promise<\"yes\" | \"no\" | \"unknown\"> {\n if (target.kind === \"deploymentName\")\n return deploymentAccess(token, target.deploymentName);\n if (target.kind !== \"teamAndProjectSlugs\") return \"unknown\";\n try {\n const response = await profileApi(\n token,\n `/v1/teams/${encodeURIComponent(target.teamSlug)}/projects/${encodeURIComponent(target.projectSlug)}`,\n );\n if (response.ok) return \"yes\";\n return [401, 403, 404].includes(response.status) ? \"no\" : \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nfunction configuredCloudDeployment(): string | null {\n const configured = process.env[CONVEX_DEPLOYMENT_ENV_VAR_NAME]?.trim();\n if (\n !configured ||\n getDeploymentTypeFromConfiguredDeployment(configured) === \"local\"\n )\n return null;\n const name = stripDeploymentTypePrefix(configured);\n return isAnonymousDeployment(name) ? null : name;\n}\n\nexport async function bindProfileToDirectory(\n ctx: Context,\n name: string,\n force = false,\n target?: ProjectSelection,\n): Promise<boolean> {\n const credentials = await readProfileCredentials(ctx, {\n name,\n source: \"account selection\",\n });\n loadProjectEnvironmentVariables();\n const deployment = configuredCloudDeployment();\n const selectedTarget =\n target ??\n (deployment === null\n ? null\n : {\n kind: \"deploymentName\" as const,\n deploymentName: deployment,\n deploymentType: null,\n });\n if (!force && selectedTarget !== null) {\n const label =\n selectedTarget.kind === \"teamAndProjectSlugs\"\n ? `project \"${selectedTarget.teamSlug}/${selectedTarget.projectSlug}\"`\n : `deployment \"${selectedTarget.kind === \"deploymentName\" ? selectedTarget.deploymentName : \"configured\"}\"`;\n const access = await projectAccess(\n credentials!.accessToken,\n selectedTarget,\n );\n if (access !== \"yes\") {\n logWarning(\n access === \"no\"\n ? `Account \"${name}\" cannot access ${label}.`\n : `Could not verify whether account \"${name}\" can access ${label}.`,\n );\n if (\n !process.stdin.isTTY ||\n !(await promptYesNo(ctx, {\n message: `Use account \"${name}\" here anyway?`,\n default: false,\n }))\n ) {\n logMessage(\n `Directory selection unchanged. To select this account anyway, run \\`npx convex account select ${name} --force\\`.`,\n );\n return false;\n }\n }\n }\n await writeProfileDirectory(ctx, name);\n return true;\n}\n\nexport async function profileLoginMetadata(\n ctx: Context,\n profile: ProfileSelection,\n loginToken: string,\n previous: ProfileCredentials | null,\n): Promise<Omit<ProfileCredentials, \"accessToken\">> {\n let identity: { memberId: string; email: string } | null = null;\n try {\n const response = await profileApi(loginToken, \"/api/dashboard/profile\");\n if (response.ok) {\n const data = await response.json();\n if (\n (typeof data.id === \"number\" || typeof data.id === \"string\") &&\n typeof data.email === \"string\"\n ) {\n identity = { memberId: String(data.id), email: data.email };\n }\n }\n } catch {\n // Older authentication tokens can be valid without access to the dashboard profile API.\n }\n const sameAccount =\n previous !== null && (previous.memberId === undefined || identity === null)\n ? await tokensBelongToSameAccount(previous.accessToken, loginToken)\n : null;\n if (\n previous !== null &&\n (previous.memberId === undefined || identity === null\n ? sameAccount !== true\n : identity.memberId !== previous.memberId)\n ) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage:\n sameAccount === null &&\n (previous.memberId === undefined || identity === null)\n ? `Could not verify the identity of saved account \"${profile.name}\". To replace this saved login, run \\`npx convex logout --account ${profile.name}\\` followed by \\`npx convex login --account ${profile.name}\\`. Choose the intended account when logging in.`\n : `The login does not match saved account \"${profile.name}\". Log in with the matching account, or choose another name with \\`npx convex login --account <name>\\`.`,\n });\n }\n return {\n ...(identity ??\n (previous?.memberId === undefined\n ? {}\n : { memberId: previous.memberId, email: previous.email })),\n };\n}\n\nasync function tokensBelongToSameAccount(\n older: string,\n newer: string,\n): Promise<boolean | null> {\n try {\n const responses = await Promise.all(\n [older, newer].map((token) =>\n profileApi(token, \"/v1/list_personal_access_tokens?limit=100\"),\n ),\n );\n if (responses.some((response) => !response.ok)) return null;\n const lists = await Promise.all(\n responses.map((response) => response.json()),\n );\n if (\n lists.some(\n (list) => !Array.isArray(list.items) || list.items.length === 0,\n )\n )\n return null;\n const ids = new Set(\n lists[0].items.map((token: { id: unknown }) => String(token.id)),\n );\n if (\n lists[1].items.some((token: { id: unknown }) => ids.has(String(token.id)))\n )\n return true;\n // Disjoint partial pages cannot establish that the accounts differ.\n return lists.some((list) => list.pagination?.hasMore !== false)\n ? null\n : false;\n } catch {\n return null;\n }\n}\n\nexport async function revokeReplacedProfileToken(\n ctx: Context,\n previous: string | undefined,\n accessToken: string,\n) {\n if (previous === undefined || previous === accessToken) return;\n const settings = await readProfileSettings(ctx);\n if (\n settings.revokeReplacedTokens === false ||\n settings.accessToken === previous\n )\n return;\n for (const name of savedProfileNames(ctx)) {\n const token = readProfileToken(ctx, name);\n if (token === null) {\n logWarning(\n `The new login was saved, but account \"${name}\" could not be read. Skipping revocation of the replaced token.`,\n );\n return;\n }\n if (token === previous) return;\n }\n try {\n // The API verifies token ownership using the newly authenticated account.\n const response = await profileApi(\n accessToken,\n \"/v1/delete_personal_access_token\",\n { id: previous },\n );\n if (response.ok) return;\n } catch {\n // The new credentials are already saved, so a failed revocation can be retried in the dashboard.\n }\n logWarning(\n \"The new login was saved, but the replaced token could not be revoked. You can remove it in the dashboard's account settings.\",\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|