feat(plugins): add support for loading ESM plugins (#2688)
Co-authored-by: Matt Travi <programmer@travi.org> Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com>
This commit is contained in:
parent
5df624c6e5
commit
d170f73e0b
@ -52,14 +52,18 @@ export async function loadPlugin({cwd}, name, pluginsPath) {
|
|||||||
? dirname(resolveFrom.silent(__dirname, pluginsPath[name]) || resolveFrom(cwd, pluginsPath[name]))
|
? dirname(resolveFrom.silent(__dirname, pluginsPath[name]) || resolveFrom(cwd, pluginsPath[name]))
|
||||||
: __dirname;
|
: __dirname;
|
||||||
|
|
||||||
if (!isFunction(name)) {
|
if (isFunction(name)) {
|
||||||
const file = resolveFrom.silent(basePath, name) || resolveFrom(cwd, name);
|
return name;
|
||||||
// See https://github.com/mysticatea/eslint-plugin-node/issues/250
|
|
||||||
// eslint-disable-next-line node/no-unsupported-features/es-syntax
|
|
||||||
name = (await import(`file://${file}`)).default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
const file = resolveFrom.silent(basePath, name) || resolveFrom(cwd, name);
|
||||||
|
const { default: cjsExport, ...esmNamedExports } = await import(`file://${file}`);
|
||||||
|
|
||||||
|
if (cjsExport) {
|
||||||
|
return cjsExport;
|
||||||
|
}
|
||||||
|
|
||||||
|
return esmNamedExports;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseConfig(plugin) {
|
export function parseConfig(plugin) {
|
||||||
|
3
test/fixtures/plugin-esm-named-exports.js
vendored
Normal file
3
test/fixtures/plugin-esm-named-exports.js
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export async function verifyConditions(pluginConfig, context) {
|
||||||
|
context.logger.log("verifyConditions called");
|
||||||
|
}
|
@ -44,6 +44,7 @@ const cli = path.resolve("./bin/semantic-release.js");
|
|||||||
const pluginError = path.resolve("./test/fixtures/plugin-error");
|
const pluginError = path.resolve("./test/fixtures/plugin-error");
|
||||||
const pluginInheritedError = path.resolve("./test/fixtures/plugin-error-inherited");
|
const pluginInheritedError = path.resolve("./test/fixtures/plugin-error-inherited");
|
||||||
const pluginLogEnv = path.resolve("./test/fixtures/plugin-log-env");
|
const pluginLogEnv = path.resolve("./test/fixtures/plugin-log-env");
|
||||||
|
const pluginEsmNamedExports = path.resolve("./test/fixtures/plugin-esm-named-exports");
|
||||||
|
|
||||||
test.before(async () => {
|
test.before(async () => {
|
||||||
await Promise.all([gitbox.start(), npmRegistry.start(), mockServer.start()]);
|
await Promise.all([gitbox.start(), npmRegistry.start(), mockServer.start()]);
|
||||||
@ -713,3 +714,26 @@ test("Use the repository URL as is if none of the given git credentials are vali
|
|||||||
dummyUrl
|
dummyUrl
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("ESM Plugin with named exports", async (t) => {
|
||||||
|
const packageName = "log-secret";
|
||||||
|
// Create a git repository, set the current working directory at the root of the repo
|
||||||
|
t.log("Create git repository");
|
||||||
|
const { cwd, repositoryUrl } = await gitbox.createRepo(packageName);
|
||||||
|
await writeJson(path.resolve(cwd, "package.json"), {
|
||||||
|
name: packageName,
|
||||||
|
version: "0.0.0-dev",
|
||||||
|
repository: { url: repositoryUrl },
|
||||||
|
release: { plugins: [pluginEsmNamedExports] },
|
||||||
|
});
|
||||||
|
|
||||||
|
t.log("$ semantic-release");
|
||||||
|
const { stdout, stderr } = await execa(cli, [], {
|
||||||
|
env: { ...env, MY_TOKEN: "secret token" },
|
||||||
|
cwd,
|
||||||
|
reject: false,
|
||||||
|
extendEnv: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
t.regex(stdout, new RegExp(`verifyConditions called`));
|
||||||
|
});
|
||||||
|
@ -199,7 +199,18 @@ test('loadPlugin', async (t) => {
|
|||||||
await loadPlugin({cwd}, './plugin-noop.cjs', {'./plugin-noop.cjs': './test/fixtures'}),
|
await loadPlugin({cwd}, './plugin-noop.cjs', {'./plugin-noop.cjs': './test/fixtures'}),
|
||||||
'From a shareable config context'
|
'From a shareable config context'
|
||||||
);
|
);
|
||||||
t.is(func, await loadPlugin({cwd}, func, {}), 'Defined as a function');
|
t.is(
|
||||||
|
(await import("../fixtures/plugin-noop.cjs")).default,
|
||||||
|
await loadPlugin({ cwd }, "./plugin-noop.cjs", { "./plugin-noop.cjs": "./test/fixtures" }),
|
||||||
|
"From a shareable config context"
|
||||||
|
);
|
||||||
|
const { ...namedExports } = await import("../fixtures/plugin-esm-named-exports.js");
|
||||||
|
const plugin = await loadPlugin({ cwd }, "./plugin-esm-named-exports.js", {
|
||||||
|
"./plugin-esm-named-exports.js": "./test/fixtures",
|
||||||
|
});
|
||||||
|
|
||||||
|
t.deepEqual(namedExports, plugin, "ESM with named exports");
|
||||||
|
t.is(func, await loadPlugin({ cwd }, func, {}), "Defined as a function");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('parseConfig', (t) => {
|
test('parseConfig', (t) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user