convex
Version:
Client for the Convex Cloud
394 lines (393 loc) • 13.1 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(
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var config_exports = {};
__export(config_exports, {
configFilepath: () => configFilepath,
configFromProjectConfig: () => configFromProjectConfig,
configJSON: () => configJSON,
configName: () => configName,
diffConfig: () => diffConfig,
parseProjectConfig: () => parseProjectConfig,
productionProvisionHost: () => import_utils2.productionProvisionHost,
provisionHost: () => import_utils2.provisionHost,
pullConfig: () => pullConfig,
pushConfig: () => pushConfig,
readConfig: () => readConfig,
readProjectConfig: () => readProjectConfig,
writeProjectConfig: () => writeProjectConfig
});
module.exports = __toCommonJS(config_exports);
var import_chalk = __toESM(require("chalk"));
var import_axios = __toESM(require("axios"));
var import_deep_equal = __toESM(require("deep-equal"));
var import_path = __toESM(require("path"));
var import_bundler = require("../../bundler/index.js");
var import__ = require("../../index.js");
var import_axios_retry = __toESM(require("axios-retry"));
var import_utils = require("./utils.js");
var import_utils2 = require("./utils.js");
function isAuthInfo(object) {
return "applicationID" in object && typeof object.applicationID === "string" && "domain" in object && typeof object.domain === "string";
}
function isAuthInfos(object) {
return Array.isArray(object) && object.every((item) => isAuthInfo(item));
}
class ParseError extends Error {
}
function parseProjectConfig(obj) {
if (typeof obj !== "object") {
throw new ParseError("Expected an object");
}
if (typeof obj.team !== "string") {
if (obj.instanceName && obj.origin) {
throw new ParseError(
'If upgrading from convex 0.1.8 or below, please delete "convex.json" and reinitialize using `npx convex reinit`'
);
}
throw new ParseError("Expected team to be a string");
}
if (typeof obj.project !== "string") {
throw new ParseError("Expected project to be a string");
}
if (typeof obj.prodUrl !== "string") {
throw new ParseError("Expected prodUrl to be a string");
}
if (typeof obj.functions !== "string") {
throw new ParseError("Expected functions to be a string");
}
obj.authInfo = obj.authInfo ?? [];
if (!isAuthInfos(obj.authInfo)) {
throw new ParseError("Expected authInfo to be type AuthInfo[]");
}
return obj;
}
function parseBackendConfig(obj) {
if (typeof obj !== "object") {
throw new ParseError("Expected an object");
}
if (typeof obj.functions !== "string") {
throw new ParseError("Expected functions to be a string");
}
obj.authInfo = obj.authInfo ?? [];
if (!isAuthInfos(obj.authInfo)) {
throw new ParseError("Expected authInfo to be type AuthInfo[]");
}
return obj;
}
function configName() {
return "convex.json";
}
async function configFilepath(ctx) {
const configFn = configName();
const preferredLocation = configFn;
const wrongLocation = import_path.default.join("src", configFn);
const preferredLocationExists = ctx.fs.exists(preferredLocation);
const wrongLocationExists = ctx.fs.exists(wrongLocation);
if (preferredLocationExists && wrongLocationExists) {
console.error(
import_chalk.default.red(
`Error: both ${preferredLocation} and ${wrongLocation} files exist!`
)
);
console.error(`Consolidate these and remove ${wrongLocation}.`);
return await ctx.fatalError(1, "fs");
}
if (!preferredLocationExists && wrongLocationExists) {
console.error(
import_chalk.default.red(
`Error: Please move ${wrongLocation} to the root of your project`
)
);
return await ctx.fatalError(1, "fs");
}
return preferredLocation;
}
async function readProjectConfig(ctx) {
let projectConfig;
const configPath = await configFilepath(ctx);
try {
projectConfig = parseProjectConfig(
JSON.parse(ctx.fs.readUtf8File(configPath))
);
} catch (err) {
if (err instanceof ParseError || err instanceof SyntaxError) {
console.error(import_chalk.default.red(`Error: Parsing "${configPath}" failed`));
console.error(import_chalk.default.gray(err.toString()));
} else {
console.error(
import_chalk.default.red(`Error: Unable to read project config file "${configPath}"`)
);
console.error(
"Are you running this command from the root directory of a Convex project?"
);
if (err instanceof Error) {
console.error(import_chalk.default.gray(err.message));
}
}
return await ctx.fatalError(1, "fs", err);
}
return {
projectConfig,
configPath
};
}
async function configFromProjectConfig(ctx, projectConfig, configPath, verbose) {
let modules;
try {
const baseDir = (0, import_utils.functionsDir)(configPath, projectConfig);
const entryPoints = await (0, import_bundler.databaseEntryPoints)(ctx.fs, baseDir, verbose);
modules = await (0, import_bundler.bundle)(ctx.fs, baseDir, entryPoints, true, "browser");
if (verbose) {
console.log(
"Queries and mutations modules: ",
modules.map((m) => m.path)
);
}
const nodeEntryPoints = await (0, import_bundler.actionsEntryPoints)(ctx.fs, baseDir, verbose);
const nodeModules = await (0, import_bundler.bundle)(
ctx.fs,
baseDir,
nodeEntryPoints,
true,
"node",
import_path.default.join(import_bundler.actionsDir, "_deps")
);
if (verbose) {
console.log(
"Actions modules: ",
nodeModules.map((m) => m.path)
);
}
modules.push(...nodeModules);
} catch (err) {
console.error(import_chalk.default.red("Error: Unable to bundle Convex modules"));
if (err instanceof Error) {
console.error(import_chalk.default.gray(err.message));
}
return await ctx.fatalError(1, "fs", err);
}
return {
projectConfig,
modules,
udfServerVersion: import__.version
};
}
async function readConfig(ctx, verbose) {
const { projectConfig, configPath } = await readProjectConfig(ctx);
const config = await configFromProjectConfig(
ctx,
projectConfig,
configPath,
verbose
);
return { config, configPath };
}
async function writeProjectConfig(ctx, projectConfig) {
const configPath = await configFilepath(ctx);
try {
const contents = JSON.stringify(projectConfig, void 0, 2) + "\n";
ctx.fs.writeUtf8File(configPath, contents, 420);
} catch (err) {
console.error(
import_chalk.default.red(
`Error: Unable to write project config file "${configPath}" in current directory`
)
);
console.error(
"Are you running this command from the root directory of a Convex project?"
);
return await ctx.fatalError(1, "fs", err);
}
ctx.fs.mkdir((0, import_utils.functionsDir)(configPath, projectConfig), {
allowExisting: true
});
}
async function pullConfig(ctx, project, team, origin, adminKey) {
const client = import_axios.default.create();
(0, import_axios_retry.default)(client, {
retries: 4,
retryDelay: import_axios_retry.default.exponentialDelay,
retryCondition: (error) => {
return error.response?.status == 404 || false;
}
});
try {
const res = await client.post(
`${origin}/api/${import__.version}/get_config`,
{ version: import__.version, adminKey },
{
maxContentLength: Infinity
}
);
(0, import_utils.deprecationCheckWarning)(ctx, res);
const { functions, authInfo } = parseBackendConfig(res.data.config);
const projectConfig = {
project,
team,
prodUrl: origin,
functions,
authInfo
};
return {
projectConfig,
modules: res.data.modules,
udfServerVersion: res.data.udfServerVersion
};
} catch (err) {
console.error(
import_chalk.default.red("Error: Unable to pull deployment config from", origin)
);
return await (0, import_utils.fatalServerErr)(ctx, err);
}
}
function configJSON(config, adminKey) {
const projectConfig = {
projectSlug: config.projectConfig.project,
teamSlug: config.projectConfig.team,
functions: config.projectConfig.functions,
authInfo: config.projectConfig.authInfo
};
return {
config: projectConfig,
modules: config.modules,
udfServerVersion: config.udfServerVersion,
adminKey
};
}
async function pushConfig(ctx, config, adminKey, url) {
const serializedConfig = configJSON(config, adminKey);
try {
await import_axios.default.post(`${url}/api/${import__.version}/push_config`, serializedConfig, {
maxContentLength: Infinity,
maxBodyLength: Infinity
});
} catch (err) {
console.error(import_chalk.default.red("Error: Unable to push deployment config to", url));
return await (0, import_utils.fatalServerErr)(ctx, err);
}
}
function renderModule(module2) {
const sourceMapSize = (0, import_utils.formatSize)(module2.sourceMap?.length ?? 0);
return module2.path + ` (${(0, import_utils.formatSize)(module2.source.length)}, source map ${sourceMapSize})`;
}
function compareModules(oldModules, newModules) {
let diff = "";
const droppedModules = [];
for (const oldModule of oldModules) {
let matches = false;
for (const newModule of newModules) {
if (oldModule.path === newModule.path && oldModule.source === newModule.source && oldModule.sourceMap === newModule.sourceMap) {
matches = true;
break;
}
}
if (!matches) {
droppedModules.push(oldModule);
}
}
if (droppedModules.length > 0) {
diff += "Delete the following modules:\n";
for (const module2 of droppedModules) {
diff += "[-] " + renderModule(module2) + "\n";
}
}
const addedModules = [];
for (const newModule of newModules) {
let matches = false;
for (const oldModule of oldModules) {
if (oldModule.path === newModule.path && oldModule.source === newModule.source && oldModule.sourceMap === newModule.sourceMap) {
matches = true;
break;
}
}
if (!matches) {
addedModules.push(newModule);
}
}
if (addedModules.length > 0) {
diff += "Add the following modules:\n";
for (const module2 of addedModules) {
diff += "[+] " + renderModule(module2) + "\n";
}
}
return diff;
}
function diffConfig(oldConfig, newConfig) {
let diff = compareModules(oldConfig.modules, newConfig.modules);
const droppedAuth = [];
for (const oldAuth of oldConfig.projectConfig.authInfo) {
let matches2 = false;
for (const newAuth of newConfig.projectConfig.authInfo) {
if ((0, import_deep_equal.default)(oldAuth, newAuth)) {
matches2 = true;
break;
}
}
if (!matches2) {
droppedAuth.push(oldAuth);
}
}
if (droppedAuth.length > 0) {
diff += "Remove the following auth providers:\n";
for (const authInfo of droppedAuth) {
diff += "[-] " + JSON.stringify(authInfo) + "\n";
}
}
const addedAuth = [];
for (const newAuth of newConfig.projectConfig.authInfo) {
let matches2 = false;
for (const oldAuth of oldConfig.projectConfig.authInfo) {
if ((0, import_deep_equal.default)(newAuth, oldAuth)) {
matches2 = true;
break;
}
}
if (!matches2) {
addedAuth.push(newAuth);
}
}
if (addedAuth.length > 0) {
diff += "Add the following auth providers:\n";
for (const auth of addedAuth) {
diff += "[+] " + JSON.stringify(auth) + "\n";
}
}
let versionMessage = "";
const matches = oldConfig.udfServerVersion === newConfig.udfServerVersion;
if (oldConfig.udfServerVersion && (!newConfig.udfServerVersion || !matches)) {
versionMessage += `[-] ${oldConfig.udfServerVersion}
`;
}
if (newConfig.udfServerVersion && (!oldConfig.udfServerVersion || !matches)) {
versionMessage += `[+] ${newConfig.udfServerVersion}
`;
}
if (versionMessage) {
diff += "Change the server's function version:\n";
diff += versionMessage;
}
return diff;
}
//# sourceMappingURL=config.js.map