@itcase/config 1.6.81 → 1.6.83
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/husky-hooks/_lib.sh +3 -2
- package/husky-hooks/pre-push +1 -1
- package/lint-staged/index.js +15 -4
- package/lint-staged-ts/index.js +16 -6
- package/package.json +1 -1
- package/smart-commit/cli.js +39 -8
package/husky-hooks/_lib.sh
CHANGED
|
@@ -48,10 +48,11 @@ itcase_conflict_marker_files() {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
itcase_run_lint_staged() {
|
|
51
|
+
# ACMR drops deletions; include D so removed files stay in the commit.
|
|
51
52
|
if [ -f "./node_modules/lint-staged/bin/lint-staged.js" ]; then
|
|
52
|
-
node ./node_modules/lint-staged/bin/lint-staged.js
|
|
53
|
+
node ./node_modules/lint-staged/bin/lint-staged.js --diff-filter=ACDMR
|
|
53
54
|
return $?
|
|
54
55
|
fi
|
|
55
56
|
|
|
56
|
-
npx lint-staged
|
|
57
|
+
npx lint-staged --diff-filter=ACDMR
|
|
57
58
|
}
|
package/husky-hooks/pre-push
CHANGED
package/lint-staged/index.js
CHANGED
|
@@ -2,10 +2,21 @@ import { existsSync } from 'node:fs'
|
|
|
2
2
|
import { resolve } from 'node:path'
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
|
-
'*.(js|jsx|ts|tsx)': (files) =>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
'*.(js|jsx|ts|tsx)': (files) => {
|
|
6
|
+
const existing = files.filter((file) => existsSync(file))
|
|
7
|
+
if (!existing.length) return 'true'
|
|
8
|
+
return `npx eslint --fix --color ${existing.join(' ')}`
|
|
9
|
+
},
|
|
10
|
+
'*.css': (files) => {
|
|
11
|
+
const existing = files.filter((file) => existsSync(file))
|
|
12
|
+
if (!existing.length) return 'true'
|
|
13
|
+
return `npx stylelint --fix --color --formatter verbose ${existing.join(' ')}`
|
|
14
|
+
},
|
|
15
|
+
'*.mdx': (files) => {
|
|
16
|
+
const existing = files.filter((file) => existsSync(file))
|
|
17
|
+
if (!existing.length) return 'true'
|
|
18
|
+
return `npx eslint --fix --color ${existing.join(' ')}`
|
|
19
|
+
},
|
|
9
20
|
'package.json': (files) => {
|
|
10
21
|
// Проверяем, есть ли package.json в корне репозитория
|
|
11
22
|
const rootPackageJson = resolve(process.cwd(), 'package.json')
|
package/lint-staged-ts/index.js
CHANGED
|
@@ -3,17 +3,27 @@ import { resolve } from 'node:path'
|
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
5
|
'*.(ts|tsx)': (files) => {
|
|
6
|
-
const
|
|
6
|
+
const existing = files.filter((file) => existsSync(file))
|
|
7
|
+
const tsFiles = existing.filter((file) => /\.(ts|tsx)$/.test(file))
|
|
7
8
|
const commands = []
|
|
8
9
|
if (tsFiles.length > 0) {
|
|
9
10
|
commands.push('tsc --noEmit --pretty')
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
if (existing.length > 0) {
|
|
13
|
+
commands.push(`npx eslint --fix ${existing.join(' ')}`)
|
|
14
|
+
}
|
|
15
|
+
return commands.length ? commands : 'true'
|
|
16
|
+
},
|
|
17
|
+
'*.css': (files) => {
|
|
18
|
+
const existing = files.filter((file) => existsSync(file))
|
|
19
|
+
if (!existing.length) return 'true'
|
|
20
|
+
return `npx stylelint --fix --color --formatter verbose ${existing.join(' ')}`
|
|
21
|
+
},
|
|
22
|
+
'*.mdx': (files) => {
|
|
23
|
+
const existing = files.filter((file) => existsSync(file))
|
|
24
|
+
if (!existing.length) return 'true'
|
|
25
|
+
return `npx eslint --fix ${existing.join(' ')}`
|
|
13
26
|
},
|
|
14
|
-
'*.css': (files) =>
|
|
15
|
-
`npx stylelint --fix --color --formatter verbose ${files.join(' ')}`,
|
|
16
|
-
'*.mdx': (files) => `npx eslint --fix ${files.join(' ')}`,
|
|
17
27
|
'package.json': (files) => {
|
|
18
28
|
// Проверяем, есть ли package.json в корне репозитория
|
|
19
29
|
const rootPackageJson = resolve(process.cwd(), 'package.json')
|
package/package.json
CHANGED
package/smart-commit/cli.js
CHANGED
|
@@ -22,6 +22,8 @@ import { getUpyachkaFrame } from './upyachka.js'
|
|
|
22
22
|
|
|
23
23
|
const PACKAGE_NAME = '@itcase/config'
|
|
24
24
|
const CLI_RELATIVE = 'smart-commit/cli.js'
|
|
25
|
+
// Cheap Cursor Models pool — commit messages do not need Auto / frontier models.
|
|
26
|
+
const DEFAULT_MODEL = 'composer-2.5'
|
|
25
27
|
|
|
26
28
|
const MAX_DIFF = 80_000
|
|
27
29
|
const LOCKFILE_NAMES = new Set([
|
|
@@ -54,6 +56,7 @@ const HELP = `smart-commit [--dry-run] [--yes|-y] [--type t] [--model id] [--ver
|
|
|
54
56
|
Cursor Agent → commit messages by SCOPES → [y/N] → git commit
|
|
55
57
|
Run via: npm exec smart-commit (from project with @itcase/config)
|
|
56
58
|
Needs: agent login (or CURSOR_API_KEY) + commitlint.config.* with SCOPES
|
|
59
|
+
Default model: ${DEFAULT_MODEL} (override with --model / SMART_COMMIT_MODEL).
|
|
57
60
|
|
|
58
61
|
Progress sprite is random (nyan cat, banana, upyachka, or Pac-Man).
|
|
59
62
|
Force with --cat, --banana, --upyachka, or --pacman. Agent log is below.
|
|
@@ -104,7 +107,7 @@ async function main(argv) {
|
|
|
104
107
|
(progress) =>
|
|
105
108
|
askAgent(
|
|
106
109
|
cwd,
|
|
107
|
-
option.model || process.env.SMART_COMMIT_MODEL ||
|
|
110
|
+
option.model || process.env.SMART_COMMIT_MODEL || DEFAULT_MODEL,
|
|
108
111
|
prompt,
|
|
109
112
|
option.verbose,
|
|
110
113
|
progress.onAgentActivity,
|
|
@@ -362,6 +365,7 @@ function listFiles(cwd, option) {
|
|
|
362
365
|
...new Set([
|
|
363
366
|
...lines(cwd, ['diff', '--cached', '--name-only', '--diff-filter=ACDMR']),
|
|
364
367
|
...lines(cwd, ['diff', '--name-only', '--diff-filter=ACDMR']),
|
|
368
|
+
...lines(cwd, ['ls-files', '--deleted']),
|
|
365
369
|
...lines(cwd, ['ls-files', '--others', '--exclude-standard']),
|
|
366
370
|
]),
|
|
367
371
|
]
|
|
@@ -395,14 +399,15 @@ Scopes (exact): ${buildScopeEnum(scopes).join(', ')}
|
|
|
395
399
|
Subject rules:
|
|
396
400
|
${promptSubjectRules.map((rule) => `- ${rule}`).join('\n')}
|
|
397
401
|
Prefer one commit when changes belong to the same feature.
|
|
398
|
-
Split by scope. Each listed file in exactly one commit — including new/untracked files (??).
|
|
402
|
+
Split by scope. Each listed file in exactly one commit — including deleted files (D) and new/untracked files (??).
|
|
399
403
|
Put each lockfile in the same commit as its sibling package.json. Do not make a lockfile-only commit.
|
|
400
404
|
Do not add Co-authored-by or Made-with trailers.
|
|
401
405
|
${type ? `Prefer type "${type}".\n` : ''}Files:
|
|
402
406
|
${files
|
|
403
407
|
.map((file) => {
|
|
404
408
|
const status =
|
|
405
|
-
statusByFile.get(file) ||
|
|
409
|
+
statusByFile.get(file) ||
|
|
410
|
+
(isUntracked(cwd, file) ? '??' : isOnDisk(cwd, file) ? ' M' : 'D')
|
|
406
411
|
const lockNote = isLockfile(file) ? ', lockfile' : ''
|
|
407
412
|
return `- ${file} (${status}${lockNote})`
|
|
408
413
|
})
|
|
@@ -1128,6 +1133,10 @@ async function validateAndNormalizePlans(cwd, plans) {
|
|
|
1128
1133
|
}
|
|
1129
1134
|
}
|
|
1130
1135
|
|
|
1136
|
+
function isOnDisk(cwd, file) {
|
|
1137
|
+
return fs.existsSync(path.join(cwd, file))
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1131
1140
|
function isTracked(cwd, file) {
|
|
1132
1141
|
return (
|
|
1133
1142
|
spawnSync('git', ['ls-files', '--error-unmatch', '--', file], {
|
|
@@ -1137,16 +1146,25 @@ function isTracked(cwd, file) {
|
|
|
1137
1146
|
)
|
|
1138
1147
|
}
|
|
1139
1148
|
|
|
1149
|
+
function isInHead(cwd, file) {
|
|
1150
|
+
return (
|
|
1151
|
+
spawnSync('git', ['cat-file', '-e', `HEAD:${file}`], {
|
|
1152
|
+
cwd: cwd,
|
|
1153
|
+
encoding: 'utf8',
|
|
1154
|
+
}).status === 0
|
|
1155
|
+
)
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1140
1158
|
function isUntracked(cwd, file) {
|
|
1141
|
-
return !isTracked(cwd, file) &&
|
|
1159
|
+
return !isTracked(cwd, file) && isOnDisk(cwd, file)
|
|
1142
1160
|
}
|
|
1143
1161
|
|
|
1144
1162
|
function fileHasChanges(cwd, file) {
|
|
1145
|
-
const
|
|
1163
|
+
const exists = isOnDisk(cwd, file)
|
|
1146
1164
|
const tracked = isTracked(cwd, file)
|
|
1147
1165
|
|
|
1148
|
-
if (!tracked) return
|
|
1149
|
-
if (!
|
|
1166
|
+
if (!exists && (tracked || isInHead(cwd, file))) return true
|
|
1167
|
+
if (!tracked) return exists
|
|
1150
1168
|
|
|
1151
1169
|
return (
|
|
1152
1170
|
spawnSync('git', ['diff', '--quiet', 'HEAD', '--', file], {
|
|
@@ -1158,7 +1176,20 @@ function fileHasChanges(cwd, file) {
|
|
|
1158
1176
|
|
|
1159
1177
|
function stageFiles(cwd, files) {
|
|
1160
1178
|
if (!files.length) return
|
|
1161
|
-
|
|
1179
|
+
|
|
1180
|
+
const existing = []
|
|
1181
|
+
const removed = []
|
|
1182
|
+
for (const file of files) {
|
|
1183
|
+
if (isOnDisk(cwd, file)) existing.push(file)
|
|
1184
|
+
else removed.push(file)
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// `git add -A -- deleted/path` warns or misses the deletion when the
|
|
1188
|
+
// parent directory is already gone. `git rm` stages the index removal.
|
|
1189
|
+
if (existing.length) git(cwd, ['add', '-A', '--', ...existing])
|
|
1190
|
+
if (removed.length) {
|
|
1191
|
+
git(cwd, ['rm', '--ignore-unmatch', '-q', '--', ...removed])
|
|
1192
|
+
}
|
|
1162
1193
|
}
|
|
1163
1194
|
|
|
1164
1195
|
async function confirm(count) {
|