convex
Version:
Client for the Convex Cloud
297 lines (295 loc) • 11.3 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 env_exports = {};
__export(env_exports, {
callUpdateEnvironmentVariables: () => callUpdateEnvironmentVariables,
envGetInDeployment: () => envGetInDeployment,
envGetInDeploymentAction: () => envGetInDeploymentAction,
envListInDeployment: () => envListInDeployment,
envRemoveInDeployment: () => envRemoveInDeployment,
envSetInDeployment: () => envSetInDeployment,
fetchDeploymentCanonicalSiteUrl: () => fetchDeploymentCanonicalSiteUrl
});
module.exports = __toCommonJS(env_exports);
var import_chalk = require("chalk");
var dotenv = __toESM(require("dotenv"), 1);
var import_log = require("../../bundler/log.js");
var import_run = require("./run.js");
var import_utils = require("./utils/utils.js");
var import_stdin = require("./utils/stdin.js");
var import_prompts = require("./utils/prompts.js");
var import_envvars = require("./envvars.js");
var import_formatEnvValueForDotfile = require("./formatEnvValueForDotfile.js");
var import_utils2 = require("./utils/utils.js");
function formatList(items) {
if (items.length === 0) return "";
if (items.length === 1) return items[0];
if (items.length === 2) return `${items[0]} and ${items[1]}`;
return `${items.slice(0, -1).join(", ")}, and ${items[items.length - 1]}`;
}
async function envSetInDeployment(ctx, deployment, originalName, originalValue, options) {
const { fromFile, force = false } = options ?? {};
if (originalName) {
let name = originalName, value;
const parsed = await allowEqualsSyntax(ctx, originalName, originalValue);
if (parsed) {
[name, value] = parsed;
} else if (fromFile) {
value = await getFileContents(ctx, fromFile);
} else if (!process.stdin.isTTY) {
value = await getStdIn(ctx);
} else {
value = await (0, import_prompts.promptSecret)(ctx, {
message: `Enter value for ${name}:`
});
}
await callUpdateEnvironmentVariables(ctx, deployment, [{ name, value }]);
if (options?.secret) {
const formatted = /\s/.test(value) ? `"${value}"` : value;
(0, import_log.logFinishedStep)(
`Successfully set ${import_chalk.chalkStderr.bold(name)} to ${import_chalk.chalkStderr.bold(formatted)}${deployment.deploymentNotice}`
);
} else {
(0, import_log.logFinishedStep)(`Successfully set ${import_chalk.chalkStderr.bold(name)}`);
}
return true;
}
let content, source;
if (fromFile) {
content = await getFileContents(ctx, fromFile);
source = fromFile;
} else if (!process.stdin.isTTY) {
content = await getStdIn(ctx);
source = "stdin";
} else {
return false;
}
await envSetFromContentInDeployment(ctx, deployment, {
content,
source,
force
});
return true;
}
async function getFileContents(ctx, filePath) {
if (!ctx.fs.exists(filePath)) {
return await ctx.crash({
exitCode: 1,
errorType: "fatal",
printedMessage: `error: file not found: ${filePath}`
});
}
return ctx.fs.readUtf8File(filePath);
}
async function getStdIn(ctx) {
try {
return await (0, import_stdin.readFromStdin)();
} catch (error) {
return await ctx.crash({
exitCode: 1,
errorType: "fatal",
printedMessage: `error: failed to read from stdin: ${error instanceof Error ? error.message : String(error)}`
});
}
}
async function envSetFromContentInDeployment(ctx, deployment, options) {
const { content, source, force } = options;
const parsedEnv = dotenv.parse(content);
const envVars = Object.entries(parsedEnv);
const filteredVars = [];
const envVarsToSet = [];
const managedVars = /* @__PURE__ */ new Set([
import_utils2.CONVEX_DEPLOY_KEY_ENV_VAR_NAME,
import_utils2.CONVEX_DEPLOYMENT_ENV_VAR_NAME,
import_utils2.CONVEX_SELF_HOSTED_URL_VAR_NAME,
import_utils2.CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME,
...import_envvars.EXPECTED_CONVEX_URL_NAMES,
...import_envvars.EXPECTED_SITE_URL_NAMES
]);
for (const [name, value] of envVars) {
if (managedVars.has(name)) {
filteredVars.push(name);
} else {
envVarsToSet.push([name, value]);
}
}
if (filteredVars.length > 0) {
const varNames = filteredVars.map((n) => import_chalk.chalkStderr.bold(n));
const formattedNames = formatList(varNames);
(0, import_log.logMessage)(
`Skipping ${filteredVars.length} CLI-managed environment variable${filteredVars.length === 1 ? "" : "s"}: ${formattedNames}`
);
}
if (envVarsToSet.length === 0) {
if (envVars.length === 0) {
(0, import_log.logMessage)(`No environment variables found in ${source}.`);
}
return;
}
const existingEnvVars = await getEnvVars(ctx, deployment);
const existingEnvMap = new Map(
existingEnvVars.map((env) => [env.name, env.value])
);
const newVars = [];
const updatedVars = [];
const unchangedVars = [];
const conflicts = [];
for (const [name, value] of envVarsToSet) {
const existingValue = existingEnvMap.get(name);
if (existingValue === void 0) {
newVars.push([name, value]);
} else if (existingValue === value) {
unchangedVars.push([name, value]);
} else if (force) {
updatedVars.push([name, value]);
} else {
conflicts.push({ name, existing: existingValue, new: value });
}
}
if (conflicts.length > 0) {
const varNames = conflicts.map((c) => import_chalk.chalkStderr.bold(c.name));
const formattedNames = formatList(varNames);
return await ctx.crash({
exitCode: 1,
errorType: "fatal",
printedMessage: `error: environment variable${conflicts.length === 1 ? "" : "s"} ${formattedNames} already exist${conflicts.length === 1 ? "s" : ""} with different value${conflicts.length === 1 ? "" : "s"}.
Use ${import_chalk.chalkStderr.bold("--force")} to overwrite existing values.`
});
}
const varsToUpdate = force ? [...newVars, ...updatedVars] : newVars;
const changes = varsToUpdate.map(([name, value]) => ({
name,
value
}));
if (changes.length > 0) {
await callUpdateEnvironmentVariables(ctx, deployment, changes);
}
const newCount = newVars.length;
const updatedCount = updatedVars.length;
const unchangedCount = unchangedVars.length;
const parts = [];
if (newCount > 0) parts.push(`${newCount} new`);
if (updatedCount > 0) parts.push(`${updatedCount} updated`);
if (unchangedCount > 0) parts.push(`${unchangedCount} unchanged`);
const totalProcessed = newCount + updatedCount + unchangedCount;
if (changes.length === 0) {
(0, import_log.logMessage)(
`All ${totalProcessed} environment variable${totalProcessed === 1 ? "" : "s"} from ${import_chalk.chalkStderr.bold(source)} already set${deployment.deploymentNotice}`
);
} else {
(0, import_log.logFinishedStep)(
`Successfully set ${changes.length} environment variable${changes.length === 1 ? "" : "s"} from ${import_chalk.chalkStderr.bold(source)} (${parts.join(", ")})${deployment.deploymentNotice}`
);
}
}
async function allowEqualsSyntax(ctx, name, value) {
if (/^[a-zA-Z][a-zA-Z0-9_]*=/.test(name)) {
const [n, ...values] = name.split("=");
if (value === void 0) {
return [n, values.join("=")];
} else {
await ctx.crash({
exitCode: 1,
errorType: "fatal",
printedMessage: `When setting an environment variable, you can either set a value with 'NAME=value', or with NAME value, but not both. Are you missing quotes around the CLI argument? Try:
npx convex env set '${name} ${value}'`
});
}
}
if (value === void 0) return null;
return [name, value];
}
async function envGetInDeploymentAction(ctx, deployment, name) {
const envVar = await envGetInDeployment(ctx, deployment, name);
if (envVar === null) {
(0, import_log.logFailure)(`Environment variable "${name}" not found.`);
return;
}
(0, import_log.logOutput)(`${envVar}`);
}
async function envGetInDeployment(ctx, deployment, name) {
const envVar = await (0, import_run.runSystemQuery)(ctx, {
...deployment,
functionName: "_system/cli/queryEnvironmentVariables:get",
componentPath: void 0,
args: { name }
});
return envVar === null ? null : envVar.value;
}
async function envRemoveInDeployment(ctx, deployment, name) {
await callUpdateEnvironmentVariables(ctx, deployment, [{ name }]);
(0, import_log.logFinishedStep)(
`Successfully unset ${import_chalk.chalkStderr.bold(name)}${deployment.deploymentNotice}`
);
}
async function getEnvVars(ctx, deployment) {
return await (0, import_run.runSystemQuery)(ctx, {
...deployment,
functionName: "_system/cli/queryEnvironmentVariables",
componentPath: void 0,
args: {}
});
}
async function envListInDeployment(ctx, deployment) {
const envs = await getEnvVars(ctx, deployment);
if (envs.length === 0) {
(0, import_log.logMessage)("No environment variables set.");
return;
}
for (const { name, value } of envs) {
const { formatted, warning } = (0, import_formatEnvValueForDotfile.formatEnvValueForDotfile)(value);
if (warning) {
(0, import_log.logMessage)(`Warning (${name}): ${warning}`);
}
(0, import_log.logOutput)(`${name}=${formatted}`);
}
}
async function callUpdateEnvironmentVariables(ctx, deployment, changes) {
const fetch = (0, import_utils.deploymentFetch)(ctx, deployment);
try {
await fetch("/api/update_environment_variables", {
body: JSON.stringify({ changes }),
method: "POST"
});
} catch (e) {
return await (0, import_utils.logAndHandleFetchError)(ctx, e);
}
}
async function fetchDeploymentCanonicalSiteUrl(ctx, options) {
const result = await envGetInDeployment(ctx, options, "CONVEX_SITE_URL");
if (typeof result !== "string") {
return await ctx.crash({
exitCode: 1,
errorType: "invalid filesystem or env vars",
printedMessage: "Invalid process.env.CONVEX_SITE_URL"
});
}
return result;
}
//# sourceMappingURL=env.js.map