@nitra/cursor 1.8.171 → 1.8.177
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/.claude-template/npm-CLAUDE.md +9 -4
- package/CHANGELOG.md +47 -0
- package/README.md +14 -0
- package/bin/auto-rules.md +3 -1
- package/mdc/changelog.mdc +64 -0
- package/mdc/k8s.mdc +57 -0
- package/mdc/npm-module.mdc +2 -6
- package/package.json +1 -1
- package/schemas/n-cursor.json +1 -1
- package/scripts/auto-rules.mjs +4 -8
- package/scripts/check-abie.mjs +17 -11
- package/scripts/check-changelog.mjs +402 -0
- package/scripts/check-docker.mjs +12 -5
- package/scripts/check-graphql.mjs +15 -9
- package/scripts/check-hasura.mjs +14 -8
- package/scripts/check-image.mjs +15 -9
- package/scripts/check-js-bun-db.mjs +25 -15
- package/scripts/check-js-mssql.mjs +27 -17
- package/scripts/check-js-run.mjs +26 -16
- package/scripts/check-k8s.mjs +131 -14
- package/scripts/check-nginx-default-tpl.mjs +26 -16
- package/scripts/check-npm-module.mjs +13 -62
- package/scripts/check-vue.mjs +27 -17
- package/scripts/rename-yaml-extensions.mjs +35 -29
- package/scripts/run-docker.mjs +11 -5
- package/scripts/run-k8s.mjs +14 -8
- package/scripts/utils/load-cursor-config.mjs +53 -0
- package/scripts/utils/walkDir.mjs +49 -8
package/scripts/check-vue.mjs
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
isVueImportScanSourceFile,
|
|
21
21
|
shouldSkipFileForVueImportScan
|
|
22
22
|
} from './utils/vue-forbidden-imports.mjs'
|
|
23
|
+
import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
|
|
23
24
|
import { walkDir } from './utils/walkDir.mjs'
|
|
24
25
|
import { getMonorepoPackageRootDirs } from './utils/workspaces.mjs'
|
|
25
26
|
|
|
@@ -113,14 +114,18 @@ async function collectEsbuildMatchesInFiles(absPackageRoot, files, maxMatches) {
|
|
|
113
114
|
* @param {(msg: string) => void} passFn callback при успішній перевірці
|
|
114
115
|
* @param {(msg: string) => void} fail callback при помилці
|
|
115
116
|
*/
|
|
116
|
-
async function checkEsbuildMentions(rootDir, absPackageRoot, prefix, passFn, fail) {
|
|
117
|
+
async function checkEsbuildMentions(rootDir, absPackageRoot, ignorePaths, prefix, passFn, fail) {
|
|
117
118
|
/** @type {{ rel: string }[]} */
|
|
118
119
|
const candidates = []
|
|
119
|
-
await walkDir(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
await walkDir(
|
|
121
|
+
absPackageRoot,
|
|
122
|
+
absPath => {
|
|
123
|
+
const rel = relative(absPackageRoot, absPath).split('\\').join('/')
|
|
124
|
+
if (!isEsbuildScanFile(rel)) return
|
|
125
|
+
candidates.push({ rel })
|
|
126
|
+
},
|
|
127
|
+
ignorePaths
|
|
128
|
+
)
|
|
124
129
|
|
|
125
130
|
const maxMatches = 30
|
|
126
131
|
const matches = await collectEsbuildMatchesInFiles(absPackageRoot, candidates, maxMatches)
|
|
@@ -308,7 +313,7 @@ async function checkViteConfig(rootDir, prefix, passFn, fail) {
|
|
|
308
313
|
* @param {(msg: string) => void} passFn callback при успішній перевірці
|
|
309
314
|
* @param {(msg: string) => void} fail callback при помилці
|
|
310
315
|
*/
|
|
311
|
-
async function checkVueImportViolations(rootDir, absPackageRoot, hasVueAutoImport, prefix, passFn, fail) {
|
|
316
|
+
async function checkVueImportViolations(rootDir, absPackageRoot, ignorePaths, hasVueAutoImport, prefix, passFn, fail) {
|
|
312
317
|
if (!hasVueAutoImport) {
|
|
313
318
|
passFn(
|
|
314
319
|
`${prefix}value-імпорти з 'vue' не заборонені — спершу додай 'vue' до AutoImport.imports у vite.config`
|
|
@@ -317,12 +322,16 @@ async function checkVueImportViolations(rootDir, absPackageRoot, hasVueAutoImpor
|
|
|
317
322
|
}
|
|
318
323
|
/** @type {string[]} */
|
|
319
324
|
const sourcePaths = []
|
|
320
|
-
await walkDir(
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
325
|
+
await walkDir(
|
|
326
|
+
absPackageRoot,
|
|
327
|
+
absPath => {
|
|
328
|
+
const rel = relative(absPackageRoot, absPath).split('\\').join('/')
|
|
329
|
+
if (!shouldSkipFileForVueImportScan(rel) && isVueImportScanSourceFile(rel)) {
|
|
330
|
+
sourcePaths.push(absPath)
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
ignorePaths
|
|
334
|
+
)
|
|
326
335
|
|
|
327
336
|
let importViolations = 0
|
|
328
337
|
for (const absPath of sourcePaths) {
|
|
@@ -347,7 +356,7 @@ async function checkVueImportViolations(rootDir, absPackageRoot, hasVueAutoImpor
|
|
|
347
356
|
* @param {(msg: string) => void} passFn успішне повідомлення (як у check-reporter)
|
|
348
357
|
* @returns {Promise<void>} завершується після перевірок залежностей, `vite.config` і сканування джерел на імпорти з `vue`
|
|
349
358
|
*/
|
|
350
|
-
async function checkVuePackage(rootDir, fail, passFn) {
|
|
359
|
+
async function checkVuePackage(rootDir, ignorePaths, fail, passFn) {
|
|
351
360
|
const prefix = `[${packageLabel(rootDir)}] `
|
|
352
361
|
const pkg = JSON.parse(await readFile(join(rootDir, 'package.json'), 'utf8'))
|
|
353
362
|
const deps = pkg.dependencies || {}
|
|
@@ -387,8 +396,8 @@ async function checkVuePackage(rootDir, fail, passFn) {
|
|
|
387
396
|
)
|
|
388
397
|
|
|
389
398
|
const { hasVueAutoImport } = await checkViteConfig(rootDir, prefix, passFn, fail)
|
|
390
|
-
await checkVueImportViolations(rootDir, join(process.cwd(), rootDir), hasVueAutoImport, prefix, passFn, fail)
|
|
391
|
-
await checkEsbuildMentions(rootDir, join(process.cwd(), rootDir), prefix, passFn, fail)
|
|
399
|
+
await checkVueImportViolations(rootDir, join(process.cwd(), rootDir), ignorePaths, hasVueAutoImport, prefix, passFn, fail)
|
|
400
|
+
await checkEsbuildMentions(rootDir, join(process.cwd(), rootDir), ignorePaths, prefix, passFn, fail)
|
|
392
401
|
}
|
|
393
402
|
|
|
394
403
|
/**
|
|
@@ -446,8 +455,9 @@ export async function check() {
|
|
|
446
455
|
|
|
447
456
|
await checkVueVolarRecommendation(pass, fail)
|
|
448
457
|
|
|
458
|
+
const ignorePaths = await loadCursorIgnorePaths(process.cwd())
|
|
449
459
|
for (const r of vueRoots) {
|
|
450
|
-
await checkVuePackage(r, fail, pass)
|
|
460
|
+
await checkVuePackage(r, ignorePaths, fail, pass)
|
|
451
461
|
}
|
|
452
462
|
|
|
453
463
|
return reporter.getExitCode()
|
|
@@ -14,6 +14,7 @@ import { rename } from 'node:fs/promises'
|
|
|
14
14
|
import { cwd } from 'node:process'
|
|
15
15
|
import { relative, resolve } from 'node:path'
|
|
16
16
|
|
|
17
|
+
import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
|
|
17
18
|
import { walkDir } from './utils/walkDir.mjs'
|
|
18
19
|
|
|
19
20
|
const K8S_YML_RE = /\.yml$/iu
|
|
@@ -69,37 +70,41 @@ export function replaceExtension(relPosix, newExt) {
|
|
|
69
70
|
* @param {string} rootAbs абсолютний корінь репозиторію
|
|
70
71
|
* @returns {Promise<Array<{ kind: 'k8s' | 'github', fromAbs: string, toAbs: string, relFrom: string, relTo: string }>>} відсортовані операції перейменування без запису на диск
|
|
71
72
|
*/
|
|
72
|
-
async function collectRenameOps(rootAbs) {
|
|
73
|
+
async function collectRenameOps(rootAbs, ignorePaths) {
|
|
73
74
|
/** @type {Array<{ kind: 'k8s' | 'github', fromAbs: string, toAbs: string, relFrom: string, relTo: string }>} */
|
|
74
75
|
const ops = []
|
|
75
76
|
|
|
76
|
-
await walkDir(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
77
|
+
await walkDir(
|
|
78
|
+
rootAbs,
|
|
79
|
+
fileAbs => {
|
|
80
|
+
const rel = posixRelFromRoot(rootAbs, fileAbs)
|
|
81
|
+
if (rel === null) return
|
|
82
|
+
if (pathMatchesK8sYml(rel)) {
|
|
83
|
+
const relTo = replaceExtension(rel, '.yaml')
|
|
84
|
+
if (relTo === rel) return
|
|
85
|
+
ops.push({
|
|
86
|
+
kind: 'k8s',
|
|
87
|
+
fromAbs: resolve(rootAbs, rel),
|
|
88
|
+
toAbs: resolve(rootAbs, relTo),
|
|
89
|
+
relFrom: rel,
|
|
90
|
+
relTo
|
|
91
|
+
})
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
if (pathMatchesGithubYaml(rel)) {
|
|
95
|
+
const relTo = replaceExtension(rel, '.yml')
|
|
96
|
+
if (relTo === rel) return
|
|
97
|
+
ops.push({
|
|
98
|
+
kind: 'github',
|
|
99
|
+
fromAbs: resolve(rootAbs, rel),
|
|
100
|
+
toAbs: resolve(rootAbs, relTo),
|
|
101
|
+
relFrom: rel,
|
|
102
|
+
relTo
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
ignorePaths
|
|
107
|
+
)
|
|
103
108
|
|
|
104
109
|
ops.sort((a, b) => {
|
|
105
110
|
const ko = (a.kind === 'k8s' ? 0 : 1) - (b.kind === 'k8s' ? 0 : 1)
|
|
@@ -119,7 +124,8 @@ async function collectRenameOps(rootAbs) {
|
|
|
119
124
|
export async function renameYamlExtensions(root, options = {}) {
|
|
120
125
|
const dryRun = options.dryRun === true
|
|
121
126
|
const rootAbs = resolve(root)
|
|
122
|
-
const
|
|
127
|
+
const ignorePaths = await loadCursorIgnorePaths(rootAbs)
|
|
128
|
+
const ops = await collectRenameOps(rootAbs, ignorePaths)
|
|
123
129
|
|
|
124
130
|
/** @type { { relFrom: string, relTo: string }[]} */
|
|
125
131
|
const renamed = []
|
package/scripts/run-docker.mjs
CHANGED
|
@@ -12,6 +12,7 @@ import { basename } from 'node:path'
|
|
|
12
12
|
import { isRunAsCli } from './cli-entry.mjs'
|
|
13
13
|
import { lintDockerfileWithHadolint, posixRel } from './utils/docker-hadolint.mjs'
|
|
14
14
|
import { createCheckReporter } from './utils/check-reporter.mjs'
|
|
15
|
+
import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
|
|
15
16
|
import { walkDir } from './utils/walkDir.mjs'
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -30,12 +31,16 @@ export function isLintDockerfileName(name) {
|
|
|
30
31
|
* @param {string} root корінь репозиторію
|
|
31
32
|
* @returns {Promise<string[]>} відсортовані абсолютні шляхи
|
|
32
33
|
*/
|
|
33
|
-
export async function findLintDockerfilePaths(root) {
|
|
34
|
+
export async function findLintDockerfilePaths(root, ignorePaths = []) {
|
|
34
35
|
/** @type {string[]} */
|
|
35
36
|
const out = []
|
|
36
|
-
await walkDir(
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
await walkDir(
|
|
38
|
+
root,
|
|
39
|
+
p => {
|
|
40
|
+
if (isLintDockerfileName(basename(p))) out.push(p)
|
|
41
|
+
},
|
|
42
|
+
ignorePaths
|
|
43
|
+
)
|
|
39
44
|
return out.toSorted((a, b) => a.localeCompare(b))
|
|
40
45
|
}
|
|
41
46
|
|
|
@@ -48,7 +53,8 @@ async function main() {
|
|
|
48
53
|
const { pass, fail } = reporter
|
|
49
54
|
|
|
50
55
|
const root = process.cwd()
|
|
51
|
-
const
|
|
56
|
+
const ignorePaths = await loadCursorIgnorePaths(root)
|
|
57
|
+
const files = await findLintDockerfilePaths(root, ignorePaths)
|
|
52
58
|
|
|
53
59
|
if (files.length === 0) {
|
|
54
60
|
pass('lint-docker: немає Dockerfile / *.Dockerfile — hadolint пропущено')
|
package/scripts/run-k8s.mjs
CHANGED
|
@@ -16,6 +16,7 @@ import { spawnSync } from 'node:child_process'
|
|
|
16
16
|
import { basename, dirname } from 'node:path'
|
|
17
17
|
|
|
18
18
|
import { isRunAsCli } from './cli-entry.mjs'
|
|
19
|
+
import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
|
|
19
20
|
import { resolveCmd } from './utils/resolve-cmd.mjs'
|
|
20
21
|
import { walkDir } from './utils/walkDir.mjs'
|
|
21
22
|
|
|
@@ -60,15 +61,19 @@ export function k8sRootFromFile(absFile) {
|
|
|
60
61
|
* @param {string} root корінь репозиторію
|
|
61
62
|
* @returns {Promise<string[]>} відсортовані абсолютні шляхи до каталогів `k8s`
|
|
62
63
|
*/
|
|
63
|
-
export async function findK8sRoots(root) {
|
|
64
|
+
export async function findK8sRoots(root, ignorePaths = []) {
|
|
64
65
|
/** @type {Set<string>} */
|
|
65
66
|
const roots = new Set()
|
|
66
|
-
await walkDir(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
await walkDir(
|
|
68
|
+
root,
|
|
69
|
+
p => {
|
|
70
|
+
if (!pathHasK8sSegment(p)) return
|
|
71
|
+
if (!YAML_EXT_RE.test(p)) return
|
|
72
|
+
const k8sRoot = k8sRootFromFile(p)
|
|
73
|
+
if (k8sRoot) roots.add(k8sRoot)
|
|
74
|
+
},
|
|
75
|
+
ignorePaths
|
|
76
|
+
)
|
|
72
77
|
return [...roots].toSorted((a, b) => a.localeCompare(b))
|
|
73
78
|
}
|
|
74
79
|
|
|
@@ -134,7 +139,8 @@ function runKubescape(dirs) {
|
|
|
134
139
|
*/
|
|
135
140
|
async function main() {
|
|
136
141
|
const root = process.cwd()
|
|
137
|
-
const
|
|
142
|
+
const ignorePaths = await loadCursorIgnorePaths(root)
|
|
143
|
+
const dirs = await findK8sRoots(root, ignorePaths)
|
|
138
144
|
|
|
139
145
|
if (dirs.length === 0) {
|
|
140
146
|
console.log('run-k8s: немає *.yaml під k8s — kubeconform і kubescape пропущено')
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Утиліта читання `.n-cursor.json` у корені репозиторію.
|
|
3
|
+
*
|
|
4
|
+
* Зараз експортує `loadCursorIgnorePaths(root)` — список абсолютних posix-шляхів каталогів,
|
|
5
|
+
* які check-скрипти повністю виключають з обходу (поле `ignore` у конфізі).
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync } from 'node:fs'
|
|
8
|
+
import { readFile } from 'node:fs/promises'
|
|
9
|
+
import { isAbsolute, join, resolve, sep } from 'node:path'
|
|
10
|
+
|
|
11
|
+
const CONFIG_FILE = '.n-cursor.json'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Нормалізує шлях до абсолютного posix-формату без trailing-slash.
|
|
15
|
+
* Відносні шляхи розв'язуються від `root`.
|
|
16
|
+
* @param {string} root абсолютний корінь репозиторію
|
|
17
|
+
* @param {string} p шлях з конфігу (відносний або абсолютний)
|
|
18
|
+
* @returns {string} абсолютний posix-шлях
|
|
19
|
+
*/
|
|
20
|
+
function toAbsPosix(root, p) {
|
|
21
|
+
const trimmed = String(p).trim()
|
|
22
|
+
const abs = isAbsolute(trimmed) ? trimmed : resolve(root, trimmed)
|
|
23
|
+
return abs.split(sep).join('/').replace(/\/+$/, '')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Читає `.n-cursor.json` з кореня та повертає нормалізовані ignore-шляхи.
|
|
28
|
+
* Якщо файлу нема, поле `ignore` відсутнє чи має невалідний формат — повертає порожній масив.
|
|
29
|
+
* Сам конфіг не валідується (це робить v8r/окрема перевірка) — лише поле `ignore`.
|
|
30
|
+
* @param {string} root абсолютний корінь репозиторію
|
|
31
|
+
* @returns {Promise<string[]>} абсолютні posix-шляхи без trailing-slash
|
|
32
|
+
*/
|
|
33
|
+
export async function loadCursorIgnorePaths(root) {
|
|
34
|
+
const file = join(root, CONFIG_FILE)
|
|
35
|
+
if (!existsSync(file)) return []
|
|
36
|
+
let raw
|
|
37
|
+
try {
|
|
38
|
+
raw = JSON.parse(await readFile(file, 'utf8'))
|
|
39
|
+
} catch {
|
|
40
|
+
return []
|
|
41
|
+
}
|
|
42
|
+
const list = raw?.ignore
|
|
43
|
+
if (!Array.isArray(list)) return []
|
|
44
|
+
/** @type {string[]} */
|
|
45
|
+
const out = []
|
|
46
|
+
for (const item of list) {
|
|
47
|
+
if (typeof item !== 'string') continue
|
|
48
|
+
const v = item.trim()
|
|
49
|
+
if (v.length === 0) continue
|
|
50
|
+
out.push(toAbsPosix(root, v))
|
|
51
|
+
}
|
|
52
|
+
return out
|
|
53
|
+
}
|
|
@@ -2,19 +2,60 @@
|
|
|
2
2
|
* Рекурсивний обхід каталогів для скриптів перевірки (Dockerfile, k8s YAML тощо).
|
|
3
3
|
*
|
|
4
4
|
* Обходить дерево від заданого кореня; для кожного звичайного файлу викликає переданий callback.
|
|
5
|
-
* Каталоги node_modules, .git, dist, coverage, .turbo, .next не заходяться.
|
|
6
|
-
*
|
|
5
|
+
* Каталоги node_modules, .git, dist, coverage, .turbo, .next не заходяться.
|
|
6
|
+
* Додатково можна передати `ignorePaths` — повні шляхи каталогів (абсолютні posix), які слід
|
|
7
|
+
* пропускати разом з усім вмістом (поле `ignore` у `.n-cursor.json`). Якщо readdir для каталогу
|
|
8
|
+
* не вдається — тихо виходить без throw.
|
|
7
9
|
*/
|
|
8
10
|
import { readdir } from 'node:fs/promises'
|
|
9
|
-
import { join } from 'node:path'
|
|
11
|
+
import { isAbsolute, join, resolve, sep } from 'node:path'
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
|
-
*
|
|
14
|
+
* Перетворює довільний шлях у абсолютний posix-формат без trailing-slash.
|
|
15
|
+
* @param {string} p шлях
|
|
16
|
+
* @returns {string} абсолютний posix-шлях
|
|
17
|
+
*/
|
|
18
|
+
function toAbsPosix(p) {
|
|
19
|
+
const abs = isAbsolute(p) ? p : resolve(p)
|
|
20
|
+
return abs.split(sep).join('/').replace(/\/+$/, '')
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Чи каталог `dirAbsPosix` входить у список ignore (точний збіг або префікс з '/').
|
|
25
|
+
* Часткові збіги басенейму не враховуються (postgres-master-test ≠ postgres-master).
|
|
26
|
+
* @param {string} dirAbsPosix абсолютний posix-шлях каталогу
|
|
27
|
+
* @param {string[]} ignorePosix вже нормалізовані ignore-шляхи
|
|
28
|
+
* @returns {boolean}
|
|
29
|
+
*/
|
|
30
|
+
function isIgnoredDir(dirAbsPosix, ignorePosix) {
|
|
31
|
+
for (const ig of ignorePosix) {
|
|
32
|
+
if (dirAbsPosix === ig) return true
|
|
33
|
+
if (dirAbsPosix.startsWith(`${ig}/`)) return true
|
|
34
|
+
}
|
|
35
|
+
return false
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Рекурсивно обходить каталог, пропускає типові артефакти збірки/залежностей та `ignorePaths`.
|
|
13
40
|
* @param {string} dir абсолютний шлях
|
|
14
41
|
* @param {(filePath: string) => void} onFile виклик для кожного файлу
|
|
42
|
+
* @param {string[]} [ignorePaths=[]] шляхи каталогів (відносні від cwd або абсолютні), що повністю виключаються з обходу
|
|
43
|
+
* @returns {Promise<void>}
|
|
44
|
+
*/
|
|
45
|
+
export async function walkDir(dir, onFile, ignorePaths = []) {
|
|
46
|
+
const ignorePosix = ignorePaths.map(toAbsPosix)
|
|
47
|
+
await walkDirInner(dir, onFile, ignorePosix)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Внутрішній рекурсор. ignorePosix вже нормалізовано — не нормалізуємо повторно на кожному рівні.
|
|
52
|
+
* @param {string} dir
|
|
53
|
+
* @param {(filePath: string) => void} onFile
|
|
54
|
+
* @param {string[]} ignorePosix
|
|
15
55
|
* @returns {Promise<void>}
|
|
16
56
|
*/
|
|
17
|
-
|
|
57
|
+
async function walkDirInner(dir, onFile, ignorePosix) {
|
|
58
|
+
if (ignorePosix.length > 0 && isIgnoredDir(toAbsPosix(dir), ignorePosix)) return
|
|
18
59
|
let entries
|
|
19
60
|
try {
|
|
20
61
|
entries = await readdir(dir, { withFileTypes: true })
|
|
@@ -31,9 +72,9 @@ export async function walkDir(dir, onFile) {
|
|
|
31
72
|
e.name === 'coverage' ||
|
|
32
73
|
e.name === '.turbo' ||
|
|
33
74
|
e.name === '.next'
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
75
|
+
if (skipDir) continue
|
|
76
|
+
if (ignorePosix.length > 0 && isIgnoredDir(toAbsPosix(p), ignorePosix)) continue
|
|
77
|
+
await walkDirInner(p, onFile, ignorePosix)
|
|
37
78
|
} else if (e.isFile()) {
|
|
38
79
|
onFile(p)
|
|
39
80
|
}
|