@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 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` пакет сам копирует `.husky/_run.sh` (git его не вызывает). Добавьте в `.gitignore`:
90
+ При `npm i` пакет копирует `.husky/_run.sh` и создаёт недостающие обёртки хуков. Свои полные хуки не перезаписывает. Добавьте в `.gitignore`:
91
91
 
92
92
  ```gitignore
93
93
  .husky/_run.sh
94
94
  ```
95
95
 
96
- Скрипт не трогает `.husky` самого `@itcase/config` и репы без обёрток. `npm i --ignore-scripts` файл не создаст.
96
+ Репы без обёрток и без одного только `.husky/config` скрипт не трогает. `npm i --ignore-scripts` файлы не создаст.
97
97
 
98
98
  В каждом git-hook оставьте обёртку:
99
99
 
@@ -41,10 +41,10 @@ itcase_export_release_branch_env() {
41
41
  fi
42
42
  }
43
43
 
44
- itcase_has_conflict_markers() {
45
- git grep -I --untracked --exclude-standard \
44
+ itcase_conflict_marker_files() {
45
+ git grep -lI --untracked --exclude-standard \
46
46
  -e '^<<<<<<< ' -e '^=======$' -e '^>>>>>>> ' \
47
- -- . ':!node_modules' ':!dist' >/dev/null 2>&1
47
+ -- . ':!node_modules' ':!dist' 2>/dev/null
48
48
  }
49
49
 
50
50
  itcase_run_lint_staged() {
@@ -9,8 +9,9 @@ fi
9
9
 
10
10
  ROOT="$(CDPATH= cd -- "$HUSKY_DIR/.." && pwd)"
11
11
  for candidate in \
12
- "$ROOT/node_modules/@itcase/config/husky-hooks/run.cjs" \
13
- "$ROOT/../itcase-config/husky-hooks/run.cjs"
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
+ }
@@ -28,8 +28,9 @@ if [ -n "${PROTECTED_BRANCHES:-}" ]; then
28
28
  fi
29
29
 
30
30
  # Проверка на конфликты слияния
31
- if itcase_has_conflict_markers; then
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
- const { spawnSync } = require('node:child_process')
3
- const fs = require('node:fs')
4
- const path = require('node:path')
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('Usage: itcase-config-husky-hooks <hook-name> [args...]\n')
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(__dirname, hookName)
26
+ const hookScript = path.join(import.meta.dirname, hookName)
25
27
 
26
28
  if (!fs.existsSync(hookScript)) {
27
- process.stderr.write(`❌ Husky hook '${hookName}' not found in @itcase/config.\n`)
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 && path.join(process.env.PROGRAMFILES, 'Git', 'bin', 'bash.exe'),
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) {
@@ -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 ['npm install --package-lock-only', 'git add package-lock.json']
13
+ return 'npm install --package-lock-only'
14
14
  }
15
15
  return 'true' // Пропускаем, если не найден
16
16
  },
@@ -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 ['npm install --package-lock-only', 'git add package-lock.json']
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.64",
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.cjs"
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.cjs",
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": "^10.3.0",
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.121",
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.2"
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
- }