trifid-core
Version:
Trifid Core
84 lines (83 loc) • 3.45 kB
JavaScript
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
if (typeof path === "string" && /^\.\.?\//.test(path)) {
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
});
}
return path;
};
import { resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
import cloneDeep from 'lodash/cloneDeep.js';
import { moduleResolve } from 'import-meta-resolve';
/**
* URL of the running application's entry point, used as the base to resolve
* plugins that are dependencies of the application rather than of trifid-core.
*/
const applicationBase = new URL(pathToFileURL(process.argv[1] ?? `${process.cwd()}/`).href);
/**
* Export conditions Node was started with, so that resolving plugins relative
* to the application behaves like a regular import. The test suite relies on
* this to load TypeScript sources via `--conditions=source` instead of the
* built `dist/` output.
*/
const conditions = (() => {
const result = new Set(['node', 'import']);
const args = [
...process.execArgv,
...(process.env.NODE_OPTIONS ?? '').split(/\s+/).filter(Boolean),
];
args.forEach((arg, index) => {
const next = args[index + 1];
if ((arg === '--conditions' || arg === '-C') && next) {
result.add(next);
}
else if (arg.startsWith('--conditions=')) {
result.add(arg.slice('--conditions='.length));
}
else if (arg.startsWith('-C') && arg.length > 2) {
result.add(arg.slice(2));
}
});
return result;
})();
const resolveModulePath = (modulePath) => {
// Local paths are resolved against the current working directory.
if (['.', '/'].includes(modulePath.slice(0, 1))) {
return pathToFileURL(resolve(modulePath)).href;
}
// Prefer Node's own resolution, relative to this module: it honours the
// active export conditions and resolves trifid-core's own plugins as well as
// any plugin hoisted above it (e.g. a flat npm layout).
try {
return import.meta.resolve(modulePath);
}
catch {
// The plugin is a dependency of the application, not of trifid-core, and is
// not reachable from here (e.g. pnpm's isolated node_modules). Resolve it
// relative to the application instead.
return moduleResolve(modulePath, applicationBase, conditions).href;
}
};
export const loader = async (modulePath) => {
const plugin = await import(__rewriteRelativeImportExtension(resolveModulePath(modulePath)));
return plugin.default;
};
const load = async (config) => {
const source = (config.plugins && typeof config.plugins === 'object')
? cloneDeep(config.plugins)
: {};
const plugins = {};
await Promise.all(Object.entries(source).map(async ([name, pluginConfig]) => {
if (pluginConfig === null || pluginConfig === undefined) {
return;
}
if (!pluginConfig.module) {
throw new Error(`plugin '${name}' has no module configured`);
}
const { module, ...rest } = pluginConfig;
plugins[name] = { ...rest, module: await loader(module) };
}));
return plugins;
};
export default load;