Source: saltcorn-data/db/connect.js

/**
 * Controls Saltcorn configuration
 * @type {path.PlatformPath | path}
 */
const path = require("path");
const fs = require("fs");
const envPaths = require("env-paths");

const pathsNoApp = envPaths("", { suffix: "" });
const pathsWithApp = envPaths("saltcorn", { suffix: "" });
/**
 * Default data path?
 * @type {string}
 */
const defaultDataPath = pathsWithApp.data;
const stringToJSON = (x) => (typeof x === "string" ? JSON.parse(x) : x);
/**
 * Get Git revision of Saltcorn source.
 * Required to work:
 *  - Git client installed,
 *  - Local git with repo Saltcorn sources.
 * @returns {null} - Return current Git commit
 */
const getGitRevision = () => {
  let revision = null;
  let options = { stdio: "pipe", cwd: __dirname };
  try {
    revision = require("child_process")
      .execSync("git rev-parse HEAD", options)
      .toString()
      .trim();
  } catch (error) {}
  return revision;
};
/**
 * Prepare Saltcorn connection object that controls main Saltcorn instance settings like:
 * - PostgreSQL or SQLite
 * - Connection to DB settings
 * - Multitenant mode
 * - Web Session secret
 * - File store path
 * - Saltcorn confuration inheritance and fixed configuration
 * For all parameters and priority see the code of function.
 * @param connSpec
 * @returns {{sc_version: string, connectionString: *, git_commit: *, version_tag: (*|string)}|{sqlite_path}|boolean}
 */
const getConnectObject = (connSpec = {}) => {
  const git_commit = getGitRevision();
  const sc_version = require("../package.json").version;
  const version_tag = git_commit || sc_version;
  var connObj = { version_tag, git_commit, sc_version };
  const fileCfg = getConfigFile() || {};

  function setKey(k, envnm, opts = {}) {
    const f = opts.transform || ((x) => x);
    // Priorities:
    // 1. getConnectObject argument
    if (typeof connSpec[k] !== "undefined") connObj[k] = f(connSpec[k]);
    // 2. Environment variables
    else if (typeof process.env[envnm] !== "undefined")
      connObj[k] = f(process.env[envnm]);
    // 3. Config file
    else if (typeof fileCfg[k] !== "undefined") connObj[k] = f(fileCfg[k]);
    // 4. default
    else if (typeof opts.default !== "undefined") connObj[k] = f(opts.default);
  }

  setKey("user", "PGUSER");
  setKey("sqlite_path", "SQLITE_FILEPATH");
  setKey("host", "PGHOST");
  setKey("port", "PGPORT");
  setKey("password", "PGPASSWORD");
  setKey("database", "PGDATABASE");
  setKey("session_secret", "SALTCORN_SESSION_SECRET");
  setKey("multi_tenant", "SALTCORN_MULTI_TENANT", { default: false });
  setKey("file_store", "SALTCORN_FILE_STORE", { default: pathsWithApp.data });
  setKey("default_schema", "SALTCORN_DEFAULT_SCHEMA", { default: "public" });
  setKey("fixed_configuration", "SALTCORN_FIXED_CONFIGURATION", {
    default: {},
    transform: stringToJSON,
  });
  setKey("inherit_configuration", "SALTCORN_INHERIT_CONFIGURATION", {
    default: [],
    transform: stringToJSON,
  });

  if (process.env.DATABASE_URL) {
    delete connObj[user];
    delete connObj[password];
    delete connObj[database];
    delete connObj[sqlite_path];
    return { ...connObj, connectionString: process.env.DATABASE_URL };
  } else if (
    connObj.sqlite_path ||
    (connObj.user && connObj.password && connObj.database)
  ) {
    return connObj;
  } else {
    return false;
  }
};
/**
 * Path to Config directory
 * @type {string}
 */
const configFileDir = pathsNoApp.config;
/**
 * Path to config file .saltcorn
 * @type {string}
 */
const configFilePath = path.join(configFileDir, ".saltcorn");
/**
 * Reads Saltcorn configuration file
 * @returns {boolean|any} - Returns JSON presentation of Saltcorn confuration file. Returns false in case of Exception.
 */
const getConfigFile = () => {
  try {
    let rawdata = fs.readFileSync(configFilePath);
    return JSON.parse(rawdata);
  } catch (e) {
    return false;
  }
};
/**
 * Check that Saltcorn configured to use SQLite as database
 * @param connObj - connectin object
 * @returns {boolean} - Returns true if Saltcorn configured to use SQLite as database
 */
const is_sqlite = (connObj) => {
  if (connObj.connectionString)
    return connObj.connectionString.startsWith("sqlite");

  return !!connObj.sqlite_path;
};

module.exports = {
  getConnectObject,
  getConfigFile,
  configFileDir,
  configFilePath,
  is_sqlite,
  defaultDataPath,
};