Skip to content

Commit a773c8b

Browse files
jpedrohgr2m
andauthored
feat: esm (#247)
BREAKING CHANGE: `@semantic-release/commit-analyzer` is now a native ES Module BREAKING CHANGE: When setting the `releaseRules` option to a path, the path must include the `.js` extension, and the file must be an ES Module itself, exporting an array as default Before: ```json { "plugins": [ ["@semantic-release/commit-analyzer", { "preset": "angular", "releaseRules": "./config/release-rules" }], "@semantic-release/release-notes-generator" ] } ``` ```js // File: config/release-rules.js module.exports = [ {type: 'docs', scope: 'README', release: 'patch'}, {type: 'refactor', scope: 'core-*', release: 'minor'}, {type: 'refactor', release: 'patch'}, ]; ``` After: ```json { "plugins": [ ["@semantic-release/commit-analyzer", { "preset": "angular", "releaseRules": "./config/release-rules.js" }], "@semantic-release/release-notes-generator" ] } ``` ```js // File: config/release-rules.js export default [ {type: 'docs', scope: 'README', release: 'patch'}, {type: 'refactor', scope: 'core-*', release: 'minor'}, {type: 'refactor', release: 'patch'}, ]; ``` Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com>
1 parent e7e56f6 commit a773c8b

17 files changed

+106
-78
lines changed

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ With this configuration:
162162

163163
##### External package / file
164164

165-
`releaseRules` can also reference a module, either by it's `npm` name or path:
165+
`releaseRules` can also reference a module, either by it's `npm` name or path. Note that the path must include the `.js` extension.
166+
166167
```json
167168
{
168169
"plugins": [
@@ -174,9 +175,12 @@ With this configuration:
174175
]
175176
}
176177
```
178+
179+
The file must be an ES Module exporting an array as default
180+
177181
```js
178182
// File: config/release-rules.js
179-
module.exports = [
183+
export default [
180184
{type: 'docs', scope: 'README', release: 'patch'},
181185
{type: 'refactor', scope: 'core-*', release: 'minor'},
182186
{type: 'refactor', release: 'patch'},

index.js

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
const {isUndefined} = require('lodash');
2-
const parser = require('conventional-commits-parser').sync;
3-
const filter = require('conventional-commits-filter');
4-
const debug = require('debug')('semantic-release:commit-analyzer');
5-
const loadParserConfig = require('./lib/load-parser-config');
6-
const loadReleaseRules = require('./lib/load-release-rules');
7-
const analyzeCommit = require('./lib/analyze-commit');
8-
const compareReleaseTypes = require('./lib/compare-release-types');
9-
const RELEASE_TYPES = require('./lib/default-release-types');
10-
const DEFAULT_RELEASE_RULES = require('./lib/default-release-rules');
1+
import lodash from 'lodash';
2+
const {isUndefined} = lodash;
3+
import {sync as parser} from 'conventional-commits-parser';
4+
import filter from 'conventional-commits-filter';
5+
import debug from 'debug';
6+
import loadParserConfig from './lib/load-parser-config.js';
7+
import loadReleaseRules from './lib/load-release-rules.js';
8+
import analyzeCommit from './lib/analyze-commit.js';
9+
import compareReleaseTypes from './lib/compare-release-types.js';
10+
import RELEASE_TYPES from './lib/default-release-types.js';
11+
import DEFAULT_RELEASE_RULES from './lib/default-release-rules.js';
12+
13+
debug('semantic-release:commit-analyzer');
1114

1215
/**
1316
* Determine the type of release to create based on a list of commits.
@@ -25,7 +28,7 @@ const DEFAULT_RELEASE_RULES = require('./lib/default-release-rules');
2528
*/
2629
async function analyzeCommits(pluginConfig, context) {
2730
const {commits, logger} = context;
28-
const releaseRules = loadReleaseRules(pluginConfig, context);
31+
const releaseRules = await loadReleaseRules(pluginConfig, context);
2932
const config = await loadParserConfig(pluginConfig, context);
3033
let releaseType = null;
3134

@@ -79,4 +82,4 @@ async function analyzeCommits(pluginConfig, context) {
7982
return releaseType;
8083
}
8184

82-
module.exports = {analyzeCommits};
85+
export {analyzeCommits};

lib/analyze-commit.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
const {isMatchWith, isString} = require('lodash');
2-
const micromatch = require('micromatch');
3-
const debug = require('debug')('semantic-release:commit-analyzer');
4-
const RELEASE_TYPES = require('./default-release-types');
5-
const compareReleaseTypes = require('./compare-release-types');
1+
import lodash from 'lodash';
2+
import micromatch from 'micromatch';
3+
import debug from 'debug';
4+
import RELEASE_TYPES from './default-release-types.js';
5+
import compareReleaseTypes from './compare-release-types.js';
6+
const {isMatchWith, isString} = lodash;
7+
const {isMatch} = micromatch;
8+
debug('semantic-release:commit-analyzer');
69

710
/**
811
* Find all the rules matching and return the highest release type of the matching rules.
@@ -11,7 +14,7 @@ const compareReleaseTypes = require('./compare-release-types');
1114
* @param {Commit} commit a parsed commit.
1215
* @return {string} the highest release type of the matching rules or `undefined` if no rule match the commit.
1316
*/
14-
module.exports = (releaseRules, commit) => {
17+
export default (releaseRules, commit) => {
1518
let releaseType;
1619

1720
releaseRules
@@ -23,7 +26,7 @@ module.exports = (releaseRules, commit) => {
2326
(!revert || commit.revert) &&
2427
// Otherwise match the regular rules
2528
isMatchWith(commit, rule, (object, src) =>
26-
isString(src) && isString(object) ? micromatch.isMatch(object, src) : undefined
29+
isString(src) && isString(object) ? isMatch(object, src) : undefined
2730
)
2831
)
2932
.every(match => {

lib/compare-release-types.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const RELEASE_TYPES = require('./default-release-types');
1+
import RELEASE_TYPES from './default-release-types.js';
22

33
/**
44
* Test if a realease type is of higher level than a given one.
@@ -7,5 +7,5 @@ const RELEASE_TYPES = require('./default-release-types');
77
* @param {string} releaseType the release type to compare with.
88
* @return {Boolean} true if `releaseType` is higher than `currentReleaseType`.
99
*/
10-
module.exports = (currentReleaseType, releaseType) =>
10+
export default (currentReleaseType, releaseType) =>
1111
!currentReleaseType || RELEASE_TYPES.indexOf(releaseType) < RELEASE_TYPES.indexOf(currentReleaseType);

lib/default-release-rules.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* @type {Array}
55
*/
6-
module.exports = [
6+
export default [
77
{breaking: true, release: 'major'},
88
{revert: true, release: 'patch'},
99
// Angular

lib/default-release-types.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
*
44
* @type {Array}
55
*/
6-
module.exports = ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'];
6+
export default ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'];

lib/esm-import.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export const esmImport = async name => {
2+
try {
3+
return (await import(name)).default;
4+
} catch (error) {
5+
if (error.code === 'ERR_MODULE_NOT_FOUND') {
6+
error.code = 'MODULE_NOT_FOUND';
7+
}
8+
9+
throw error;
10+
}
11+
};

lib/load-parser-config.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
const {promisify} = require('util');
2-
const {isPlainObject} = require('lodash');
3-
const importFrom = require('import-from');
4-
const conventionalChangelogAngular = require('conventional-changelog-angular');
1+
import {promisify} from 'util';
2+
import lodash from 'lodash';
3+
const {isPlainObject} = lodash;
4+
import {esmImport} from './esm-import.js';
55

66
/**
77
* Load `conventional-changelog-parser` options. Handle presets that return either a `Promise<Array>` or a `Promise<Function>`.
@@ -14,16 +14,16 @@ const conventionalChangelogAngular = require('conventional-changelog-angular');
1414
* @param {String} context.cwd The current working directory.
1515
* @return {Promise<Object>} a `Promise` that resolve to the `conventional-changelog-parser` options.
1616
*/
17-
module.exports = async ({preset, config, parserOpts, presetConfig}, {cwd}) => {
17+
export default async ({preset, config, parserOpts, presetConfig}, {_}) => {
1818
let loadedConfig;
1919

2020
if (preset) {
2121
const presetPackage = `conventional-changelog-${preset.toLowerCase()}`;
22-
loadedConfig = importFrom.silent(__dirname, presetPackage) || importFrom(cwd, presetPackage);
22+
loadedConfig = await esmImport(presetPackage);
2323
} else if (config) {
24-
loadedConfig = importFrom.silent(__dirname, config) || importFrom(cwd, config);
24+
loadedConfig = await esmImport(config);
2525
} else {
26-
loadedConfig = conventionalChangelogAngular;
26+
loadedConfig = await esmImport('conventional-changelog-angular');
2727
}
2828

2929
loadedConfig = await (typeof loadedConfig === 'function'

lib/load-release-rules.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
const {isUndefined} = require('lodash');
2-
const importFrom = require('import-from');
3-
const RELEASE_TYPES = require('./default-release-types');
1+
import lodash from 'lodash';
2+
const {isUndefined} = lodash;
3+
import {esmImport} from './esm-import.js';
4+
import RELEASE_TYPES from './default-release-types.js';
5+
import {resolve} from 'path';
6+
import {pathToFileURL} from 'url';
47

58
/**
69
* Load and validate the `releaseRules` rules.
@@ -15,14 +18,12 @@ const RELEASE_TYPES = require('./default-release-types');
1518
*
1619
* @return {Array} the loaded and validated `releaseRules`.
1720
*/
18-
module.exports = ({releaseRules}, {cwd}) => {
21+
export default async ({releaseRules}, {cwd}) => {
1922
let loadedReleaseRules;
2023

2124
if (releaseRules) {
2225
loadedReleaseRules =
23-
typeof releaseRules === 'string'
24-
? importFrom.silent(__dirname, releaseRules) || importFrom(cwd, releaseRules)
25-
: releaseRules;
26+
typeof releaseRules === 'string' ? await esmImport(pathToFileURL(resolve(cwd, releaseRules)).href) : releaseRules;
2627

2728
if (!Array.isArray(loadedReleaseRules)) {
2829
throw new TypeError('Error in commit-analyzer configuration: "releaseRules" must be an array of rules');

package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"name": "@semantic-release/commit-analyzer",
3+
"type": "module",
34
"description": "semantic-release plugin to analyze commits with conventional-changelog",
45
"version": "0.0.0-development",
56
"author": "Pierre Vanduynslager (https://twitter.com/@pvdlg_)",
@@ -56,7 +57,7 @@
5657
"semantic-release"
5758
],
5859
"license": "MIT",
59-
"main": "index.js",
60+
"exports": "./index.js",
6061
"nyc": {
6162
"include": [
6263
"lib/**/*.js",
@@ -94,7 +95,11 @@
9495
"prettier": true,
9596
"space": true,
9697
"rules": {
97-
"unicorn/string-content": "off"
98+
"unicorn/string-content": "off",
99+
"unicorn/import-index": "off",
100+
"import/extensions": "off",
101+
"import/no-useless-path-segments": "off",
102+
"node/no-unsupported-features/es-syntax": "off"
98103
}
99104
},
100105
"renovate": {

0 commit comments

Comments
 (0)