@itcase/config 1.6.66 → 1.6.68

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,33 @@ 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` и создаёт недостающие обёртки хуков. Свои полные хуки не перезаписывает. Добавьте в `.gitignore`:
90
+ При каждом `npm i` в проекте нужен `prepare` (скрипт корня репозитория, не `postinstall` зависимости):
91
+
92
+ ```json
93
+ {
94
+ "scripts": {
95
+ "prepare": "husky && itcase-config-husky-install"
96
+ }
97
+ }
98
+ ```
99
+
100
+ Пока бинарь ещё не в установленной версии пакета, можно так:
101
+
102
+ ```json
103
+ {
104
+ "scripts": {
105
+ "prepare": "husky && node node_modules/@itcase/config/husky-hooks/install-launcher.js"
106
+ }
107
+ }
108
+ ```
109
+
110
+ `itcase-config-husky-install` копирует `.husky/_run.sh`, создаёт недостающие обёртки и при пустом `.husky` восстанавливает `config` из `config.example`. Свои полные хуки не перезаписывает. Добавьте в `.gitignore`:
91
111
 
92
112
  ```gitignore
93
113
  .husky/_run.sh
94
114
  ```
95
115
 
96
- Репы без обёрток и без одного только `.husky/config` скрипт не трогает. `npm i --ignore-scripts` файлы не создаст.
116
+ `npm i --ignore-scripts` файлы не создаст.
97
117
 
98
118
  В каждом git-hook оставьте обёртку:
99
119
 
@@ -111,4 +131,4 @@ PROTECTED_BRANCHES="master"
111
131
  RELEASE_BRANCHES="master"
112
132
  ```
113
133
 
114
- `prepare` в `package.json` как обычно: `"prepare": "husky"`.
134
+ `prepare` в `package.json`: `"prepare": "husky && itcase-config-husky-install"`.
@@ -21,6 +21,13 @@ const WRAPPER = `#!/usr/bin/env sh
21
21
  `
22
22
 
23
23
  function projectRoot() {
24
+ const cwd = process.cwd()
25
+ const marker = `${path.sep}node_modules${path.sep}@itcase${path.sep}config`
26
+ const index = cwd.lastIndexOf(marker)
27
+ if (index !== -1) {
28
+ return cwd.slice(0, index)
29
+ }
30
+
24
31
  const initCwd = process.env.INIT_CWD
25
32
  if (
26
33
  initCwd &&
@@ -30,13 +37,6 @@ function projectRoot() {
30
37
  return initCwd
31
38
  }
32
39
 
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
40
  return cwd
41
41
  }
42
42
 
@@ -48,29 +48,61 @@ function readHook(huskyDir, name) {
48
48
  }
49
49
  }
50
50
 
51
+ function isOldItcaseHook(text) {
52
+ if (!text || text.includes('_run.sh')) {
53
+ return false
54
+ }
55
+
56
+ return text.includes('GIT_WORKFLOW') && text.includes('/config')
57
+ }
58
+
59
+ function isEmptyHuskyDir(huskyDir) {
60
+ const names = fs
61
+ .readdirSync(huskyDir)
62
+ .filter((name) => name !== '_' && name !== '.DS_Store')
63
+ return names.length === 0
64
+ }
65
+
51
66
  function isItcaseHuskyDir(huskyDir) {
67
+ if (fs.existsSync(path.join(huskyDir, 'config'))) {
68
+ return true
69
+ }
70
+
52
71
  if (fs.existsSync(path.join(huskyDir, '_run.sh'))) {
53
72
  return true
54
73
  }
55
74
 
56
- const hookContents = GIT_HOOKS.map((name) => readHook(huskyDir, name))
57
- if (hookContents.some((text) => text?.includes('_run.sh'))) {
75
+ if (isEmptyHuskyDir(huskyDir)) {
58
76
  return true
59
77
  }
60
78
 
61
- const hasCustomHooks = hookContents.some(
62
- (text) => text !== null && !text.includes('_run.sh'),
79
+ const hookContents = GIT_HOOKS.map((name) => readHook(huskyDir, name))
80
+ return hookContents.some(
81
+ (text) => text?.includes('_run.sh') || isOldItcaseHook(text),
63
82
  )
64
- if (hasCustomHooks) {
65
- return false
66
- }
83
+ }
67
84
 
68
- return fs.existsSync(path.join(huskyDir, 'config'))
85
+ function shouldWriteWrapper(text) {
86
+ return text === null || text.includes('_run.sh') || isOldItcaseHook(text)
69
87
  }
70
88
 
71
- function writeWrapper(huskyDir, name) {
72
- const dest = path.join(huskyDir, name)
73
- fs.writeFileSync(dest, WRAPPER)
89
+ function writeExecutable(dest, contents) {
90
+ fs.writeFileSync(dest, contents)
91
+ try {
92
+ fs.chmodSync(dest, 0o755)
93
+ } catch {
94
+ // Windows may not support chmod; Git Bash still runs the file via sh.
95
+ }
96
+ }
97
+
98
+ function ensureConfig(huskyDir) {
99
+ const dest = path.join(huskyDir, 'config')
100
+ if (fs.existsSync(dest)) {
101
+ return
102
+ }
103
+
104
+ const example = path.join(import.meta.dirname, 'config.example')
105
+ fs.copyFileSync(example, dest)
74
106
  try {
75
107
  fs.chmodSync(dest, 0o755)
76
108
  } catch {
@@ -84,17 +116,14 @@ if (!fs.existsSync(huskyDir) || !isItcaseHuskyDir(huskyDir)) {
84
116
  process.exit(0)
85
117
  }
86
118
 
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
- }
119
+ writeExecutable(
120
+ path.join(huskyDir, '_run.sh'),
121
+ fs.readFileSync(path.join(import.meta.dirname, '_run.sh')),
122
+ )
123
+ ensureConfig(huskyDir)
94
124
 
95
125
  for (const name of GIT_HOOKS) {
96
- const text = readHook(huskyDir, name)
97
- if (text === null || text.includes('_run.sh')) {
98
- writeWrapper(huskyDir, name)
126
+ if (shouldWriteWrapper(readHook(huskyDir, name))) {
127
+ writeExecutable(path.join(huskyDir, name), WRAPPER)
99
128
  }
100
129
  }
package/package.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "@itcase/config",
3
- "version": "1.6.66",
3
+ "version": "1.6.68",
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.js"
10
+ "itcase-config-husky-hooks": "./husky-hooks/run.js",
11
+ "itcase-config-husky-install": "./husky-hooks/install-launcher.js"
11
12
  },
12
13
  "scripts": {
13
- "prepare": "husky",
14
+ "prepare": "husky && node ./husky-hooks/install-launcher.js",
14
15
  "postinstall": "node ./husky-hooks/install-launcher.js",
15
16
  "semantic-release": "semantic-release"
16
17
  },