UNPKG

convex

Version:

Client for the Convex Cloud

411 lines (410 loc) 14.2 kB
"use strict"; 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 anonymous_exports = {}; __export(anonymous_exports, { handleAnonymousDeployment: () => handleAnonymousDeployment, handleLinkToProject: () => handleLinkToProject, listExistingAnonymousDeployments: () => listExistingAnonymousDeployments, loadAnonymousDeployment: () => loadAnonymousDeployment, moveDeployment: () => moveDeployment }); module.exports = __toCommonJS(anonymous_exports); var import_path = __toESM(require("path"), 1); var import_context = require("../../../bundler/context.js"); var import_prompts = require("../utils/prompts.js"); var import_bigBrain = require("./bigBrain.js"); var import_errors = require("./errors.js"); var import_filePaths = require("./filePaths.js"); var import_filePaths2 = require("./filePaths.js"); var import_run = require("./run.js"); var import_run2 = require("./run.js"); var import_upgrade = require("./upgrade.js"); var import_utils = require("./utils.js"); var import_dashboard = require("./dashboard.js"); var import_crypto = __toESM(require("crypto"), 1); var import_fsUtils = require("../fsUtils.js"); var import_download = require("./download.js"); var import_deployment = require("../deployment.js"); var import_api = require("../api.js"); var import_deployment2 = require("../deployment.js"); var import_fs = require("../../../bundler/fs.js"); async function handleAnonymousDeployment(ctx, options) { if (await (0, import_utils.isOffline)()) { return await ctx.crash({ exitCode: 1, errorType: "fatal", printedMessage: "Cannot run a local deployment while offline" }); } const deployment = await chooseDeployment(ctx, { deploymentName: options.deploymentName, chosenConfiguration: options.chosenConfiguration }); if (deployment.kind === "first") { (0, import_context.logMessage)( ctx, "This command, `npx convex dev`, will run your Convex backend locally and update it with the function you write in the `convex/` directory." ); (0, import_context.logMessage)( ctx, "Use `npx convex dashboard` to view and interact with your project from a web UI." ); (0, import_context.logMessage)( ctx, "Use `npx convex docs` to read the docs and `npx convex help` to see other commands." ); (0, import_filePaths.ensureUuidForAnonymousUser)(ctx); if (process.stdin.isTTY) { const result = await (0, import_prompts.promptYesNo)(ctx, { message: "Continue?", default: true }); if (!result) { return ctx.crash({ exitCode: 1, errorType: "fatal", printedMessage: "Exiting" }); } } } ctx.registerCleanup(async (_exitCode, err) => { if (err instanceof import_errors.LocalDeploymentError) { (0, import_errors.printLocalDeploymentOnError)(ctx); } }); const { binaryPath, version } = await (0, import_download.ensureBackendBinaryDownloaded)( ctx, options.backendVersion === void 0 ? { kind: "latest" } : { kind: "version", version: options.backendVersion } ); await (0, import_dashboard.handleDashboard)(ctx, version); let adminKey; let instanceSecret; if (deployment.kind === "existing") { adminKey = deployment.config.adminKey; instanceSecret = deployment.config.instanceSecret ?? import_utils.LOCAL_BACKEND_INSTANCE_SECRET; await (0, import_run.ensureBackendStopped)(ctx, { ports: { cloud: deployment.config.ports.cloud }, maxTimeSecs: 5, deploymentName: deployment.deploymentName, allowOtherDeployments: true }); } else { instanceSecret = (0, import_utils.generateInstanceSecret)(); const data = await (0, import_bigBrain.bigBrainGenerateAdminKeyForAnonymousDeployment)(ctx, { instanceName: deployment.deploymentName, instanceSecret }); adminKey = data.adminKey; } const [cloudPort, sitePort] = await (0, import_utils.choosePorts)(ctx, { count: 2, startPort: 3210, requestedPorts: [options.ports?.cloud ?? null, options.ports?.site ?? null] }); const onActivity = async (isOffline2, _wasOffline) => { await (0, import_run2.ensureBackendRunning)(ctx, { cloudPort, deploymentName: deployment.deploymentName, maxTimeSecs: 5 }); if (isOffline2) { return; } }; const { cleanupHandle } = await (0, import_upgrade.handlePotentialUpgrade)(ctx, { deploymentName: deployment.deploymentName, deploymentKind: "anonymous", oldVersion: deployment.kind === "existing" ? deployment.config.backendVersion : null, newBinaryPath: binaryPath, newVersion: version, ports: { cloud: cloudPort, site: sitePort }, adminKey, instanceSecret, forceUpgrade: options.forceUpgrade }); const cleanupFunc = ctx.removeCleanup(cleanupHandle); ctx.registerCleanup(async (exitCode, err) => { if (cleanupFunc !== null) { await cleanupFunc(exitCode, err); } }); return { adminKey, deploymentName: deployment.deploymentName, deploymentUrl: (0, import_run.localDeploymentUrl)(cloudPort), onActivity }; } async function loadAnonymousDeployment(ctx, deploymentName) { const config = (0, import_filePaths.loadDeploymentConfig)(ctx, "anonymous", deploymentName); if (config === null) { return ctx.crash({ exitCode: 1, errorType: "fatal", printedMessage: `Could not find deployment with name ${deploymentName}!` }); } return config; } async function listExistingAnonymousDeployments(ctx) { const dir = (0, import_filePaths2.rootDeploymentStateDir)("anonymous"); if (!ctx.fs.exists(dir)) { return []; } const deploymentNames = ctx.fs.listDir(dir).map((d) => d.name).filter((d) => (0, import_deployment.isAnonymousDeployment)(d)); return deploymentNames.flatMap((deploymentName) => { const config = (0, import_filePaths.loadDeploymentConfig)(ctx, "anonymous", deploymentName); if (config !== null) { return [{ deploymentName, config }]; } return []; }); } async function chooseDeployment(ctx, options) { const deployments = await listExistingAnonymousDeployments(ctx); if (options.deploymentName !== null && options.chosenConfiguration === null) { const existing = deployments.find( (d) => d.deploymentName === options.deploymentName ); if (existing === void 0) { (0, import_context.logWarning)( ctx, `Could not find project with name ${options.deploymentName}!` ); } else { return { kind: "existing", deploymentName: existing.deploymentName, config: existing.config }; } } if (deployments.length === 0) { (0, import_context.logMessage)(ctx, "Let's set up your first project."); return await promptForNewDeployment(ctx, []); } if (options.chosenConfiguration === "new") { const deploymentName = await (0, import_prompts.promptString)(ctx, { message: "Choose a name for your new project:", default: import_path.default.basename(process.cwd()) }); const uniqueName = await getUniqueName( ctx, deploymentName, deployments.map((d) => d.deploymentName) ); (0, import_context.logVerbose)(ctx, `Deployment name: ${uniqueName}`); return { kind: "new", deploymentName: uniqueName }; } const newOrExisting = await (0, import_prompts.promptSearch)(ctx, { message: "Which project would you like to use?", choices: [ ...options.chosenConfiguration === "existing" ? [] : [ { name: "Create a new one", value: "new" } ], ...deployments.map((d) => ({ name: d.deploymentName, value: d.deploymentName })) ] }); if (newOrExisting !== "new") { const existingDeployment = deployments.find( (d) => d.deploymentName === newOrExisting ); if (existingDeployment === void 0) { return ctx.crash({ exitCode: 1, errorType: "fatal", printedMessage: `Could not find project with name ${newOrExisting}!` }); } return { kind: "existing", deploymentName: existingDeployment.deploymentName, config: existingDeployment.config }; } return await promptForNewDeployment( ctx, deployments.map((d) => d.deploymentName) ); } async function promptForNewDeployment(ctx, existingNames) { const isFirstDeployment = existingNames.length === 0; const deploymentName = await (0, import_prompts.promptString)(ctx, { message: "Choose a name:", default: import_path.default.basename(process.cwd()) }); const uniqueName = await getUniqueName( ctx, `anonymous-${deploymentName}`, existingNames ); (0, import_context.logVerbose)(ctx, `Deployment name: ${uniqueName}`); return isFirstDeployment ? { kind: "first", deploymentName: uniqueName } : { kind: "new", deploymentName: uniqueName }; } async function getUniqueName(ctx, name, existingNames) { if (!existingNames.includes(name)) { return name; } for (let i = 1; i <= 5; i++) { const uniqueName2 = `${name}-${i}`; if (!existingNames.includes(uniqueName2)) { return uniqueName2; } } const randomSuffix = import_crypto.default.randomBytes(4).toString("hex"); const uniqueName = `${name}-${randomSuffix}`; if (!existingNames.includes(uniqueName)) { return uniqueName; } return ctx.crash({ exitCode: 1, errorType: "fatal", printedMessage: `Could not generate a unique name for your project, please choose a different name` }); } async function handleLinkToProject(ctx, args) { (0, import_context.logVerbose)( ctx, `Linking ${args.deploymentName} to a project in team ${args.teamSlug}` ); const config = await (0, import_filePaths.loadDeploymentConfig)( ctx, "anonymous", args.deploymentName ); if (config === null) { return ctx.crash({ exitCode: 1, errorType: "fatal", printedMessage: "Failed to load deployment config" }); } await (0, import_run.ensureBackendStopped)(ctx, { ports: { cloud: config.ports.cloud }, deploymentName: args.deploymentName, allowOtherDeployments: true, maxTimeSecs: 5 }); const projectName = (0, import_deployment2.removeAnonymousPrefix)(args.deploymentName); let projectSlug; if (args.projectSlug !== null) { projectSlug = args.projectSlug; } else { const { projectSlug: newProjectSlug } = await (0, import_api.createProject)(ctx, { teamSlug: args.teamSlug, projectName, deploymentTypeToProvision: "prod" }); projectSlug = newProjectSlug; } (0, import_context.logVerbose)(ctx, `Creating local deployment in project ${projectSlug}`); const { deploymentName: localDeploymentName, adminKey } = await (0, import_bigBrain.bigBrainStart)( ctx, { port: config.ports.cloud, projectSlug, teamSlug: args.teamSlug, instanceName: null } ); const localConfig = (0, import_filePaths.loadDeploymentConfig)(ctx, "local", localDeploymentName); if (localConfig !== null) { return ctx.crash({ exitCode: 1, errorType: "fatal", printedMessage: `Project ${projectSlug} already has a local deployment, so we cannot link this anonymous local deployment to it.` }); } (0, import_context.logVerbose)(ctx, `Moving ${args.deploymentName} to ${localDeploymentName}`); await moveDeployment( ctx, { deploymentKind: "anonymous", deploymentName: args.deploymentName }, { deploymentKind: "local", deploymentName: localDeploymentName } ); (0, import_context.logVerbose)(ctx, `Saving deployment config for ${localDeploymentName}`); await (0, import_filePaths.saveDeploymentConfig)(ctx, "local", localDeploymentName, { adminKey, backendVersion: config.backendVersion, ports: config.ports }); await (0, import_bigBrain.bigBrainPause)(ctx, { projectSlug, teamSlug: args.teamSlug }); (0, import_context.logFinishedStep)( ctx, `Linked ${args.deploymentName} to project ${projectSlug}` ); return { projectSlug, deploymentName: localDeploymentName, deploymentUrl: (0, import_run.localDeploymentUrl)(config.ports.cloud) }; } async function moveDeployment(ctx, oldDeployment, newDeployment) { const oldPath = (0, import_filePaths.deploymentStateDir)( oldDeployment.deploymentKind, oldDeployment.deploymentName ); const newPath = (0, import_filePaths.deploymentStateDir)( newDeployment.deploymentKind, newDeployment.deploymentName ); await (0, import_fsUtils.recursivelyCopy)(ctx, import_fs.nodeFs, oldPath, newPath); (0, import_fsUtils.recursivelyDelete)(ctx, oldPath); } //# sourceMappingURL=anonymous.js.map