@clickup/pg-mig
Version:
PostgreSQL schema migration tool with microsharding and clustering support
72 lines (64 loc) • 2.01 kB
text/typescript
import { existsSync } from "fs";
import { dirname } from "path";
import omitBy from "lodash/omitBy";
/**
* Reads the config files from parent directories and return them from the most
* parent'ish to the most child'ish.
*
* A config is a code file which may:
* 1. Export an object.
* 2. Export a function (sync or async) which returns an object.
*/
export async function readConfigs(
fileName: string,
...args: unknown[]
): Promise<object[]> {
const configs: object[] = [];
for (let dir = process.cwd(); dirname(dir) !== dir; dir = dirname(dir)) {
const path = `${dir}/${fileName}`;
let loaded: { default?: unknown } | undefined;
const pathJS = `${path}.js`;
if (existsSync(pathJS)) {
try {
// First, try CommonJS require().
loaded = require(pathJS);
} catch (e: unknown) {
if (`${e}`.includes("ERR_REQUIRE_ESM")) {
// If it's a ESM project (e.g. "type": "module" in package.json), then
// try ESM native import.
loaded = await import(pathJS);
} else {
throw e;
}
}
}
const pathTS = `${path}.ts`;
if (!loaded && existsSync(pathTS)) {
try {
// eslint-disable-next-line import/no-extraneous-dependencies
require("ts-node/register");
} catch (e: unknown) {
throw (
`${(e instanceof Error ? e.stack ?? e.message : "" + e).trim()}\n` +
`Cause:\n To load ${pathTS}, please install ts-node module.`
);
}
loaded = require(pathTS);
}
if (!loaded) {
continue;
}
let config =
loaded instanceof Function
? loaded(...args)
: loaded.default instanceof Function
? loaded.default(...args)
: loaded.default
? loaded.default
: loaded;
config = config instanceof Promise ? await config : config;
config = omitBy(config, (v) => v === undefined);
configs.push(config);
}
return configs.reverse();
}