UNPKG

@cocalc/server

Version:

CoCalc server functionality: functions used by either the hub and the next.js server

84 lines (72 loc) 2.56 kB
/* * This file is part of CoCalc: Copyright © 2020 Sagemath, Inc. * License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details */ // This is used by the hub to adjust the "customization" variable for the user visible site, and also by manage in on-prem, to actually get the associated configuration import getLogger from "@cocalc/backend/logger"; import { Purpose, sanitizeSoftwareEnv, SoftwareEnvConfig, } from "@cocalc/util/sanitize-software-envs"; import { constants } from "fs"; import { access, readFile } from "fs/promises"; import { join } from "path"; const logger = getLogger("hub:webapp-config"); const L = logger.debug; const W = logger.warn; const cache: { [key in Purpose]: SoftwareEnvConfig | false | null } = { server: null, webapp: null, }; /** * A configuration for available software environments could be stored at the location of $COCALC_SOFTWARE_ENVIRONMENTS. */ export async function getSoftwareEnvironments( purpose: Purpose ): Promise<SoftwareEnvConfig | null> { if (cache[purpose] === null) { cache[purpose] = (await readConfig(purpose)) ?? false; } const data = cache[purpose]; return data === false ? null : data; } async function readConfig(purpose: Purpose): Promise<SoftwareEnvConfig | null> { const dir = process.env.COCALC_SOFTWARE_ENVIRONMENTS; if (!dir) return null; // Check if a file "software.json" and "registry" exist and are readable at the directory "dir": const softwareFn = join(dir, "software.json"); const registryFn = join(dir, "registry"); if (!(await isReadable(softwareFn))) { W( `WARNING: $COCALC_SOFTWARE_ENVIRONMENTS is defined but ${softwareFn} does not exist` ); return null; } if (!(await isReadable(registryFn))) { W( `WARNING: $COCALC_SOFTWARE_ENVIRONMENTS is defined but ${registryFn} does not exist` ); return null; } // read the content of registry and trim it to a one line string const registry = (await readFile(registryFn)).toString().trim(); // parse the content of softwareFn as json try { const software = JSON.parse((await readFile(softwareFn)).toString()); const dbg = (...msg) => L(...msg); const sanitized = sanitizeSoftwareEnv({ software, registry, purpose }, dbg); return sanitized; } catch (err) { W(`WARNING: ${softwareFn} is not a valid JSON file -- ${err}`); return null; } } async function isReadable(path: string): Promise<boolean> { try { await access(path, constants.R_OK); } catch (err) { return false; } return true; }