UNPKG

convex

Version:

Client for the Convex Cloud

298 lines (297 loc) 8.85 kB
"use strict"; import chalk from "chalk"; import inquirer from "inquirer"; import { logError, logFailure, logMessage } from "../bundler/context.js"; import { fetchDeploymentCredentialsForName, fetchDeploymentCredentialsProvisioningDevOrProdMaybeThrows } from "./lib/api.js"; import { enforceDeprecatedConfigField, readProjectConfig, upgradeOldAuthInfoToAuthConfig, writeProjectConfig } from "./lib/config.js"; import { eraseDeploymentEnvVar, writeDeploymentEnvVar } from "./lib/deployment.js"; import { init } from "./lib/init.js"; import { reinit } from "./lib/reinit.js"; import { functionsDir, getConfiguredDeploymentName, hasProject, hasProjects, hasTeam, logAndHandleFetchError, ThrowingFetchError } from "./lib/utils.js"; import { writeConvexUrlToEnvFile } from "./lib/envvars.js"; export async function initOrReinitForDeprecatedCommands(ctx, cmdOptions) { const { url } = await deploymentCredentialsOrConfigure(ctx, null, { ...cmdOptions, prod: false }); const envVarWrite = await writeConvexUrlToEnvFile(ctx, url); if (envVarWrite !== null) { logMessage( ctx, chalk.green( `Saved the dev deployment URL as ${envVarWrite.envVar} to ${envVarWrite.envFile}` ) ); } } export async function deploymentCredentialsOrConfigure(ctx, chosenConfiguration, cmdOptions) { const { url, adminKey } = cmdOptions; if (url !== void 0 && adminKey !== void 0) { const didErase = await eraseDeploymentEnvVar(ctx); if (didErase) { logMessage( ctx, chalk.yellowBright( `Removed the CONVEX_DEPLOYMENT environment variable from .env.local` ) ); } const envVarWrite = await writeConvexUrlToEnvFile(ctx, url); if (envVarWrite !== null) { logMessage( ctx, chalk.green( `Saved the given --url as ${envVarWrite.envVar} to ${envVarWrite.envFile}` ) ); } return { url, adminKey }; } const deploymentType = cmdOptions.prod ? "prod" : "dev"; const configuredDeployment = chosenConfiguration === null ? await getConfiguredDeploymentOrUpgrade(ctx, deploymentType) : null; if (configuredDeployment === null) { const choice2 = chosenConfiguration !== "ask" && chosenConfiguration !== null ? chosenConfiguration : await askToConfigure(ctx); return await initOrReinit(ctx, choice2, deploymentType, cmdOptions); } if ("error" in configuredDeployment) { const projectConfig = (await readProjectConfig(ctx)).projectConfig; const choice2 = await askToReconfigure( ctx, projectConfig, configuredDeployment.error ); return initOrReinit(ctx, choice2, deploymentType, cmdOptions); } const { deploymentName } = configuredDeployment; const adminKeyAndUrlForConfiguredDeployment = await fetchDeploymentCredentialsForName( ctx, deploymentName, deploymentType ); if (!("error" in adminKeyAndUrlForConfiguredDeployment)) { return adminKeyAndUrlForConfiguredDeployment; } await checkForDeploymentTypeError( ctx, adminKeyAndUrlForConfiguredDeployment.error, deploymentType ); const choice = await askToReconfigureNew(ctx, deploymentName); return initOrReinit(ctx, choice, deploymentType, cmdOptions); } async function checkForDeploymentTypeError(ctx, error, deploymentType) { let data = null; if (error instanceof ThrowingFetchError) { data = error.serverErrorData || null; } if (data && "code" in data && data.code === "DeploymentTypeMismatch") { if (deploymentType === "prod") { logFailure( ctx, "Use `npx convex deploy` to push changes to your production deployment" ); } else { logFailure( ctx, "CONVEX_DEPLOYMENT is a production deployment, but --prod flag was not specified. Use `npx convex dev --prod` to develop against this production deployment." ); } logError(ctx, chalk.red(data.message)); await ctx.crash(1, "invalid filesystem data", error); } } async function getConfiguredDeploymentOrUpgrade(ctx, deploymentType) { const deploymentName = await getConfiguredDeploymentName(ctx); if (deploymentName !== null) { return { deploymentName }; } return await upgradeOldConfigToDeploymentVar(ctx, deploymentType); } async function initOrReinit(ctx, choice, deploymentType, cmdOptions) { switch (choice) { case "new": return await init(ctx, deploymentType, cmdOptions); case "existing": { return await reinit(ctx, deploymentType, cmdOptions); } default: { return choice; } } } async function upgradeOldConfigToDeploymentVar(ctx, deploymentType) { const { configPath, projectConfig } = await readProjectConfig(ctx); const { team, project } = projectConfig; if (typeof team !== "string" || typeof project !== "string") { return null; } let devDeploymentName; try { const { deploymentName } = await fetchDeploymentCredentialsProvisioningDevOrProdMaybeThrows( ctx, { teamSlug: team, projectSlug: project }, deploymentType ); devDeploymentName = deploymentName; } catch (error) { return { error }; } await writeDeploymentEnvVar(ctx, deploymentType, { team, project, deploymentName: devDeploymentName }); logMessage( ctx, chalk.green( `Saved the ${deploymentType} deployment name as CONVEX_DEPLOYMENT to .env.local` ) ); const projectConfigWithoutAuthInfo = await upgradeOldAuthInfoToAuthConfig( ctx, projectConfig, functionsDir(configPath, projectConfig) ); await writeProjectConfig(ctx, projectConfigWithoutAuthInfo, { deleteIfAllDefault: true }); return { deploymentName: devDeploymentName }; } async function askToConfigure(ctx) { if (!await hasProjects(ctx)) { return "new"; } return await promptToInitWithProjects(); } async function askToReconfigure(ctx, projectConfig, error) { const team = await enforceDeprecatedConfigField(ctx, projectConfig, "team"); const project = await enforceDeprecatedConfigField( ctx, projectConfig, "project" ); const [isExistingTeam, existingProject, hasAnyProjects] = await Promise.all([ await hasTeam(ctx, team), await hasProject(ctx, team, project), await hasProjects(ctx) ]); if (isExistingTeam && existingProject) { return await logAndHandleFetchError(ctx, error); } if (isExistingTeam) { logFailure( ctx, `Project ${chalk.bold(project)} does not exist in your team ${chalk.bold( team )}, as configured in ${chalk.bold("convex.json")}` ); } else { logFailure( ctx, `You don't have access to team ${chalk.bold( team )}, as configured in ${chalk.bold("convex.json")}` ); } if (!hasAnyProjects) { const { confirmed } = await inquirer.prompt([ { type: "confirm", name: "confirmed", message: `Create a new project?`, default: true } ]); if (!confirmed) { logFailure( ctx, "Run `npx convex dev` in a directory with a valid convex.json." ); return await ctx.crash(1, "invalid filesystem data"); } return "new"; } return await promptToReconfigure(); } async function askToReconfigureNew(ctx, configuredDeploymentName) { logFailure( ctx, `You don't have access to the project with deployment ${chalk.bold( configuredDeploymentName )}, as configured in ${chalk.bold("CONVEX_DEPLOYMENT")}` ); const hasAnyProjects = await hasProjects(ctx); if (!hasAnyProjects) { const { confirmed } = await inquirer.prompt([ { type: "confirm", name: "confirmed", message: `Configure a new project?`, default: true } ]); if (!confirmed) { logFailure( ctx, "Run `npx convex dev` in a directory with a valid CONVEX_DEPLOYMENT set" ); return await ctx.crash(1, "invalid filesystem data"); } return "new"; } return await promptToReconfigure(); } export async function promptToInitWithProjects() { const { choice } = await inquirer.prompt([ { type: "list", name: "choice", message: `What would you like to configure?`, default: "new", choices: [ { name: "a new project", value: "new" }, { name: "an existing project", value: "existing" } ] } ]); return choice; } export async function promptToReconfigure() { const { choice } = await inquirer.prompt([ { type: "list", name: "choice", message: `Configure a different project?`, default: "new", choices: [ { name: "create new project", value: "new" }, { name: "choose an existing project", value: "existing" } ] } ]); return choice; } //# sourceMappingURL=configure.js.map