astro-ghostcms/.pnpm-store/v3/files/f9/ec1ddd400de210b2fb3b62858ff...

179 lines
4.8 KiB
Plaintext
Raw Normal View History

2024-02-14 14:10:47 +00:00
import fs, { promises, constants } from 'node:fs';
import { parse, resolve, dirname, join, basename } from 'node:path';
import process from 'node:process';
import { interopDefault } from 'mlly';
import jiti from 'jiti';
import { toArray, notNullish } from '@antfu/utils';
import defu from 'defu';
const defaultExtensions = ["mts", "cts", "ts", "mjs", "cjs", "js", "json", ""];
function existsSync(fp) {
try {
fs.accessSync(fp, constants.R_OK);
return true;
} catch {
return false;
}
}
async function findUp(paths, options = {}) {
const {
cwd = process.cwd(),
stopAt = parse(cwd).root,
multiple = false,
allowSymlinks = true
} = options;
let current = cwd;
const files = [];
const stat = allowSymlinks ? promises.stat : promises.lstat;
while (current && current !== stopAt) {
for (const path of paths) {
const filepath = resolve(current, path);
if (existsSync(filepath) && (await stat(filepath)).isFile()) {
files.push(filepath);
if (!multiple)
return files;
}
}
const parent = dirname(current);
if (parent === current)
break;
current = parent;
}
return files;
}
function createConfigLoader(options) {
const sources = toArray(options.sources || []);
const {
cwd = process.cwd(),
merge,
defaults
} = options;
const results = [];
let matchedFiles;
async function findConfigs() {
if (matchedFiles == null)
matchedFiles = [];
matchedFiles.length = 0;
for (const source of sources) {
const { extensions = defaultExtensions } = source;
const flatTargets = toArray(source?.files || []).flatMap(
(file) => !extensions.length ? [file] : extensions.map((i) => i ? `${file}.${i}` : file)
);
const files = await findUp(flatTargets, { cwd, stopAt: options.stopAt, multiple: merge });
matchedFiles.push([source, files]);
}
return matchedFiles.flatMap((i) => i[1]);
}
async function load(force = false) {
if (matchedFiles == null || force)
await findConfigs();
for (const [source, files] of matchedFiles) {
if (!files.length)
continue;
if (!merge) {
const result = await loadConfigFile(files[0], source);
if (result) {
return {
config: defu(result.config, defaults),
sources: result.sources
};
}
} else {
results.push(
...(await Promise.all(
files.map((file) => loadConfigFile(file, source))
)).filter(notNullish)
);
}
}
if (!results.length) {
return {
config: defaults,
sources: []
};
}
return {
// @ts-expect-error cast
config: defu(...results.map((i) => i.config), defaults),
sources: results.map((i) => i.sources).flat()
};
}
return {
load,
findConfigs
};
}
async function loadConfig(options) {
return createConfigLoader(options).load();
}
async function loadConfigFile(filepath, source) {
let config;
let parser = source.parser || "auto";
let bundleFilepath = filepath;
let code;
async function read() {
if (code == null)
code = await promises.readFile(filepath, "utf-8");
return code;
}
if (source.transform) {
const transformed = await source.transform(await read(), filepath);
if (transformed) {
bundleFilepath = join(dirname(filepath), `__unconfig_${basename(filepath)}`);
await promises.writeFile(bundleFilepath, transformed, "utf-8");
code = transformed;
}
}
if (parser === "auto") {
try {
config = JSON.parse(await read());
parser = "json";
} catch {
parser = "require";
}
}
try {
if (!config) {
if (typeof parser === "function") {
config = await parser(filepath);
} else if (parser === "require") {
if (process.versions.bun) {
const defaultImport = await import(filepath);
config = interopDefault(defaultImport);
} else {
config = await jiti(filepath, {
interopDefault: true,
cache: false,
v8cache: false,
esmResolve: true,
// FIXME: https://github.com/unjs/jiti/pull/141
requireCache: false
})(bundleFilepath);
}
} else if (parser === "json") {
config = JSON.parse(await read());
}
}
if (!config)
return;
const rewritten = source.rewrite ? await source.rewrite(config, filepath) : config;
if (!rewritten)
return void 0;
return {
config: rewritten,
sources: [filepath]
};
} catch (e) {
if (source.skipOnError)
return;
throw e;
} finally {
if (bundleFilepath !== filepath)
await promises.unlink(bundleFilepath).catch();
}
}
export { createConfigLoader, defaultExtensions, loadConfig };