Skip to content

Commit fc2acfc

Browse files
authored
feat: support esm format configs (#120)
1 parent 72edba9 commit fc2acfc

File tree

29 files changed

+171
-77
lines changed

29 files changed

+171
-77
lines changed

.changeset/selfish-owls-collect.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"simple-git-hooks": minor
3+
---
4+
5+
feat: support esm format configs

.eslintrc.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,13 @@ module.exports = {
88
"extends": "eslint:recommended",
99
"parserOptions": {
1010
"ecmaVersion": 12
11-
}
11+
},
12+
"overrides": [
13+
{
14+
"files": ["*.mjs"],
15+
"parserOptions": {
16+
"sourceType": "module"
17+
}
18+
}
19+
]
1220
};

.github/workflows/codeql-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939

4040
steps:
4141
- name: Checkout repository
42-
uses: actions/checkout@v3
42+
uses: actions/checkout@v4
4343

4444
# Initializes the CodeQL tools for scanning.
4545
- name: Initialize CodeQL

.github/workflows/lint.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jobs:
1616
- name: Lint
1717
uses: actions/setup-node@v4
1818
with:
19-
node-version: 14.x
20-
- run: yarn --frozen-lockfile
19+
node-version: 18.x
20+
cache: yarn
21+
- run: yarn --frozen-lockfile --ignore-engines
2122
- run: yarn lint

.github/workflows/tests.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jobs:
1616
- name: Lint
1717
uses: actions/setup-node@v4
1818
with:
19-
node-version: 14.x
20-
- run: yarn --frozen-lockfile
19+
node-version: 18.x
20+
cache: yarn
21+
- run: yarn --frozen-lockfile --ignore-engines
2122
- run: yarn test

README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,13 @@ Note that you should manually run `npx simple-git-hooks` **every time you change
120120

121121
### Additional configuration options
122122

123-
You can also add a `.simple-git-hooks.cjs`, `.simple-git-hooks.js`, `simple-git-hooks.cjs`, `simple-git-hooks.js`, `.simple-git-hooks.json` or `simple-git-hooks.json` file to the project and write the configuration inside it.
123+
You can also add a `.simple-git-hooks.cjs`, `.simple-git-hooks.js`, `.simple-git-hooks.mjs`, `simple-git-hooks.cjs`, `simple-git-hooks.js`, `simple-git-hooks.mjs`, `.simple-git-hooks.json` or `simple-git-hooks.json` file to the project and write the configuration inside it.
124124

125125
This way `simple-git-hooks` configuration in `package.json` will not take effect any more.
126126

127-
`.simple-git-hooks.cjs`, `.simple-git-hooks.js` or `simple-git-hooks.cjs`, `simple-git-hooks.js` should look like the following.
127+
`.simple-git-hooks.cjs`, `.simple-git-hooks.js`, `.simple-git-hooks.mjs` or `simple-git-hooks.cjs`, `simple-git-hooks.js`, `simple-git-hooks.mjs` should look like the following.
128+
129+
#### CommonJS
128130

129131
```js
130132
module.exports = {
@@ -133,6 +135,16 @@ module.exports = {
133135
};
134136
```
135137

138+
139+
#### ES Modules
140+
141+
```js
142+
export default {
143+
"pre-commit": "npx lint-staged",
144+
"pre-push": "npm run format",
145+
};
146+
```
147+
136148
`.simple-git-hooks.json` or `simple-git-hooks.json` should look like the following.
137149

138150
```json

_tests/project_with_configuration_in_alternative_separate_cjs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-alternative-cjs",
33
"version": "1.0.0",
44
"devDependencies": {
55
"simple-git-hooks": "1.0.0"

_tests/project_with_configuration_in_alternative_separate_js/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-alternative-js",
33
"version": "1.0.0",
44
"devDependencies": {
55
"simple-git-hooks": "1.0.0"

_tests/project_with_configuration_in_alternative_separate_json/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-alternative-json",
33
"version": "1.0.0",
44
"devDependencies": {
55
"simple-git-hooks": "1.0.0"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default {
2+
"pre-push": "exit 1",
3+
"pre-commit": "exit 1"
4+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "simple-git-hooks-test-package-alternative-mjs",
3+
"version": "1.0.0",
4+
"devDependencies": {
5+
"simple-git-hooks": "1.0.0"
6+
}
7+
}

_tests/project_with_configuration_in_package_json/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-pkg-json",
33
"version": "1.0.0",
44
"simple-git-hooks": {
55
"pre-commit": "exit 1"

_tests/project_with_configuration_in_separate_cjs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-cjs",
33
"version": "1.0.0",
44
"devDependencies": {
55
"simple-git-hooks": "1.0.0"

_tests/project_with_configuration_in_separate_js/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-js",
33
"version": "1.0.0",
44
"devDependencies": {
55
"simple-git-hooks": "1.0.0"

_tests/project_with_configuration_in_separate_json/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-json",
33
"version": "1.0.0",
44
"devDependencies": {
55
"simple-git-hooks": "1.0.0"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "simple-git-hooks-test-package-mjs",
3+
"version": "1.0.0",
4+
"devDependencies": {
5+
"simple-git-hooks": "1.0.0"
6+
}
7+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default {
2+
"pre-push": "exit 1",
3+
"pre-commit": "exit 1"
4+
}

_tests/project_with_custom_configuration/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-custom",
33
"version": "1.0.0",
44
"devDependencies": {
55
"simple-git-hooks": "1.0.0"

_tests/project_with_incorrect_configuration_in_package_json/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-incorrect",
33
"version": "1.0.0",
44
"devDependencies": {
55
"simple-git-hooks": "1.0.0"

_tests/project_with_simple_git_hooks_in_deps/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-deps",
33
"version": "1.0.0",
44
"dependencies": {
55
"simple-git-hooks": "1.0.0"

_tests/project_with_simple_git_hooks_in_dev_deps/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-dev-deps",
33
"version": "1.0.0",
44
"devDependencies": {
55
"simple-git-hooks": "1.0.0"

_tests/project_with_unused_configuration_in_package_json/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-unused",
33
"version": "1.0.0",
44
"simple-git-hooks": {
55
"pre-commit": "exit 1",

_tests/project_without_configuration/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-without-config",
33
"version": "1.0.0",
44
"devDependencies": {
55
"simple-git-hooks": "1.0.0"

_tests/project_without_simple_git_hooks/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "simple-git-hooks-test-package",
2+
"name": "simple-git-hooks-test-package-without",
33
"version": "1.0.0",
44
"devDependencies": {
55
},

cli.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ if (['1', 'true'].includes(SKIP_INSTALL_SIMPLE_GIT_HOOKS)) {
1313
return
1414
}
1515

16-
try {
17-
setHooksFromConfig(process.cwd(), process.argv)
18-
console.log('[INFO] Successfully set all git hooks')
19-
} catch (e) {
20-
console.log('[ERROR], Was not able to set git hooks. Error: ' + e)
21-
}
16+
setHooksFromConfig(process.cwd(), process.argv)
17+
.then(() => console.log('[INFO] Successfully set all git hooks'))
18+
.catch(e => console.log('[ERROR], Was not able to set git hooks. Error: ' + e))

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"name": "simple-git-hooks",
3+
"type": "commonjs",
34
"version": "2.11.1",
45
"description": "A simple, zero dependency tool for setting up git hooks for small projects",
56
"author": "Mikhail Gorbunov <toplenboren@gmail.com>",
@@ -15,7 +16,7 @@
1516
"scripts": {
1617
"postinstall": "node ./postinstall.js",
1718
"lint": "eslint *.js",
18-
"test": "jest",
19+
"test": "node --experimental-vm-modules ./node_modules/.bin/jest",
1920
"release": "clean-pkg-json && changeset publish",
2021
"uninstall": "node ./uninstall.js"
2122
},

postinstall.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const {checkSimpleGitHooksInDependencies, getProjectRootDirectoryFromNodeModules
66
/**
77
* Creates the pre-commit from command in config by default
88
*/
9-
function postinstall() {
9+
async function postinstall() {
1010
let projectDirectory;
1111

1212
/* When script is run after install, the process.cwd() would be like <project_folder>/node_modules/simple-git-hooks
@@ -21,7 +21,7 @@ function postinstall() {
2121

2222
if (checkSimpleGitHooksInDependencies(projectDirectory)) {
2323
try {
24-
setHooksFromConfig(projectDirectory)
24+
await setHooksFromConfig(projectDirectory)
2525
} catch (err) {
2626
console.log('[ERROR] Was not able to set git hooks. Reason: ' + err)
2727
}

simple-git-hooks.js

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const fs = require('fs')
22
const path = require('path')
3+
const url = require('url')
34

45
const VALID_GIT_HOOKS = [
56
'applypatch-msg',
@@ -158,12 +159,12 @@ function checkSimpleGitHooksInDependencies(projectRootPath) {
158159
* @param {string} projectRootPath
159160
* @param {string[]} [argv]
160161
*/
161-
function setHooksFromConfig(projectRootPath=process.cwd(), argv=process.argv) {
162+
async function setHooksFromConfig(projectRootPath=process.cwd(), argv=process.argv) {
162163
const customConfigPath = _getCustomConfigPath(argv)
163-
const config = _getConfig(projectRootPath, customConfigPath)
164+
const config = await _getConfig(projectRootPath, customConfigPath)
164165

165166
if (!config) {
166-
throw('[ERROR] Config was not found! Please add `.simple-git-hooks.js` or `simple-git-hooks.js` or `.simple-git-hooks.json` or `simple-git-hooks.json` or `simple-git-hooks` entry in package.json.\r\nCheck README for details')
167+
throw('[ERROR] Config was not found! Please add `.simple-git-hooks.cjs` or `.simple-git-hooks.js` or `.simple-git-hooks.mjs` or `simple-git-hooks.cjs` or `simple-git-hooks.js` or `simple-git-hooks.mjs` or `.simple-git-hooks.json` or `simple-git-hooks.json` or `simple-git-hooks` entry in package.json.\r\nCheck README for details')
167168
}
168169

169170
const preserveUnused = Array.isArray(config.preserveUnused) ? config.preserveUnused : config.preserveUnused ? VALID_GIT_HOOKS: []
@@ -274,10 +275,10 @@ function _getCustomConfigPath(argv=[]) {
274275
* @param {string} projectRootPath
275276
* @param {string} [configFileName]
276277
* @throws TypeError if projectRootPath is not string
277-
* @return {{string: string} | undefined}
278+
* @return {Promise<{[key: string]: unknown} | undefined>}
278279
* @private
279280
*/
280-
function _getConfig(projectRootPath, configFileName='') {
281+
async function _getConfig(projectRootPath, configFileName='') {
281282
if (typeof projectRootPath !== 'string') {
282283
throw TypeError("Check project root path! Expected a string, but got " + typeof projectRootPath)
283284
}
@@ -286,8 +287,10 @@ function _getConfig(projectRootPath, configFileName='') {
286287
const sources = [
287288
() => _getConfigFromFile(projectRootPath, '.simple-git-hooks.cjs'),
288289
() => _getConfigFromFile(projectRootPath, '.simple-git-hooks.js'),
290+
() => _getConfigFromFile(projectRootPath, '.simple-git-hooks.mjs'),
289291
() => _getConfigFromFile(projectRootPath, 'simple-git-hooks.cjs'),
290292
() => _getConfigFromFile(projectRootPath, 'simple-git-hooks.js'),
293+
() => _getConfigFromFile(projectRootPath, 'simple-git-hooks.mjs'),
291294
() => _getConfigFromFile(projectRootPath, '.simple-git-hooks.json'),
292295
() => _getConfigFromFile(projectRootPath, 'simple-git-hooks.json'),
293296
() => _getConfigFromPackageJson(projectRootPath),
@@ -299,11 +302,12 @@ function _getConfig(projectRootPath, configFileName='') {
299302
}
300303

301304
for (let executeSource of sources) {
302-
let config = executeSource()
303-
if (config && _validateHooks(config)) {
304-
return config
305-
}
306-
else if (config && !_validateHooks(config)) {
305+
let config = await executeSource()
306+
if (config) {
307+
if (_validateHooks(config)) {
308+
return config
309+
}
310+
307311
throw('[ERROR] Config was not in correct format. Please check git hooks or options name')
308312
}
309313
}
@@ -316,22 +320,22 @@ function _getConfig(projectRootPath, configFileName='') {
316320
* @param {string} projectRootPath
317321
* @throws TypeError if packageJsonPath is not a string
318322
* @throws Error if package.json couldn't be read or was not validated
319-
* @return {{string: string} | undefined}
323+
* @return {Promise<{[key: string]: unknown}> | {[key: string]: unknown} | undefined}
320324
*/
321325
function _getConfigFromPackageJson(projectRootPath = process.cwd()) {
322326
const {packageJsonContent} = _getPackageJson(projectRootPath)
323327
const config = packageJsonContent['simple-git-hooks'];
324-
return typeof config === 'string' ? _getConfig(config) : packageJsonContent['simple-git-hooks']
328+
return typeof config === 'string' ? _getConfig(config) : config
325329
}
326330

327331
/**
328332
* Gets user-set config from file
329333
* Since the file is not required in node.js projects it returns undefined if something is off
330334
* @param {string} projectRootPath
331335
* @param {string} fileName
332-
* @return {{string: string} | undefined}
336+
* @return {Promise<{[key: string]: unknown} | undefined>}
333337
*/
334-
function _getConfigFromFile(projectRootPath, fileName) {
338+
async function _getConfigFromFile(projectRootPath, fileName) {
335339
if (typeof projectRootPath !== "string") {
336340
throw TypeError("projectRootPath is not a string")
337341
}
@@ -347,7 +351,12 @@ function _getConfigFromFile(projectRootPath, fileName) {
347351
if (filePath === __filename) {
348352
return undefined
349353
}
350-
return require(filePath) // handle `.js` and `.json`
354+
// handle `.json` with `require`, `import()` requires `with:{type:'json'}` which does not work for all engines
355+
if (filePath.endsWith('.json')) {
356+
return require(filePath)
357+
}
358+
const result = await import(url.pathToFileURL(filePath)) // handle `.cjs`, `.js`, `.mjs`
359+
return result.default || result
351360
} catch (err) {
352361
return undefined
353362
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy