convex
Version:
Client for the Convex Cloud
276 lines (272 loc) • 10.9 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var login_exports = {};
__export(login_exports, {
login: () => login
});
module.exports = __toCommonJS(login_exports);
var import_extra_typings = require("@commander-js/extra-typings");
var import_context = require("../bundler/context.js");
var import_login = require("./lib/login.js");
var import_filePaths = require("./lib/localDeployment/filePaths.js");
var import_anonymous = require("./lib/localDeployment/anonymous.js");
var import_dashboard = require("./lib/dashboard.js");
var import_prompts = require("./lib/utils/prompts.js");
var import_utils = require("./lib/utils/utils.js");
var import_configure = require("./configure.js");
var import_deploymentSelection = require("./lib/deploymentSelection.js");
var import_deployment = require("./lib/deployment.js");
const login = new import_extra_typings.Command("login").description("Login to Convex").allowExcessArguments(false).option(
"--device-name <name>",
"Provide a name for the device being authorized"
).option(
"-f, --force",
"Proceed with login even if a valid access token already exists for this device"
).option(
"--no-open",
"Don't automatically open the login link in the default browser"
).addOption(
new import_extra_typings.Option(
"--login-flow <mode>",
`How to log in; defaults to guessing based on the environment.`
).choices(["paste", "auto", "poll"]).default("auto")
).addOption(new import_extra_typings.Option("--link-deployments").hideHelp()).addOption(new import_extra_typings.Option("--override-auth-url <url>").hideHelp()).addOption(new import_extra_typings.Option("--override-auth-client <id>").hideHelp()).addOption(new import_extra_typings.Option("--override-auth-username <username>").hideHelp()).addOption(new import_extra_typings.Option("--override-auth-password <password>").hideHelp()).addOption(new import_extra_typings.Option("--override-access-token <token>").hideHelp()).addOption(new import_extra_typings.Option("--accept-opt-ins").hideHelp()).addOption(new import_extra_typings.Option("--dump-access-token").hideHelp()).addOption(new import_extra_typings.Option("--check-login").hideHelp()).action(async (options, cmd) => {
const ctx = await (0, import_context.oneoffContext)({
url: void 0,
adminKey: void 0,
envFile: void 0
});
if (!options.force && await (0, import_login.checkAuthorization)(ctx, !!options.acceptOptIns)) {
(0, import_context.logFinishedStep)(
ctx,
"This device has previously been authorized and is ready for use with Convex."
);
await handleLinkingDeployments(ctx, {
interactive: !!options.linkDeployments
});
return;
}
if (!options.force && options.checkLogin) {
const isLoggedIn = await (0, import_login.checkAuthorization)(ctx, !!options.acceptOptIns);
if (!isLoggedIn) {
return ctx.crash({
exitCode: 1,
errorType: "fatal",
errForSentry: "You are not logged in.",
printedMessage: "You are not logged in."
});
}
}
if (!!options.overrideAuthUsername !== !!options.overrideAuthPassword) {
cmd.error(
"If overriding credentials, both username and password must be provided"
);
}
const uuid = (0, import_filePaths.loadUuidForAnonymousUser)(ctx);
await (0, import_login.performLogin)(ctx, {
...options,
anonymousId: uuid
});
await handleLinkingDeployments(ctx, {
interactive: !!options.linkDeployments
});
});
async function handleLinkingDeployments(ctx, args) {
if (!(0, import_deploymentSelection.shouldAllowAnonymousDevelopment)()) {
return;
}
const anonymousDeployments = await (0, import_anonymous.listExistingAnonymousDeployments)(ctx);
if (anonymousDeployments.length === 0) {
if (args.interactive) {
(0, import_context.logMessage)(
ctx,
"It doesn't look like you have any deployments to link. You can run `npx convex dev` to set up a new project or select an existing one."
);
}
return;
}
if (!args.interactive) {
const message = getMessage(
anonymousDeployments.map((d) => d.deploymentName)
);
const createProjects = await (0, import_prompts.promptYesNo)(ctx, {
message,
default: true
});
if (!createProjects) {
(0, import_context.logMessage)(
ctx,
"Not linking your existing deployments. If you want to link them later, run `npx convex login --link-deployments`."
);
(0, import_context.logMessage)(
ctx,
`Visit ${import_dashboard.DASHBOARD_HOST} or run \`npx convex dev\` to get started with your new account.`
);
return;
}
const { teamSlug } = await (0, import_utils.validateOrSelectTeam)(
ctx,
void 0,
"Choose a team for your deployments:"
);
const projectsRemaining = await getProjectsRemaining(ctx, teamSlug);
if (anonymousDeployments.length > projectsRemaining) {
(0, import_context.logFailure)(
ctx,
`You have ${anonymousDeployments.length} deployments to link, but only have ${projectsRemaining} projects remaining. If you'd like to choose which ones to link, run this command with the --link-deployments flag.`
);
return;
}
const deploymentSelection2 = await (0, import_deploymentSelection.getDeploymentSelection)(ctx, {
url: void 0,
adminKey: void 0,
envFile: void 0
});
const configuredDeployment2 = deploymentSelection2.kind === "anonymous" ? deploymentSelection2.deploymentName : null;
let dashboardUrl = (0, import_dashboard.teamDashboardUrl)(teamSlug);
for (const deployment of anonymousDeployments) {
const linkedDeployment = await (0, import_anonymous.handleLinkToProject)(ctx, {
deploymentName: deployment.deploymentName,
teamSlug,
projectSlug: null
});
(0, import_context.logFinishedStep)(
ctx,
`Added ${deployment.deploymentName} to project ${linkedDeployment.projectSlug}`
);
if (deployment.deploymentName === configuredDeployment2) {
await (0, import_configure.updateEnvAndConfigForDeploymentSelection)(
ctx,
{
url: linkedDeployment.deploymentUrl,
deploymentName: linkedDeployment.deploymentName,
teamSlug,
projectSlug: linkedDeployment.projectSlug,
deploymentType: "local"
},
configuredDeployment2
);
dashboardUrl = (0, import_dashboard.deploymentDashboardUrlPage)(
linkedDeployment.deploymentName,
""
);
}
}
(0, import_context.logFinishedStep)(
ctx,
`Sucessfully linked your deployments! Visit ${dashboardUrl} to get started.`
);
return;
}
const deploymentSelection = await (0, import_deploymentSelection.getDeploymentSelection)(ctx, {
url: void 0,
adminKey: void 0,
envFile: void 0
});
const configuredDeployment = deploymentSelection.kind === "anonymous" ? deploymentSelection.deploymentName : null;
while (true) {
(0, import_context.logMessage)(
ctx,
getDeploymentListMessage(
anonymousDeployments.map((d) => d.deploymentName)
)
);
const updatedAnonymousDeployments = await (0, import_anonymous.listExistingAnonymousDeployments)(ctx);
const deploymentToLink = await (0, import_prompts.promptSearch)(ctx, {
message: "Which deployment would you like to link to your account?",
choices: updatedAnonymousDeployments.map((d) => ({
name: d.deploymentName,
value: d.deploymentName
}))
});
const { teamSlug } = await (0, import_utils.validateOrSelectTeam)(
ctx,
void 0,
"Choose a team for your deployment:"
);
const { projectSlug } = await (0, import_configure.selectProject)(ctx, "ask", {
team: teamSlug,
devDeployment: "local",
defaultProjectName: (0, import_deployment.removeAnonymousPrefix)(deploymentToLink)
});
const linkedDeployment = await (0, import_anonymous.handleLinkToProject)(ctx, {
deploymentName: deploymentToLink,
teamSlug,
projectSlug
});
(0, import_context.logFinishedStep)(
ctx,
`Added ${deploymentToLink} to project ${linkedDeployment.projectSlug}`
);
if (deploymentToLink === configuredDeployment) {
await (0, import_configure.updateEnvAndConfigForDeploymentSelection)(
ctx,
{
url: linkedDeployment.deploymentUrl,
deploymentName: linkedDeployment.deploymentName,
teamSlug,
projectSlug: linkedDeployment.projectSlug,
deploymentType: "local"
},
configuredDeployment
);
}
const shouldContinue = await (0, import_prompts.promptYesNo)(ctx, {
message: "Would you like to link another deployment?",
default: true
});
if (!shouldContinue) {
break;
}
}
}
async function getProjectsRemaining(ctx, teamSlug) {
const response = await (0, import_utils.bigBrainAPI)({
ctx,
method: "GET",
url: `/api/teams/${teamSlug}/projects_remaining`
});
return response.projectsRemaining;
}
function getDeploymentListMessage(anonymousDeploymentNames) {
let message = `You have ${anonymousDeploymentNames.length} existing deployments.`;
message += `
Deployments:`;
for (const deploymentName of anonymousDeploymentNames) {
message += `
- ${deploymentName}`;
}
return message;
}
function getMessage(anonymousDeploymentNames) {
if (anonymousDeploymentNames.length === 1) {
return `Would you like to link your existing deployment to your account? ("${anonymousDeploymentNames[0]}")`;
}
let message = `You have ${anonymousDeploymentNames.length} existing deployments. Would you like to link them to your account?`;
message += `
Deployments:`;
for (const deploymentName of anonymousDeploymentNames) {
message += `
- ${deploymentName}`;
}
message += `
You can alternatively run \`npx convex login --link-deployments\` to interactively choose which deployments to add.`;
return message;
}
//# sourceMappingURL=login.js.map