UNPKG

convex

Version:

Client for the Convex Cloud

394 lines (393 loc) 13.1 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( 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