convex
Version:
Client for the Convex Cloud
474 lines (473 loc) • 15.8 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 api_exports = {};
__export(api_exports, {
createProject: () => createProject,
createProjectProvisioningDevOrProd: () => createProjectProvisioningDevOrProd,
deploymentSelectionFromOptions: () => deploymentSelectionFromOptions,
fetchDeploymentCredentialsForName: () => fetchDeploymentCredentialsForName,
fetchDeploymentCredentialsProvisionProd: () => fetchDeploymentCredentialsProvisionProd,
fetchDeploymentCredentialsProvisioningDevOrProdMaybeThrows: () => fetchDeploymentCredentialsProvisioningDevOrProdMaybeThrows,
fetchDeploymentCredentialsWithinCurrentProject: () => fetchDeploymentCredentialsWithinCurrentProject,
fetchTeamAndProject: () => fetchTeamAndProject,
projectSelection: () => projectSelection,
storeAdminKeyEnvVar: () => storeAdminKeyEnvVar
});
module.exports = __toCommonJS(api_exports);
var import_context = require("../../bundler/context.js");
var import_deployment = require("./deployment.js");
var import_envvars = require("./envvars.js");
var import_login = require("./login.js");
var import_utils = require("./utils/utils.js");
async function createProject(ctx, {
teamSlug: selectedTeamSlug,
projectName
}) {
const provisioningArgs = {
team: selectedTeamSlug,
projectName,
// TODO: Consider allowing projects with no deployments, or consider switching
// to provisioning prod on creation.
deploymentType: "dev",
backendVersionOverride: process.env.CONVEX_BACKEND_VERSION_OVERRIDE
};
const data = await (0, import_utils.bigBrainAPI)({
ctx,
method: "POST",
url: "create_project",
data: provisioningArgs
});
const { projectSlug, teamSlug, projectsRemaining } = data;
if (projectSlug === void 0 || teamSlug === void 0 || projectsRemaining === void 0) {
const error = "Unexpected response during provisioning: " + JSON.stringify(data);
return await ctx.crash({
exitCode: 1,
errorType: "transient",
errForSentry: error,
printedMessage: error
});
}
return {
projectSlug,
teamSlug,
projectsRemaining
};
}
async function createProjectProvisioningDevOrProd(ctx, {
teamSlug: selectedTeamSlug,
projectName
}, firstDeploymentType) {
const provisioningArgs = {
team: selectedTeamSlug,
projectName,
deploymentType: firstDeploymentType,
backendVersionOverride: process.env.CONVEX_BACKEND_VERSION_OVERRIDE
};
const data = await (0, import_utils.bigBrainAPI)({
ctx,
method: "POST",
url: "create_project",
data: provisioningArgs
});
const {
projectSlug,
teamSlug,
deploymentName,
adminKey,
projectsRemaining,
prodUrl: url
} = data;
if (projectSlug === void 0 || teamSlug === void 0 || deploymentName === void 0 || url === void 0 || adminKey === void 0 || projectsRemaining === void 0) {
const error = "Unexpected response during provisioning: " + JSON.stringify(data);
return await ctx.crash({
exitCode: 1,
errorType: "transient",
errForSentry: error,
printedMessage: error
});
}
return {
projectSlug,
teamSlug,
deploymentName,
url,
adminKey,
projectsRemaining
};
}
async function fetchDeploymentCredentialsForName(ctx, deploymentName, deploymentType) {
let data;
try {
data = await (0, import_utils.bigBrainAPIMaybeThrows)({
ctx,
method: "POST",
url: "deployment/authorize_for_name",
data: {
deploymentName,
deploymentType
}
});
} catch (error) {
return { error };
}
const adminKey = data.adminKey;
const url = data.url;
const resultDeploymentType = data.deploymentType;
if (adminKey === void 0 || url === void 0) {
const msg = "Unknown error during authorization: " + JSON.stringify(data);
return await ctx.crash({
exitCode: 1,
errorType: "transient",
errForSentry: new Error(msg),
printedMessage: msg
});
}
return {
deploymentName,
adminKey,
url,
deploymentType: resultDeploymentType
};
}
function storeAdminKeyEnvVar(adminKeyOption) {
if (adminKeyOption) {
process.env[import_utils.CONVEX_DEPLOY_KEY_ENV_VAR_NAME] = adminKeyOption;
}
}
function deploymentSelectionFromOptions(options) {
storeAdminKeyEnvVar(options.adminKey);
const adminKey = (0, import_utils.readAdminKeyFromEnvVar)();
if (options.url !== void 0) {
if (adminKey) {
return { kind: "urlWithAdminKey", url: options.url, adminKey };
}
return { kind: "urlWithLogin", url: options.url };
}
if (options.previewName !== void 0) {
return { kind: "previewName", previewName: options.previewName };
}
if (options.deploymentName !== void 0) {
return { kind: "deploymentName", deploymentName: options.deploymentName };
}
if (adminKey !== void 0) {
return { kind: "deployKey" };
}
return { kind: options.prod === true ? "ownProd" : "ownDev" };
}
async function fetchDeploymentCredentialsWithinCurrentProject(ctx, deploymentSelection) {
if (deploymentSelection.kind === "urlWithAdminKey") {
return {
adminKey: deploymentSelection.adminKey,
url: deploymentSelection.url
};
}
const configuredAdminKey = (0, import_utils.readAdminKeyFromEnvVar)();
if (configuredAdminKey === void 0) {
const buildEnvironmentExpectsConvexDeployKey = (0, import_envvars.buildEnvironment)();
if (buildEnvironmentExpectsConvexDeployKey) {
return await ctx.crash({
exitCode: 1,
errorType: "fatal",
printedMessage: `${buildEnvironmentExpectsConvexDeployKey} build environment detected but ${import_utils.CONVEX_DEPLOY_KEY_ENV_VAR_NAME} is not set. Set this environment variable to deploy from this environment. See https://docs.convex.dev/production/hosting`
});
}
const header = await (0, import_utils.getAuthHeaderForBigBrain)(ctx);
if (!header) {
return await ctx.crash({
exitCode: 1,
errorType: "fatal",
printedMessage: `Error: You are not logged in. Log in with \`npx convex dev\` or set the ${import_utils.CONVEX_DEPLOY_KEY_ENV_VAR_NAME} environment variable. See https://docs.convex.dev/production/hosting`
});
}
const configuredDeployment = await (0, import_utils.getConfiguredDeploymentName)(ctx);
if (configuredDeployment === null) {
return await ctx.crash({
exitCode: 1,
errorType: "fatal",
printedMessage: "No CONVEX_DEPLOYMENT set, run `npx convex dev` to configure a Convex project"
});
}
}
const data = await fetchDeploymentCredentialsWithinCurrentProjectInner(
ctx,
deploymentSelection,
configuredAdminKey
);
const { deploymentName, adminKey, deploymentType, url } = data;
if (adminKey === void 0 || url === void 0 || deploymentName === void 0) {
const msg = "Unknown error during authorization: " + JSON.stringify(data);
return await ctx.crash({
exitCode: 1,
errorType: "transient",
errForSentry: new Error(msg),
printedMessage: msg
});
}
return {
deploymentName,
adminKey,
url,
deploymentType
};
}
async function projectSelection(ctx, configuredDeployment, configuredAdminKey) {
if (configuredAdminKey !== void 0 && (0, import_deployment.isPreviewDeployKey)(configuredAdminKey)) {
const { teamSlug, projectSlug } = await (0, import_deployment.getTeamAndProjectFromPreviewAdminKey)(ctx, configuredAdminKey);
return {
kind: "teamAndProjectSlugs",
teamSlug,
projectSlug
};
}
if (configuredAdminKey !== void 0) {
return {
kind: "deploymentName",
deploymentName: await (0, import_deployment.deploymentNameFromAdminKeyOrCrash)(
ctx,
configuredAdminKey
)
};
}
if (configuredDeployment) {
return {
kind: "deploymentName",
deploymentName: configuredDeployment
};
}
return await ctx.crash({
exitCode: 1,
errorType: "fatal",
printedMessage: "Select project by setting `CONVEX_DEPLOYMENT` with `npx convex dev` or `CONVEX_DEPLOY_KEY` from the Convex dashboard."
});
}
async function fetchDeploymentCredentialsWithinCurrentProjectInner(ctx, deploymentSelection, configuredAdminKey) {
const configuredDeployment = (0, import_deployment.getConfiguredDeploymentFromEnvVar)().name;
switch (deploymentSelection.kind) {
case "ownDev": {
return {
...await fetchExistingDevDeploymentCredentialsOrCrash(
ctx,
configuredDeployment
),
deploymentName: configuredDeployment
};
}
case "ownProd":
return await (0, import_utils.bigBrainAPI)({
ctx,
method: "POST",
url: "deployment/authorize_prod",
data: {
deploymentName: configuredDeployment
}
});
case "previewName":
return await (0, import_utils.bigBrainAPI)({
ctx,
method: "POST",
url: "deployment/authorize_preview",
data: {
previewName: deploymentSelection.previewName,
projectSelection: await projectSelection(
ctx,
configuredDeployment,
configuredAdminKey
)
}
});
case "deploymentName":
return await (0, import_utils.bigBrainAPI)({
ctx,
method: "POST",
url: "deployment/authorize_within_current_project",
data: {
selectedDeploymentName: deploymentSelection.deploymentName,
projectSelection: await projectSelection(
ctx,
configuredDeployment,
configuredAdminKey
)
}
});
case "deployKey": {
const deploymentName = await (0, import_deployment.deploymentNameFromAdminKeyOrCrash)(
ctx,
configuredAdminKey
);
let url = await deriveUrlFromAdminKey(ctx, configuredAdminKey);
if (process.env.CONVEX_PROVISION_HOST !== void 0) {
url = await (0, import_utils.bigBrainAPI)({
ctx,
method: "POST",
url: "deployment/url_for_key",
data: {
deployKey: configuredAdminKey
}
});
}
const deploymentType = (0, import_deployment.deploymentTypeFromAdminKey)(configuredAdminKey);
return {
adminKey: configuredAdminKey,
url,
deploymentName,
deploymentType
};
}
case "urlWithLogin":
return {
...await (0, import_utils.bigBrainAPI)({
ctx,
method: "POST",
url: "deployment/authorize_within_current_project",
data: {
selectedDeploymentName: configuredDeployment,
projectSelection: await projectSelection(
ctx,
configuredDeployment,
configuredAdminKey
)
}
}),
url: deploymentSelection.url
};
default: {
const _exhaustivenessCheck = deploymentSelection;
return ctx.crash({
exitCode: 1,
errorType: "fatal",
// This should be unreachable, so don't bother with a printed message.
printedMessage: null,
errForSentry: `Unexpected deployment selection: ${deploymentSelection}`
});
}
}
}
async function fetchDeploymentCredentialsProvisionProd(ctx, deploymentSelection) {
if (deploymentSelection.kind === "ownDev" && !await (0, import_login.checkAuthorization)(ctx, false)) {
await (0, import_login.performLogin)(ctx);
}
if (deploymentSelection.kind !== "ownDev") {
const result2 = await fetchDeploymentCredentialsWithinCurrentProject(
ctx,
deploymentSelection
);
(0, import_context.logVerbose)(
ctx,
`Deployment URL: ${result2.url}, Deployment Name: ${result2.deploymentName}, Deployment Type: ${result2.deploymentType}`
);
return {
url: result2.url,
adminKey: result2.adminKey,
deploymentName: result2.deploymentName,
deploymentType: result2.deploymentType
};
}
const configuredDeployment = await (0, import_utils.getConfiguredDeploymentOrCrash)(ctx);
const result = await fetchExistingDevDeploymentCredentialsOrCrash(
ctx,
configuredDeployment
);
(0, import_context.logVerbose)(
ctx,
`Deployment URL: ${result.url}, Deployment Name: ${configuredDeployment}, Deployment Type: ${result.deploymentType}`
);
return {
url: result.url,
adminKey: result.adminKey,
deploymentType: result.deploymentType,
deploymentName: configuredDeployment
};
}
async function fetchTeamAndProject(ctx, deploymentName) {
const data = await (0, import_utils.bigBrainAPI)({
ctx,
method: "GET",
url: `deployment/${deploymentName}/team_and_project`
});
const { team, project } = data;
if (team === void 0 || project === void 0) {
const msg = "Unknown error when fetching team and project: " + JSON.stringify(data);
return await ctx.crash({
exitCode: 1,
errorType: "transient",
errForSentry: new Error(msg),
printedMessage: msg
});
}
return data;
}
async function fetchDeploymentCredentialsProvisioningDevOrProdMaybeThrows(ctx, { teamSlug, projectSlug }, deploymentType) {
const data = await (0, import_utils.bigBrainAPIMaybeThrows)({
ctx,
method: "POST",
url: "deployment/provision_and_authorize",
data: {
teamSlug,
projectSlug,
deploymentType
}
});
const deploymentName = data.deploymentName;
const adminKey = data.adminKey;
const url = data.url;
if (adminKey === void 0 || url === void 0) {
const msg = "Unknown error during authorization: " + JSON.stringify(data);
return await ctx.crash({
exitCode: 1,
errorType: "transient",
errForSentry: new Error(msg),
printedMessage: msg
});
}
return { adminKey, deploymentUrl: url, deploymentName };
}
function credentialsAsDevCredentials(cred) {
if (cred.deploymentType === "dev") {
return cred;
}
throw new Error("Credentials are not for a dev deployment.");
}
async function fetchExistingDevDeploymentCredentialsOrCrash(ctx, deploymentName) {
const credentials = await fetchDeploymentCredentialsForName(
ctx,
deploymentName,
"dev"
);
if ("error" in credentials) {
return await ctx.crash({
exitCode: 1,
errorType: "invalid filesystem data",
errForSentry: credentials.error,
printedMessage: `Failed to authorize "${deploymentName}" configured in CONVEX_DEPLOYMENT, run \`npx convex dev\` to configure a Convex project`
});
}
if (credentials.deploymentType !== "dev") {
return await ctx.crash({
exitCode: 1,
errorType: "invalid filesystem data",
printedMessage: `Deployment "${deploymentName}" is not a dev deployment`
});
}
return credentialsAsDevCredentials(credentials);
}
async function deriveUrlFromAdminKey(ctx, adminKey) {
const deploymentName = await (0, import_deployment.deploymentNameFromAdminKeyOrCrash)(ctx, adminKey);
return `https://${deploymentName}.convex.cloud`;
}
//# sourceMappingURL=api.js.map