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