Skip to content

Commit

Permalink
feat: bump cosmiconfig version and conditionally support mjs config (#…
Browse files Browse the repository at this point in the history
…3747)

* feat(load): use cosmiconfig-typescript-loader v5 to remove ts-node dependency for @commitlint/load

* feat: conditionally support loading mjs config based on the node version

* chore: update 'test-ci' command

* chore: add yarn cache to ci

* chore: swap node and checkout order. Remove ownership workaround

* chore(load): remove duplicate tests

* docs: add mjs config files to README
  • Loading branch information
joberstein committed Nov 10, 2023
1 parent f33be70 commit a2b65fc
Show file tree
Hide file tree
Showing 26 changed files with 123 additions and 119 deletions.
4 changes: 4 additions & 0 deletions @commitlint/load/fixtures/config/.commitlintrc
@@ -0,0 +1,4 @@
extends:
- './first-extended'
rules:
zero: [0, 'never']
6 changes: 6 additions & 0 deletions @commitlint/load/fixtures/config/.commitlintrc.cjs
@@ -0,0 +1,6 @@
module.exports = {
extends: ['./first-extended'],
rules: {
zero: [0, 'never'],
},
};
Expand Up @@ -3,4 +3,4 @@ module.exports = {
rules: {
zero: [0, 'never'],
},
};
};
Expand Up @@ -3,4 +3,4 @@
"rules": {
"zero": [0, "never"]
}
}
}
6 changes: 6 additions & 0 deletions @commitlint/load/fixtures/config/.commitlintrc.mjs
@@ -0,0 +1,6 @@
export default {
extends: ['./first-extended'],
rules: {
zero: [0, 'never'],
},
};
4 changes: 4 additions & 0 deletions @commitlint/load/fixtures/config/.commitlintrc.yaml
@@ -0,0 +1,4 @@
extends:
- './first-extended'
rules:
zero: [0, 'never']
@@ -1,4 +1,4 @@
extends:
- './first-extended'
rules:
zero: [0, 'never']
zero: [0, 'never']
6 changes: 6 additions & 0 deletions @commitlint/load/fixtures/config/commitlint.config.cjs
@@ -0,0 +1,6 @@
module.exports = {
extends: ['./first-extended'],
rules: {
zero: [0, 'never'],
},
};
6 changes: 6 additions & 0 deletions @commitlint/load/fixtures/config/commitlint.config.js
@@ -0,0 +1,6 @@
module.exports = {
extends: ['./first-extended'],
rules: {
zero: [0, 'never'],
},
};
6 changes: 6 additions & 0 deletions @commitlint/load/fixtures/config/commitlint.config.mjs
@@ -0,0 +1,6 @@
export default {
extends: ['./first-extended'],
rules: {
zero: [0, 'never'],
},
};
Expand Up @@ -10,4 +10,4 @@
]
}
}
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

@@ -1,7 +1,7 @@
import type {UserConfig} from './types';

const Configuration: UserConfig = {
extends: ['./first-extended'],
extends: ['./first-extended/index.ts'],
rules: {
zero: [0, 'never', 'zero']
}
Expand Down
@@ -1,6 +1,6 @@
import type {UserConfig} from '../types';
module.exports = {
extends: ['./second-extended'],
extends: ['./second-extended/index.ts'],
rules: {
one: [1, 'never', 'one']
}
Expand Down

This file was deleted.

This file was deleted.

96 changes: 27 additions & 69 deletions @commitlint/load/src/load.test.ts
Expand Up @@ -7,10 +7,12 @@ jest.mock('@scope/commitlint-plugin-example', () => scopedPlugin, {
});

import path from 'path';
import {readFileSync, writeFileSync} from 'fs';
import resolveFrom from 'resolve-from';
import {fix, git, npm} from '@commitlint/test';

import load from './load';
import {isDynamicAwaitSupported} from './utils/load-config';

const fixBootstrap = (name: string) => fix.bootstrap(name, __dirname);
const gitBootstrap = (name: string) => git.bootstrap(name, __dirname);
Expand Down Expand Up @@ -186,24 +188,30 @@ test('respects cwd option', async () => {
});
});

test('recursive extends', async () => {
const cwd = await gitBootstrap('fixtures/recursive-extends');
const actual = await load({}, {cwd});

expect(actual).toMatchObject({
formatter: '@commitlint/format',
extends: ['./first-extended'],
plugins: {},
rules: {
zero: [0, 'never'],
one: [1, 'always'],
two: [2, 'never'],
},
});
});
const mjsConfigFiles = isDynamicAwaitSupported()
? ['commitlint.config.mjs', '.commitlintrc.mjs']
: [];

test.each(
[
'commitlint.config.cjs',
'commitlint.config.js',
'package.json',
'.commitlintrc',
'.commitlintrc.cjs',
'.commitlintrc.js',
'.commitlintrc.json',
'.commitlintrc.yml',
'.commitlintrc.yaml',
...mjsConfigFiles,
].map((configFile) => [configFile])
)('recursive extends with %s', async (configFile) => {
const cwd = await gitBootstrap(`fixtures/recursive-extends-js-template`);
const configPath = path.join(__dirname, `../fixtures/config/${configFile}`);
const config = readFileSync(configPath);

writeFileSync(path.join(cwd, configFile), config);

test('recursive extends with json file', async () => {
const cwd = await gitBootstrap('fixtures/recursive-extends-json');
const actual = await load({}, {cwd});

expect(actual).toMatchObject({
Expand All @@ -218,63 +226,13 @@ test('recursive extends with json file', async () => {
});
});

test('recursive extends with yaml file', async () => {
const cwd = await gitBootstrap('fixtures/recursive-extends-yaml');
const actual = await load({}, {cwd});

expect(actual).toMatchObject({
formatter: '@commitlint/format',
extends: ['./first-extended'],
plugins: {},
rules: {
zero: [0, 'never'],
one: [1, 'never'],
two: [2, 'always'],
},
});
});

test('recursive extends with js file', async () => {
const cwd = await gitBootstrap('fixtures/recursive-extends-js');
const actual = await load({}, {cwd});

expect(actual).toMatchObject({
formatter: '@commitlint/format',
extends: ['./first-extended'],
plugins: {},
rules: {
zero: [0, 'never'],
one: [1, 'never'],
two: [2, 'always'],
},
});
});

test('recursive extends with package.json file', async () => {
const cwd = await gitBootstrap('fixtures/recursive-extends-package');
const actual = await load({}, {cwd});

expect(actual).toMatchObject({
formatter: '@commitlint/format',
extends: ['./first-extended'],
plugins: {},
rules: {
zero: [0, 'never'],
one: [1, 'never'],
two: [2, 'never'],
},
});
});

// fails since a jest update: https://github.com/conventional-changelog/commitlint/pull/3362
// eslint-disable-next-line jest/no-disabled-tests
test.skip('recursive extends with ts file', async () => {
test('recursive extends with ts file', async () => {
const cwd = await gitBootstrap('fixtures/recursive-extends-ts');
const actual = await load({}, {cwd});

expect(actual).toMatchObject({
formatter: '@commitlint/format',
extends: ['./first-extended'],
extends: ['./first-extended/index.ts'],
plugins: {},
rules: {
zero: [0, 'never', 'zero'],
Expand Down
45 changes: 42 additions & 3 deletions @commitlint/load/src/utils/load-config.ts
@@ -1,4 +1,9 @@
import {cosmiconfig, type Loader} from 'cosmiconfig';
import {
cosmiconfig,
defaultLoadersSync,
Options,
type Loader,
} from 'cosmiconfig';
import {TypeScriptLoader} from 'cosmiconfig-typescript-loader';
import path from 'path';

Expand All @@ -8,12 +13,12 @@ export interface LoadConfigResult {
isEmpty?: boolean;
}

const moduleName = 'commitlint';

export async function loadConfig(
cwd: string,
configPath?: string
): Promise<LoadConfigResult | null> {
const moduleName = 'commitlint';

let tsLoaderInstance: Loader | undefined;
const tsLoader: Loader = (...args) => {
if (!tsLoaderInstance) {
Expand All @@ -22,6 +27,8 @@ export async function loadConfig(
return tsLoaderInstance(...args);
};

const {searchPlaces, loaders} = getDynamicAwaitConfig();

const explorer = cosmiconfig(moduleName, {
searchPlaces: [
// cosmiconfig overrides default searchPlaces if any new search place is added (For e.g. `*.ts` files),
Expand All @@ -41,10 +48,14 @@ export async function loadConfig(
`.${moduleName}rc.cts`,
`${moduleName}.config.ts`,
`${moduleName}.config.cts`,

...(searchPlaces || []),
],
loaders: {
'.ts': tsLoader,
'.cts': tsLoader,

...(loaders || {}),
},
});

Expand All @@ -59,3 +70,31 @@ export async function loadConfig(

return null;
}

// See the following issues for more context:
// - Issue: https://github.com/nodejs/node/issues/40058
// - Resolution: https://github.com/nodejs/node/pull/48510 (Node v20.8.0)
export const isDynamicAwaitSupported = () => {
const [major, minor] = process.version
.replace('v', '')
.split('.')
.map((val) => parseInt(val));

return major >= 20 && minor >= 8;
};

// If dynamic await is supported (Node >= v20.8.0), support mjs config.
// Otherwise, don't support mjs and use synchronous js/cjs loaders.
export const getDynamicAwaitConfig = (): Partial<Options> =>
isDynamicAwaitSupported()
? {
searchPlaces: [`.${moduleName}rc.mjs`, `${moduleName}.config.mjs`],
loaders: {},
}
: {
searchPlaces: [],
loaders: {
'.cjs': defaultLoadersSync['.cjs'],
'.js': defaultLoadersSync['.js'],
},
};
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -142,10 +142,12 @@ Check the [husky documentation](https://typicode.github.io/husky/#/?id=manual) o
- `.commitlintrc.yml`
- `.commitlintrc.js`
- `.commitlintrc.cjs`
- `.commitlintrc.mjs` (Node >= v20.8.0)
- `.commitlintrc.ts`
- `.commitlintrc.cts`
- `commitlint.config.js`
- `commitlint.config.cjs`
- `commitlint.config.mjs` (Node >= v20.8.0)
- `commitlint.config.ts`
- `commitlint.config.cts`
- `commitlint` field in `package.json`
Expand Down
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -19,8 +19,8 @@
"publish": "lerna publish --conventional-commits",
"reinstall": "yarn clean && yarn install",
"start": "yarn watch",
"test": "cross-env HOME=$PWD jest",
"test-ci": "cross-env HOME=$PWD jest --runInBand",
"test": "cross-env HOME=$PWD NODE_OPTIONS=--experimental-vm-modules jest",
"test-ci": "yarn test --runInBand",
"postinstall": "yarn husky install"
},
"commitlint": {
Expand Down
12 changes: 6 additions & 6 deletions yarn.lock
Expand Up @@ -3330,13 +3330,13 @@ cosmiconfig@^7.0.0:
yaml "^1.10.0"

cosmiconfig@^8.0.0:
version "8.1.3"
resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz#0e614a118fcc2d9e5afc2f87d53cd09931015689"
integrity sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==
version "8.3.6"
resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3"
integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==
dependencies:
import-fresh "^3.2.1"
import-fresh "^3.3.0"
js-yaml "^4.1.0"
parse-json "^5.0.0"
parse-json "^5.2.0"
path-type "^4.0.0"

cp-file@^7.0.0:
Expand Down Expand Up @@ -4886,7 +4886,7 @@ ignore@^5.0.4, ignore@^5.2.0, ignore@^5.2.4:
resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==

import-fresh@^3.0.0, import-fresh@^3.2.1:
import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0:
version "3.3.0"
resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
Expand Down

0 comments on commit a2b65fc

Please sign in to comment.