convex
Version:
Client for the Convex Cloud
330 lines (329 loc) • 12.7 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var configure_exports = {};
__export(configure_exports, {
deploymentCredentialsOrConfigure: () => deploymentCredentialsOrConfigure
});
module.exports = __toCommonJS(configure_exports);
var import_chalk = __toESM(require("chalk"), 1);
var import_context = require("../bundler/context.js");
var import_api = require("./lib/api.js");
var import_config = require("./lib/config.js");
var import_deployment = require("./lib/deployment.js");
var import_init = require("./lib/init.js");
var import_utils = require("./lib/utils/utils.js");
var import_envvars = require("./lib/envvars.js");
var import_path = __toESM(require("path"), 1);
var import_dashboard = require("./dashboard.js");
var import_codegen = require("./lib/codegen.js");
var import_localDeployment = require("./lib/localDeployment/localDeployment.js");
var import_prompts = require("./lib/utils/prompts.js");
async function deploymentCredentialsOrConfigure(ctx, chosenConfiguration, cmdOptions) {
if (cmdOptions.url !== void 0 && cmdOptions.adminKey !== void 0) {
const credentials = await handleManuallySetUrlAndAdminKey(ctx, {
url: cmdOptions.url,
adminKey: cmdOptions.adminKey
});
return { ...credentials, cleanupHandle: null };
}
const { projectSlug, teamSlug } = await selectProject(
ctx,
chosenConfiguration,
{ team: cmdOptions.team, project: cmdOptions.project }
);
const deploymentOptions = cmdOptions.prod ? { kind: "prod" } : cmdOptions.local ? { kind: "local", ...cmdOptions.localOptions } : { kind: "dev" };
const {
deploymentName,
deploymentUrl: url,
adminKey,
cleanupHandle
} = await ensureDeploymentProvisioned(ctx, {
teamSlug,
projectSlug,
deploymentOptions
});
await updateEnvAndConfigForDeploymentSelection(ctx, {
url,
deploymentName,
teamSlug,
projectSlug,
deploymentType: deploymentOptions.kind
});
return { deploymentName, url, adminKey, cleanupHandle };
}
async function handleManuallySetUrlAndAdminKey(ctx, cmdOptions) {
const { url, adminKey } = cmdOptions;
const didErase = await (0, import_deployment.eraseDeploymentEnvVar)(ctx);
if (didErase) {
(0, import_context.logMessage)(
ctx,
import_chalk.default.yellowBright(
`Removed the CONVEX_DEPLOYMENT environment variable from .env.local`
)
);
}
const envVarWrite = await (0, import_envvars.writeConvexUrlToEnvFile)(ctx, url);
if (envVarWrite !== null) {
(0, import_context.logMessage)(
ctx,
import_chalk.default.green(
`Saved the given --url as ${envVarWrite.envVar} to ${envVarWrite.envFile}`
)
);
}
return { url, adminKey };
}
async function selectProject(ctx, chosenConfiguration, cmdOptions) {
let result = null;
if (chosenConfiguration === null) {
result = await getConfiguredProjectSlugs(ctx);
if (result !== null && result !== "AccessDenied") {
return result;
}
}
const reconfigure = result === "AccessDenied";
const choice = chosenConfiguration !== "ask" && chosenConfiguration !== null ? chosenConfiguration : await askToConfigure(ctx, reconfigure);
switch (choice) {
case "new":
return selectNewProject(ctx, cmdOptions);
case "existing":
return selectExistingProject(ctx, cmdOptions);
default:
return await ctx.crash({
exitCode: 1,
errorType: "fatal",
printedMessage: "No project selected."
});
}
}
async function getConfiguredProjectSlugs(ctx) {
const deploymentName = await (0, import_utils.getConfiguredDeploymentName)(ctx);
if (deploymentName !== null) {
const result = await getTeamAndProjectSlugForDeployment(ctx, {
deploymentName,
kind: "cloud"
});
if (result !== null) {
return result;
} else {
(0, import_context.logFailure)(
ctx,
`You don't have access to the project with deployment ${import_chalk.default.bold(
deploymentName
)}, as configured in ${import_chalk.default.bold(import_deployment.CONVEX_DEPLOYMENT_VAR_NAME)}`
);
return "AccessDenied";
}
}
const { projectConfig } = await (0, import_config.readProjectConfig)(ctx);
const { team, project } = projectConfig;
if (typeof team === "string" && typeof project === "string") {
const hasAccess = await hasAccessToProject(ctx, {
teamSlug: team,
projectSlug: project
});
if (!hasAccess) {
(0, import_context.logFailure)(
ctx,
`You don't have access to the project ${import_chalk.default.bold(project)} in team ${import_chalk.default.bold(team)} as configured in ${import_chalk.default.bold("convex.json")}`
);
return "AccessDenied";
}
return { teamSlug: team, projectSlug: project };
}
return null;
}
async function getTeamAndProjectSlugForDeployment(ctx, selector) {
try {
const body = await (0, import_utils.bigBrainAPIMaybeThrows)({
ctx,
url: `/api/deployment/${selector.deploymentName}/team_and_project`,
method: "GET"
});
return { teamSlug: body.team, projectSlug: body.project };
} catch (err) {
if (err instanceof import_utils.ThrowingFetchError && (err.serverErrorData?.code === "DeploymentNotFound" || err.serverErrorData?.code === "ProjectNotFound")) {
return null;
}
return (0, import_utils.logAndHandleFetchError)(ctx, err);
}
}
async function hasAccessToProject(ctx, selector) {
try {
await (0, import_utils.bigBrainAPIMaybeThrows)({
ctx,
url: `/api/teams/${selector.teamSlug}/projects/${selector.projectSlug}/deployments`,
method: "GET"
});
return true;
} catch (err) {
if (err instanceof import_utils.ThrowingFetchError && (err.serverErrorData?.code === "TeamNotFound" || err.serverErrorData?.code === "ProjectNotFound")) {
return false;
}
return (0, import_utils.logAndHandleFetchError)(ctx, err);
}
}
const cwd = import_path.default.basename(process.cwd());
async function selectNewProject(ctx, config) {
const { teamSlug: selectedTeam, chosen: didChooseBetweenTeams } = await (0, import_utils.validateOrSelectTeam)(ctx, config.team, "Team:");
let projectName = config.project || cwd;
if (!config.project) {
projectName = await (0, import_prompts.promptString)(ctx, {
message: "Project name:",
default: cwd
});
}
(0, import_context.showSpinner)(ctx, "Creating new Convex project...");
let projectSlug, teamSlug, projectsRemaining;
try {
({ projectSlug, teamSlug, projectsRemaining } = await (0, import_api.createProject)(ctx, {
teamSlug: selectedTeam,
projectName
}));
} catch (err) {
(0, import_context.logFailure)(ctx, "Unable to create project.");
return await (0, import_utils.logAndHandleFetchError)(ctx, err);
}
const teamMessage = didChooseBetweenTeams ? " in team " + import_chalk.default.bold(teamSlug) : "";
(0, import_context.logFinishedStep)(
ctx,
`Created project ${import_chalk.default.bold(
projectSlug
)}${teamMessage}, manage it at ${import_chalk.default.bold(
(0, import_dashboard.projectDashboardUrl)(teamSlug, projectSlug)
)}`
);
if (projectsRemaining <= 2) {
(0, import_context.logWarning)(
ctx,
import_chalk.default.yellow.bold(
`Your account now has ${projectsRemaining} project${projectsRemaining === 1 ? "" : "s"} remaining.`
)
);
}
const { projectConfig: existingProjectConfig } = await (0, import_config.readProjectConfig)(ctx);
const configPath = await (0, import_config.configFilepath)(ctx);
const functionsPath = (0, import_utils.functionsDir)(configPath, existingProjectConfig);
await (0, import_codegen.doInitCodegen)(ctx, functionsPath, true);
await (0, import_codegen.doCodegen)(ctx, functionsPath, "disable");
return { teamSlug, projectSlug };
}
async function selectExistingProject(ctx, config) {
const { teamSlug } = await (0, import_utils.validateOrSelectTeam)(ctx, config.team, "Team:");
const projectSlug = await (0, import_utils.validateOrSelectProject)(
ctx,
config.project,
teamSlug,
"Configure project",
"Project:"
);
if (projectSlug === null) {
return await ctx.crash({
exitCode: 1,
errorType: "fatal",
printedMessage: "Run the command again to create a new project instead."
});
}
(0, import_context.showSpinner)(ctx, `Reinitializing project ${projectSlug}...
`);
const { projectConfig: existingProjectConfig } = await (0, import_config.readProjectConfig)(ctx);
const functionsPath = (0, import_utils.functionsDir)((0, import_config.configName)(), existingProjectConfig);
await (0, import_codegen.doCodegen)(ctx, functionsPath, "disable");
return { teamSlug, projectSlug };
}
async function askToConfigure(ctx, reconfigure) {
if (!await (0, import_utils.hasProjects)(ctx)) {
return "new";
}
return await (0, import_prompts.promptOptions)(ctx, {
message: reconfigure ? "Configure a different project?" : "What would you like to configure?",
default: "new",
choices: [
{ name: "create a new project", value: "new" },
{ name: "choose an existing project", value: "existing" }
]
});
}
async function ensureDeploymentProvisioned(ctx, options) {
switch (options.deploymentOptions.kind) {
case "dev":
case "prod": {
const credentials = await (0, import_api.fetchDeploymentCredentialsProvisioningDevOrProdMaybeThrows)(
ctx,
{ teamSlug: options.teamSlug, projectSlug: options.projectSlug },
options.deploymentOptions.kind
);
return {
...credentials,
cleanupHandle: null,
onActivity: null
};
}
case "local": {
const credentials = await (0, import_localDeployment.handleLocalDeployment)(ctx, {
teamSlug: options.teamSlug,
projectSlug: options.projectSlug,
...options.deploymentOptions
});
return credentials;
}
default:
return await ctx.crash({
exitCode: 1,
errorType: "fatal",
printedMessage: `Invalid deployment type: ${options.deploymentOptions.kind}`,
errForSentry: `Invalid deployment type: ${options.deploymentOptions.kind}`
});
}
}
async function updateEnvAndConfigForDeploymentSelection(ctx, options) {
const { configPath, projectConfig: existingProjectConfig } = await (0, import_config.readProjectConfig)(ctx);
const functionsPath = (0, import_utils.functionsDir)((0, import_config.configName)(), existingProjectConfig);
const { wroteToGitIgnore, changedDeploymentEnvVar } = await (0, import_deployment.writeDeploymentEnvVar)(ctx, options.deploymentType, {
team: options.teamSlug,
project: options.projectSlug,
deploymentName: options.deploymentName
});
const projectConfig = await (0, import_config.upgradeOldAuthInfoToAuthConfig)(
ctx,
existingProjectConfig,
functionsPath
);
await (0, import_config.writeProjectConfig)(ctx, projectConfig, {
deleteIfAllDefault: true
});
await (0, import_init.finalizeConfiguration)(ctx, {
deploymentType: options.deploymentType,
url: options.url,
wroteToGitIgnore,
changedDeploymentEnvVar,
functionsPath: (0, import_utils.functionsDir)(configPath, projectConfig)
});
}
//# sourceMappingURL=configure.js.map