@itcase/config 1.6.64 → 1.6.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/husky-hooks/_lib.sh +3 -3
- package/husky-hooks/_run.sh +3 -2
- package/husky-hooks/install-launcher.js +100 -0
- package/husky-hooks/pre-commit +2 -1
- package/husky-hooks/{run.cjs → run.js} +13 -8
- package/lint-staged/index.js +1 -1
- package/lint-staged-ts/index.js +1 -1
- package/package.json +6 -6
- package/husky-hooks/install-launcher.cjs +0 -79
package/README.md
CHANGED
|
@@ -87,13 +87,13 @@ npm install --save-dev commitizen @commitlint/cz-commitlint
|
|
|
87
87
|
|
|
88
88
|
В репозитории остаются файлы, на которые опираются git и husky. Логика лежит в `@itcase/config/husky-hooks`. При установке пакета npm кладёт бинарь `itcase-config-husky-hooks` в `node_modules/.bin` — husky уже добавляет этот путь в `PATH`.
|
|
89
89
|
|
|
90
|
-
При `npm i` пакет
|
|
90
|
+
При `npm i` пакет копирует `.husky/_run.sh` и создаёт недостающие обёртки хуков. Свои полные хуки не перезаписывает. Добавьте в `.gitignore`:
|
|
91
91
|
|
|
92
92
|
```gitignore
|
|
93
93
|
.husky/_run.sh
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
Репы без обёрток и без одного только `.husky/config` скрипт не трогает. `npm i --ignore-scripts` файлы не создаст.
|
|
97
97
|
|
|
98
98
|
В каждом git-hook оставьте обёртку:
|
|
99
99
|
|
package/husky-hooks/_lib.sh
CHANGED
|
@@ -41,10 +41,10 @@ itcase_export_release_branch_env() {
|
|
|
41
41
|
fi
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
git grep -
|
|
44
|
+
itcase_conflict_marker_files() {
|
|
45
|
+
git grep -lI --untracked --exclude-standard \
|
|
46
46
|
-e '^<<<<<<< ' -e '^=======$' -e '^>>>>>>> ' \
|
|
47
|
-
-- . ':!node_modules' ':!dist' >/dev/null
|
|
47
|
+
-- . ':!node_modules' ':!dist' 2>/dev/null
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
itcase_run_lint_staged() {
|
package/husky-hooks/_run.sh
CHANGED
|
@@ -9,8 +9,9 @@ fi
|
|
|
9
9
|
|
|
10
10
|
ROOT="$(CDPATH= cd -- "$HUSKY_DIR/.." && pwd)"
|
|
11
11
|
for candidate in \
|
|
12
|
-
"$ROOT/
|
|
13
|
-
"$ROOT
|
|
12
|
+
"$ROOT/husky-hooks/run.js" \
|
|
13
|
+
"$ROOT/node_modules/@itcase/config/husky-hooks/run.js" \
|
|
14
|
+
"$ROOT/../itcase-config/husky-hooks/run.js"
|
|
14
15
|
do
|
|
15
16
|
if [ -f "$candidate" ]; then
|
|
16
17
|
exec node "$candidate" "$HOOK_NAME" "$@"
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Copies husky-hooks/_run.sh into the project .husky/ on install
|
|
4
|
+
* and creates missing git-hook wrappers. Does not overwrite custom hooks.
|
|
5
|
+
*/
|
|
6
|
+
import fs from 'node:fs'
|
|
7
|
+
import path from 'node:path'
|
|
8
|
+
|
|
9
|
+
const GIT_HOOKS = [
|
|
10
|
+
'pre-commit',
|
|
11
|
+
'commit-msg',
|
|
12
|
+
'prepare-commit-msg',
|
|
13
|
+
'pre-push',
|
|
14
|
+
'post-merge',
|
|
15
|
+
'post-commit',
|
|
16
|
+
'set-release-message',
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
const WRAPPER = `#!/usr/bin/env sh
|
|
20
|
+
. "$(dirname "$0")/_run.sh"
|
|
21
|
+
`
|
|
22
|
+
|
|
23
|
+
function projectRoot() {
|
|
24
|
+
const initCwd = process.env.INIT_CWD
|
|
25
|
+
if (
|
|
26
|
+
initCwd &&
|
|
27
|
+
path.isAbsolute(initCwd) &&
|
|
28
|
+
!initCwd.includes(`${path.sep}node_modules${path.sep}`)
|
|
29
|
+
) {
|
|
30
|
+
return initCwd
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const cwd = process.cwd()
|
|
34
|
+
const marker = `${path.sep}node_modules${path.sep}@itcase${path.sep}config`
|
|
35
|
+
const index = cwd.lastIndexOf(marker)
|
|
36
|
+
if (index !== -1) {
|
|
37
|
+
return cwd.slice(0, index)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return cwd
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function readHook(huskyDir, name) {
|
|
44
|
+
try {
|
|
45
|
+
return fs.readFileSync(path.join(huskyDir, name), 'utf8')
|
|
46
|
+
} catch {
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function isItcaseHuskyDir(huskyDir) {
|
|
52
|
+
if (fs.existsSync(path.join(huskyDir, '_run.sh'))) {
|
|
53
|
+
return true
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const hookContents = GIT_HOOKS.map((name) => readHook(huskyDir, name))
|
|
57
|
+
if (hookContents.some((text) => text?.includes('_run.sh'))) {
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const hasCustomHooks = hookContents.some(
|
|
62
|
+
(text) => text !== null && !text.includes('_run.sh'),
|
|
63
|
+
)
|
|
64
|
+
if (hasCustomHooks) {
|
|
65
|
+
return false
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return fs.existsSync(path.join(huskyDir, 'config'))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function writeWrapper(huskyDir, name) {
|
|
72
|
+
const dest = path.join(huskyDir, name)
|
|
73
|
+
fs.writeFileSync(dest, WRAPPER)
|
|
74
|
+
try {
|
|
75
|
+
fs.chmodSync(dest, 0o755)
|
|
76
|
+
} catch {
|
|
77
|
+
// Windows may not support chmod; Git Bash still runs the file via sh.
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const root = projectRoot()
|
|
82
|
+
const huskyDir = path.join(root, '.husky')
|
|
83
|
+
if (!fs.existsSync(huskyDir) || !isItcaseHuskyDir(huskyDir)) {
|
|
84
|
+
process.exit(0)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const src = path.join(import.meta.dirname, '_run.sh')
|
|
88
|
+
fs.copyFileSync(src, path.join(huskyDir, '_run.sh'))
|
|
89
|
+
try {
|
|
90
|
+
fs.chmodSync(path.join(huskyDir, '_run.sh'), 0o755)
|
|
91
|
+
} catch {
|
|
92
|
+
// Windows may not support chmod; Git Bash still runs the file via sh.
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
for (const name of GIT_HOOKS) {
|
|
96
|
+
const text = readHook(huskyDir, name)
|
|
97
|
+
if (text === null || text.includes('_run.sh')) {
|
|
98
|
+
writeWrapper(huskyDir, name)
|
|
99
|
+
}
|
|
100
|
+
}
|
package/husky-hooks/pre-commit
CHANGED
|
@@ -28,8 +28,9 @@ if [ -n "${PROTECTED_BRANCHES:-}" ]; then
|
|
|
28
28
|
fi
|
|
29
29
|
|
|
30
30
|
# Проверка на конфликты слияния
|
|
31
|
-
if
|
|
31
|
+
if conflict_files="$(itcase_conflict_marker_files)"; then
|
|
32
32
|
echo 'Fix conflicts'
|
|
33
|
+
printf '%s\n' "$conflict_files" | sed 's/^/ /'
|
|
33
34
|
exit 1
|
|
34
35
|
fi
|
|
35
36
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { spawnSync } from 'node:child_process'
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import path from 'node:path'
|
|
5
5
|
|
|
6
6
|
const ALLOWED_HOOKS = new Set([
|
|
7
7
|
'pre-commit',
|
|
@@ -17,14 +17,18 @@ const hookName = process.argv[2]
|
|
|
17
17
|
const hookArgs = process.argv.slice(3)
|
|
18
18
|
|
|
19
19
|
if (!hookName || !ALLOWED_HOOKS.has(hookName)) {
|
|
20
|
-
process.stderr.write(
|
|
20
|
+
process.stderr.write(
|
|
21
|
+
'Usage: itcase-config-husky-hooks <hook-name> [args...]\n',
|
|
22
|
+
)
|
|
21
23
|
process.exit(1)
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
const hookScript = path.join(
|
|
26
|
+
const hookScript = path.join(import.meta.dirname, hookName)
|
|
25
27
|
|
|
26
28
|
if (!fs.existsSync(hookScript)) {
|
|
27
|
-
process.stderr.write(
|
|
29
|
+
process.stderr.write(
|
|
30
|
+
`❌ Husky hook '${hookName}' not found in @itcase/config.\n`,
|
|
31
|
+
)
|
|
28
32
|
process.stderr.write(` Expected: ${hookScript}\n`)
|
|
29
33
|
process.exit(1)
|
|
30
34
|
}
|
|
@@ -35,7 +39,8 @@ function resolveBash() {
|
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
const candidates = [
|
|
38
|
-
process.env.PROGRAMFILES &&
|
|
42
|
+
process.env.PROGRAMFILES &&
|
|
43
|
+
path.join(process.env.PROGRAMFILES, 'Git', 'bin', 'bash.exe'),
|
|
39
44
|
process.env['PROGRAMFILES(X86)'] &&
|
|
40
45
|
path.join(process.env['PROGRAMFILES(X86)'], 'Git', 'bin', 'bash.exe'),
|
|
41
46
|
'C:\\Program Files\\Git\\bin\\bash.exe',
|
|
@@ -51,8 +56,8 @@ function resolveBash() {
|
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
const result = spawnSync(resolveBash(), [hookScript, ...hookArgs], {
|
|
54
|
-
stdio: 'inherit',
|
|
55
59
|
env: { ...process.env, HUSKY_DIR: process.env.HUSKY_DIR || '' },
|
|
60
|
+
stdio: 'inherit',
|
|
56
61
|
})
|
|
57
62
|
|
|
58
63
|
if (result.error) {
|
package/lint-staged/index.js
CHANGED
|
@@ -10,7 +10,7 @@ export default {
|
|
|
10
10
|
// Проверяем, есть ли package.json в корне репозитория
|
|
11
11
|
const rootPackageJson = resolve(process.cwd(), 'package.json')
|
|
12
12
|
if (existsSync(rootPackageJson) && files.includes(rootPackageJson)) {
|
|
13
|
-
return
|
|
13
|
+
return 'npm install --package-lock-only'
|
|
14
14
|
}
|
|
15
15
|
return 'true' // Пропускаем, если не найден
|
|
16
16
|
},
|
package/lint-staged-ts/index.js
CHANGED
|
@@ -18,7 +18,7 @@ export default {
|
|
|
18
18
|
// Проверяем, есть ли package.json в корне репозитория
|
|
19
19
|
const rootPackageJson = resolve(process.cwd(), 'package.json')
|
|
20
20
|
if (existsSync(rootPackageJson) && files.includes(rootPackageJson)) {
|
|
21
|
-
return
|
|
21
|
+
return 'npm install --package-lock-only'
|
|
22
22
|
}
|
|
23
23
|
return 'true' // Пропускаем, если не найден
|
|
24
24
|
},
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itcase/config",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.66",
|
|
4
4
|
"author": "ITCase",
|
|
5
5
|
"description": "ITCase Config",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=22.0.0"
|
|
8
8
|
},
|
|
9
9
|
"bin": {
|
|
10
|
-
"itcase-config-husky-hooks": "./husky-hooks/run.
|
|
10
|
+
"itcase-config-husky-hooks": "./husky-hooks/run.js"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"prepare": "husky",
|
|
14
|
-
"postinstall": "node ./husky-hooks/install-launcher.
|
|
14
|
+
"postinstall": "node ./husky-hooks/install-launcher.js",
|
|
15
15
|
"semantic-release": "semantic-release"
|
|
16
16
|
},
|
|
17
17
|
"type": "module",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"autoprefixer": "^10.5.4",
|
|
61
61
|
"chokidar-cli": "^3.0.0",
|
|
62
62
|
"commitizen": "^4.3.2",
|
|
63
|
-
"conventional-changelog-conventionalcommits": "
|
|
63
|
+
"conventional-changelog-conventionalcommits": "9.3.1",
|
|
64
64
|
"cssnano": "^8.0.5",
|
|
65
65
|
"cssnano-preset-default": "^8.0.5",
|
|
66
66
|
"inquirer": "^14.0.2",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"semantic-release-lerna": "^3.6.1"
|
|
106
106
|
},
|
|
107
107
|
"devDependencies": {
|
|
108
|
-
"@itcase/lint": "^1.1.
|
|
108
|
+
"@itcase/lint": "^1.1.122",
|
|
109
109
|
"eslint": "9.39.2",
|
|
110
110
|
"husky": "^9.1.7",
|
|
111
111
|
"inquirer": "^14.0.2",
|
|
@@ -113,6 +113,6 @@
|
|
|
113
113
|
"prettier": "^3.9.6",
|
|
114
114
|
"storybook": "^10.5.8",
|
|
115
115
|
"stylelint": "^17.14.1",
|
|
116
|
-
"typescript": "^6.0.
|
|
116
|
+
"typescript": "^6.0.3"
|
|
117
117
|
}
|
|
118
118
|
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Copies husky-hooks/_run.sh into the consumer .husky/ on install.
|
|
4
|
-
* Skips @itcase/config itself and repos that do not use the wrappers.
|
|
5
|
-
*/
|
|
6
|
-
const fs = require('node:fs')
|
|
7
|
-
const path = require('node:path')
|
|
8
|
-
|
|
9
|
-
const GIT_HOOKS = [
|
|
10
|
-
'pre-commit',
|
|
11
|
-
'commit-msg',
|
|
12
|
-
'prepare-commit-msg',
|
|
13
|
-
'pre-push',
|
|
14
|
-
'post-merge',
|
|
15
|
-
'post-commit',
|
|
16
|
-
'set-release-message',
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
function projectRoot() {
|
|
20
|
-
const initCwd = process.env.INIT_CWD
|
|
21
|
-
if (
|
|
22
|
-
initCwd &&
|
|
23
|
-
path.isAbsolute(initCwd) &&
|
|
24
|
-
!initCwd.includes(`${path.sep}node_modules${path.sep}`)
|
|
25
|
-
) {
|
|
26
|
-
return initCwd
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const cwd = process.cwd()
|
|
30
|
-
const marker = `${path.sep}node_modules${path.sep}@itcase${path.sep}config`
|
|
31
|
-
const index = cwd.lastIndexOf(marker)
|
|
32
|
-
if (index !== -1) {
|
|
33
|
-
return cwd.slice(0, index)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return cwd
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function packageName(root) {
|
|
40
|
-
try {
|
|
41
|
-
return JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')).name
|
|
42
|
-
} catch {
|
|
43
|
-
return ''
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function usesItcaseHooks(huskyDir) {
|
|
48
|
-
if (fs.existsSync(path.join(huskyDir, '_run.sh'))) {
|
|
49
|
-
return true
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return GIT_HOOKS.some((name) => {
|
|
53
|
-
try {
|
|
54
|
-
const text = fs.readFileSync(path.join(huskyDir, name), 'utf8')
|
|
55
|
-
return text.includes('_run.sh')
|
|
56
|
-
} catch {
|
|
57
|
-
return false
|
|
58
|
-
}
|
|
59
|
-
})
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const root = projectRoot()
|
|
63
|
-
if (packageName(root) === '@itcase/config') {
|
|
64
|
-
process.exit(0)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const huskyDir = path.join(root, '.husky')
|
|
68
|
-
if (!fs.existsSync(huskyDir) || !usesItcaseHooks(huskyDir)) {
|
|
69
|
-
process.exit(0)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const src = path.join(__dirname, '_run.sh')
|
|
73
|
-
const dest = path.join(huskyDir, '_run.sh')
|
|
74
|
-
fs.copyFileSync(src, dest)
|
|
75
|
-
try {
|
|
76
|
-
fs.chmodSync(dest, 0o755)
|
|
77
|
-
} catch {
|
|
78
|
-
// Windows may not support chmod; Git Bash still runs the file via sh.
|
|
79
|
-
}
|