@7n/rules-lang-js 0.3.1 → 0.4.0
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/CHANGELOG.md +6 -0
- package/package.json +14 -4
- package/rules/bun/bunfig/bunfig.mdc +17 -0
- package/rules/bun/bunfig/bunfig.rego +29 -0
- package/rules/bun/bunfig/concern.json +9 -0
- package/rules/bun/bunfig/template/bunfig.toml.snippet.toml +2 -0
- package/rules/bun/docs/index.md +11 -0
- package/rules/bun/layout/concern.json +16 -0
- package/rules/bun/layout/docs/fix-layout.md +29 -0
- package/rules/bun/layout/docs/main.md +34 -0
- package/rules/bun/layout/fix-layout.mjs +63 -0
- package/rules/bun/layout/layout.mdc +60 -0
- package/rules/bun/layout/main.mjs +53 -0
- package/rules/bun/licensee/concern.json +7 -0
- package/rules/bun/licensee/docs/fix-licensee.md +27 -0
- package/rules/bun/licensee/docs/index.md +12 -0
- package/rules/bun/licensee/docs/main.md +30 -0
- package/rules/bun/licensee/fix-licensee.mjs +31 -0
- package/rules/bun/licensee/main.mjs +68 -0
- package/rules/bun/lint-surface/concern.json +3 -0
- package/rules/bun/lint-surface/lint-surface.mdc +13 -0
- package/rules/bun/main.json +1 -0
- package/rules/bun/main.mdc +11 -0
- package/rules/bun/package_json/concern.json +9 -0
- package/rules/bun/package_json/docs/fix-package_json.md +28 -0
- package/rules/bun/package_json/docs/index.md +9 -0
- package/rules/bun/package_json/fix-package_json.mjs +311 -0
- package/rules/bun/package_json/package_json.mdc +14 -0
- package/rules/bun/package_json/package_json.rego +64 -0
- package/rules/bun/package_json/template/package.json.deny.json +4 -0
- package/rules/js/check/check.mdc +26 -0
- package/rules/js/check/concern.json +19 -0
- package/rules/js/check/docs/eslint-config.md +56 -0
- package/rules/js/check/docs/fix-check.md +48 -0
- package/rules/js/check/docs/index.md +13 -0
- package/rules/js/check/docs/main.md +48 -0
- package/rules/js/check/eslint-config.mjs +262 -0
- package/rules/js/check/fix-check.mjs +82 -0
- package/rules/js/check/main.mjs +310 -0
- package/rules/js/dep-policy/concern.json +4 -0
- package/rules/js/dep-policy/dep-policy.mdc +36 -0
- package/rules/js/dep-policy/docs/main.md +35 -0
- package/rules/js/dep-policy/main.mjs +99 -0
- package/rules/js/docs/index.md +11 -0
- package/rules/js/eslint/concern.json +8 -0
- package/rules/js/eslint/docs/fix-eslint.md +50 -0
- package/rules/js/eslint/docs/fix-worker.md +31 -0
- package/rules/js/eslint/docs/index.md +11 -0
- package/rules/js/eslint/docs/main.md +35 -0
- package/rules/js/eslint/fix-eslint.mjs +160 -0
- package/rules/js/eslint/fix-worker.mjs +139 -0
- package/rules/js/eslint/main.mjs +115 -0
- package/rules/js/file-extensions/concern.json +3 -0
- package/rules/js/file-extensions/file-extensions.mdc +12 -0
- package/rules/js/jscpd_config/concern.json +11 -0
- package/rules/js/jscpd_config/docs/fix-jscpd_config.md +25 -0
- package/rules/js/jscpd_config/docs/index.md +9 -0
- package/rules/js/jscpd_config/fix-jscpd_config.mjs +3 -0
- package/rules/js/jscpd_config/jscpd_config.mdc +42 -0
- package/rules/js/jscpd_config/jscpd_config.rego +44 -0
- package/rules/js/jscpd_config/template/.jscpd.json.snippet.json +7 -0
- package/rules/js/jscpd_duplicates/concern.json +7 -0
- package/rules/js/jscpd_duplicates/docs/main.md +29 -0
- package/rules/js/jscpd_duplicates/main.mjs +69 -0
- package/rules/js/knip/concern.json +7 -0
- package/rules/js/knip/docs/main.md +32 -0
- package/rules/js/knip/knip.mdc +15 -0
- package/rules/js/knip/main.mjs +68 -0
- package/rules/js/lint-findings/concern.json +3 -0
- package/rules/js/lint-findings/docs/main.md +40 -0
- package/rules/js/lint-findings/main.mjs +125 -0
- package/rules/js/main.json +1 -0
- package/rules/js/main.mdc +18 -0
- package/rules/js/package_json/concern.json +9 -0
- package/rules/js/package_json/docs/fix-package_json.md +25 -0
- package/rules/js/package_json/docs/index.md +9 -0
- package/rules/js/package_json/fix-package_json.mjs +3 -0
- package/rules/js/package_json/package_json.mdc +15 -0
- package/rules/js/package_json/package_json.rego +142 -0
- package/rules/js/package_json/template/package.json.snippet.json +6 -0
- package/rules/js/tooling/concern.json +3 -0
- package/rules/js/tooling/data/tooling/knip-canonical.json +30 -0
- package/rules/js/tooling/data/tooling/oxlint-canonical.json +400 -0
- package/rules/js/tooling/docs/main.md +53 -0
- package/rules/js/tooling/main.mjs +183 -0
- package/rules/js/utils_imports/concern.json +4 -0
- package/rules/js/utils_imports/docs/main.md +50 -0
- package/rules/js/utils_imports/main.mjs +185 -0
- package/rules/js/utils_imports/utils_imports.mdc +15 -0
- package/rules/js/vscode_extensions/concern.json +11 -0
- package/rules/js/vscode_extensions/docs/fix-vscode_extensions.md +24 -0
- package/rules/js/vscode_extensions/docs/index.md +11 -0
- package/rules/js/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/js/vscode_extensions/template/extensions.json.snippet.json +6 -0
- package/rules/js/vscode_extensions/vscode_extensions.mdc +11 -0
- package/rules/js/vscode_extensions/vscode_extensions.rego +12 -0
- package/rules/js-bun-db/connection/concern.json +3 -0
- package/rules/js-bun-db/connection/connection.mdc +42 -0
- package/rules/js-bun-db/docs/index.md +11 -0
- package/rules/js-bun-db/lib/bun-sql-scan.mjs +1047 -0
- package/rules/js-bun-db/lib/docs/bun-sql-scan.md +63 -0
- package/rules/js-bun-db/lib/docs/index.md +11 -0
- package/rules/js-bun-db/main.json +1 -0
- package/rules/js-bun-db/main.mdc +8 -0
- package/rules/js-bun-db/package_json/concern.json +9 -0
- package/rules/js-bun-db/package_json/package_json.mdc +31 -0
- package/rules/js-bun-db/package_json/package_json.rego +15 -0
- package/rules/js-bun-db/package_json/template/package.json.deny.json +6 -0
- package/rules/js-bun-db/pg_format_identifiers/concern.json +3 -0
- package/rules/js-bun-db/pg_format_identifiers/pg_format_identifiers.mdc +104 -0
- package/rules/js-bun-db/safety/concern.json +4 -0
- package/rules/js-bun-db/safety/docs/main.md +34 -0
- package/rules/js-bun-db/safety/main.mjs +430 -0
- package/rules/js-bun-db/safety/safety.mdc +458 -0
- package/rules/js-bun-redis/docs/index.md +11 -0
- package/rules/js-bun-redis/imports/concern.json +4 -0
- package/rules/js-bun-redis/imports/docs/main.md +36 -0
- package/rules/js-bun-redis/imports/imports.mdc +47 -0
- package/rules/js-bun-redis/imports/main.mjs +88 -0
- package/rules/js-bun-redis/lib/docs/index.md +11 -0
- package/rules/js-bun-redis/lib/docs/redis-imports.md +227 -0
- package/rules/js-bun-redis/lib/redis-imports.mjs +130 -0
- package/rules/js-bun-redis/main.json +1 -0
- package/rules/js-bun-redis/main.mdc +8 -0
- package/rules/js-bun-redis/package_json/concern.json +9 -0
- package/rules/js-bun-redis/package_json/package_json.mdc +11 -0
- package/rules/js-bun-redis/package_json/package_json.rego +15 -0
- package/rules/js-bun-redis/package_json/template/package.json.deny.json +12 -0
- package/rules/js-mssql/deps/concern.json +4 -0
- package/rules/js-mssql/deps/docs/main.md +33 -0
- package/rules/js-mssql/deps/main.mjs +297 -0
- package/rules/js-mssql/docs/index.md +11 -0
- package/rules/js-mssql/lib/docs/index.md +11 -0
- package/rules/js-mssql/lib/docs/mssql-pool-scan.md +380 -0
- package/rules/js-mssql/lib/mssql-pool-scan.mjs +610 -0
- package/rules/js-mssql/main.json +1 -0
- package/rules/js-mssql/main.mdc +144 -0
- package/rules/js-mssql/mssql-tvp/concern.json +3 -0
- package/rules/js-mssql/mssql-tvp/mssql-tvp.mdc +77 -0
- package/rules/js-mssql/package_json/concern.json +9 -0
- package/rules/js-mssql/package_json/package_json.mdc +9 -0
- package/rules/js-mssql/package_json/package_json.rego +57 -0
- package/rules/js-run/configmap/concern.json +9 -0
- package/rules/js-run/configmap/configmap.mdc +37 -0
- package/rules/js-run/configmap/configmap.rego +21 -0
- package/rules/js-run/configmap/template/configmap.yaml.contains.yml +4 -0
- package/rules/js-run/docs/index.md +11 -0
- package/rules/js-run/jsconfig/concern.json +9 -0
- package/rules/js-run/jsconfig/docs/fix-jsconfig.md +28 -0
- package/rules/js-run/jsconfig/docs/index.md +9 -0
- package/rules/js-run/jsconfig/fix-jsconfig.mjs +119 -0
- package/rules/js-run/jsconfig/jsconfig.mdc +48 -0
- package/rules/js-run/jsconfig/jsconfig.rego +59 -0
- package/rules/js-run/jsconfig/template/jsconfig.json.snippet.json +10 -0
- package/rules/js-run/lib/bunyan-imports.mjs +98 -0
- package/rules/js-run/lib/check-env-scan.mjs +338 -0
- package/rules/js-run/lib/conn-file-rules.mjs +214 -0
- package/rules/js-run/lib/conn-imports-scan.mjs +154 -0
- package/rules/js-run/lib/docs/bunyan-imports.md +121 -0
- package/rules/js-run/lib/docs/check-env-scan.md +438 -0
- package/rules/js-run/lib/docs/conn-file-rules.md +304 -0
- package/rules/js-run/lib/docs/conn-imports-scan.md +208 -0
- package/rules/js-run/lib/docs/index.md +16 -0
- package/rules/js-run/lib/docs/promise-settimeout-scan.md +334 -0
- package/rules/js-run/lib/docs/temporal-scan.md +29 -0
- package/rules/js-run/lib/promise-settimeout-scan.mjs +128 -0
- package/rules/js-run/lib/temporal-scan.mjs +52 -0
- package/rules/js-run/main.json +1 -0
- package/rules/js-run/main.mdc +16 -0
- package/rules/js-run/package_json/concern.json +9 -0
- package/rules/js-run/package_json/package_json.mdc +44 -0
- package/rules/js-run/package_json/package_json.rego +37 -0
- package/rules/js-run/package_json/template/package.json.deny.json +22 -0
- package/rules/js-run/project-structure/concern.json +3 -0
- package/rules/js-run/project-structure/project-structure.mdc +11 -0
- package/rules/js-run/runtime/concern.json +12 -0
- package/rules/js-run/runtime/docs/fix-runtime.md +27 -0
- package/rules/js-run/runtime/docs/main.md +35 -0
- package/rules/js-run/runtime/fix-runtime.mjs +46 -0
- package/rules/js-run/runtime/main.mjs +496 -0
- package/rules/js-run/runtime/runtime.mdc +184 -0
- package/rules/js-run/scope/concern.json +3 -0
- package/rules/js-run/scope/scope.mdc +11 -0
- package/rules/npm-module/docs/index.md +11 -0
- package/rules/npm-module/emit_types_config/concern.json +9 -0
- package/rules/npm-module/emit_types_config/docs/fix-emit_types_config.md +25 -0
- package/rules/npm-module/emit_types_config/docs/index.md +9 -0
- package/rules/npm-module/emit_types_config/emit_types_config.mdc +43 -0
- package/rules/npm-module/emit_types_config/emit_types_config.rego +28 -0
- package/rules/npm-module/emit_types_config/fix-emit_types_config.mjs +5 -0
- package/rules/npm-module/emit_types_config/template/tsconfig.emit-types.json.snippet.json +9 -0
- package/rules/npm-module/header_doc_pointer/concern.json +5 -0
- package/rules/npm-module/header_doc_pointer/docs/main.md +40 -0
- package/rules/npm-module/header_doc_pointer/header_doc_pointer.mdc +18 -0
- package/rules/npm-module/header_doc_pointer/main.mjs +131 -0
- package/rules/npm-module/main.json +1 -0
- package/rules/npm-module/main.mdc +36 -0
- package/rules/npm-module/npm_package_json/concern.json +9 -0
- package/rules/npm-module/npm_package_json/docs/fix-npm_package_json.md +26 -0
- package/rules/npm-module/npm_package_json/docs/index.md +9 -0
- package/rules/npm-module/npm_package_json/fix-npm_package_json.mjs +5 -0
- package/rules/npm-module/npm_package_json/npm_package_json.mdc +57 -0
- package/rules/npm-module/npm_package_json/npm_package_json.rego +73 -0
- package/rules/npm-module/npm_package_json/template/package.json.snippet.json +1 -0
- package/rules/npm-module/package_structure/concern.json +5 -0
- package/rules/npm-module/package_structure/docs/main.md +37 -0
- package/rules/npm-module/package_structure/main.mjs +448 -0
- package/rules/npm-module/package_structure/package_structure.mdc +63 -0
- package/rules/npm-module/root_package_json/concern.json +9 -0
- package/rules/npm-module/root_package_json/docs/fix-root_package_json.md +25 -0
- package/rules/npm-module/root_package_json/docs/index.md +9 -0
- package/rules/npm-module/root_package_json/fix-root_package_json.mjs +5 -0
- package/rules/npm-module/root_package_json/root_package_json.mdc +41 -0
- package/rules/npm-module/root_package_json/root_package_json.rego +28 -0
- package/rules/npm-module/root_package_json/template/package.json.snippet.json +1 -0
- package/rules/npm-module/rule_meta/concern.json +8 -0
- package/rules/npm-module/rule_meta/docs/main.md +35 -0
- package/rules/npm-module/rule_meta/main.mjs +119 -0
- package/rules/npm-module/rule_meta/rule_meta.mdc +11 -0
- package/rules/npm-module/skill_meta/concern.json +5 -0
- package/rules/npm-module/skill_meta/docs/main.md +149 -0
- package/rules/npm-module/skill_meta/main.mjs +91 -0
- package/rules/npm-module/skill_meta/skill_meta.mdc +11 -0
- package/rules/tool-surface/docs/index.md +11 -0
- package/rules/tool-surface/main.json +6 -0
- package/rules/tool-surface/main.mdc +72 -0
- package/rules/vue/composition-api/composition-api.mdc +82 -0
- package/rules/vue/composition-api/concern.json +3 -0
- package/rules/vue/docs/index.md +11 -0
- package/rules/vue/lib/docs/index.md +11 -0
- package/rules/vue/lib/docs/vue-forbidden-imports.md +265 -0
- package/rules/vue/lib/vue-forbidden-imports.mjs +240 -0
- package/rules/vue/main.json +1 -0
- package/rules/vue/main.mdc +18 -0
- package/rules/vue/nheader-layout/concern.json +3 -0
- package/rules/vue/nheader-layout/nheader-layout.mdc +171 -0
- package/rules/vue/package_json/concern.json +9 -0
- package/rules/vue/package_json/package_json.mdc +30 -0
- package/rules/vue/package_json/package_json.rego +140 -0
- package/rules/vue/packages/concern.json +6 -0
- package/rules/vue/packages/docs/index.md +11 -0
- package/rules/vue/packages/docs/main.md +35 -0
- package/rules/vue/packages/main.mjs +575 -0
- package/rules/vue/packages/packages.mdc +56 -0
- package/rules/vue/quasar-ui/concern.json +3 -0
- package/rules/vue/quasar-ui/quasar-ui.mdc +32 -0
- package/rules/vue/structure/concern.json +3 -0
- package/rules/vue/structure/structure.mdc +101 -0
- package/rules/vue/testing/concern.json +3 -0
- package/rules/vue/testing/testing.mdc +40 -0
- package/rules/vue/tfm-translations/concern.json +7 -0
- package/rules/vue/tfm-translations/docs/main.md +29 -0
- package/rules/vue/tfm-translations/main.mjs +55 -0
- package/rules/vue/tfm-translations/tfm-translations.mdc +32 -0
- package/rules/vue/vite-config/concern.json +3 -0
- package/rules/vue/vite-config/vite-config.mdc +153 -0
- package/rules/vue/vite-env/concern.json +3 -0
- package/rules/vue/vite-env/vite-env.mdc +61 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/** @see ./docs/lint-findings.md */
|
|
2
|
+
import { isAbsolute, relative } from 'node:path'
|
|
3
|
+
|
|
4
|
+
import { isIntroducedLine } from '@7n/rules/scripts/lib/diff-added-lines.mjs'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {string} jsonText вивід `oxlint --format=json`
|
|
8
|
+
* @returns {{ file: string, line: number, rule: string, message: string, tool: string }[] | null} findings,
|
|
9
|
+
* або `null` якщо json непарсабельний (краш/обрізаний вивід інструмента — НЕ «чисто»)
|
|
10
|
+
*/
|
|
11
|
+
export function parseOxlint(jsonText) {
|
|
12
|
+
let data
|
|
13
|
+
try {
|
|
14
|
+
data = JSON.parse(jsonText)
|
|
15
|
+
} catch {
|
|
16
|
+
return null
|
|
17
|
+
}
|
|
18
|
+
const diags = Array.isArray(data?.diagnostics) ? data.diagnostics : []
|
|
19
|
+
return diags
|
|
20
|
+
.filter(d => d?.filename)
|
|
21
|
+
.map(d => ({
|
|
22
|
+
file: d.filename,
|
|
23
|
+
line: d.labels?.[0]?.span?.line ?? 0,
|
|
24
|
+
rule: d.code ?? '',
|
|
25
|
+
message: d.message ?? '',
|
|
26
|
+
tool: 'oxlint'
|
|
27
|
+
}))
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} jsonText вивід `eslint --format=json`
|
|
32
|
+
* @returns {{ file: string, line: number, rule: string, message: string, tool: string }[] | null} findings,
|
|
33
|
+
* або `null` якщо json непарсабельний (краш/обрізаний вивід інструмента — НЕ «чисто»)
|
|
34
|
+
*/
|
|
35
|
+
export function parseEslint(jsonText) {
|
|
36
|
+
let data
|
|
37
|
+
try {
|
|
38
|
+
data = JSON.parse(jsonText)
|
|
39
|
+
} catch {
|
|
40
|
+
return null
|
|
41
|
+
}
|
|
42
|
+
const results = Array.isArray(data) ? data : []
|
|
43
|
+
const out = []
|
|
44
|
+
for (const r of results) {
|
|
45
|
+
for (const m of r?.messages ?? []) {
|
|
46
|
+
out.push({
|
|
47
|
+
file: r.filePath,
|
|
48
|
+
line: m.line ?? 0,
|
|
49
|
+
rule: m.ruleId ?? '(syntax)',
|
|
50
|
+
message: m.message ?? '',
|
|
51
|
+
tool: 'eslint'
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return out.filter(f => f.file)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Конвертує результати ESLint programmatic API у нормалізовані findings.
|
|
60
|
+
* @param {import('eslint').ESLint.LintResult[]} results результати `eslint.lintFiles()`
|
|
61
|
+
* @returns {{ file: string, line: number, rule: string, message: string, tool: string }[]} findings
|
|
62
|
+
*/
|
|
63
|
+
export function eslintResultsToFindings(results) {
|
|
64
|
+
const out = []
|
|
65
|
+
for (const r of results) {
|
|
66
|
+
for (const m of r.messages) {
|
|
67
|
+
out.push({
|
|
68
|
+
file: r.filePath,
|
|
69
|
+
line: m.line ?? 0,
|
|
70
|
+
rule: m.ruleId ?? '(syntax)',
|
|
71
|
+
message: m.message ?? '',
|
|
72
|
+
tool: 'eslint'
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return out.filter(f => f.file)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Розділяє findings на introduced / pre-existing за доданими рядками.
|
|
81
|
+
* @param {{ file: string, line: number }[]} findings нормалізовані findings
|
|
82
|
+
* @param {Map<string, Set<number> | string>} addedLines з `addedLinesByFile`
|
|
83
|
+
* @param {string} [cwd] корінь (для нормалізації абсолютних шляхів у relative)
|
|
84
|
+
* @returns {{ introduced: object[], preExisting: object[] }} класифікація
|
|
85
|
+
*/
|
|
86
|
+
export function classifyFindings(findings, addedLines, cwd = process.cwd()) {
|
|
87
|
+
const introduced = []
|
|
88
|
+
const preExisting = []
|
|
89
|
+
for (const f of findings) {
|
|
90
|
+
const rel = isAbsolute(f.file) ? relative(cwd, f.file) : f.file
|
|
91
|
+
if (isIntroducedLine(addedLines, rel, f.line)) introduced.push(f)
|
|
92
|
+
else preExisting.push(f)
|
|
93
|
+
}
|
|
94
|
+
return { introduced, preExisting }
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Рядок одного finding: `<rel>:<line> <rule> <message>`.
|
|
99
|
+
* @param {{ file: string, line: number, rule: string, message: string }} f finding
|
|
100
|
+
* @param {string} cwd корінь
|
|
101
|
+
* @returns {string} рядок
|
|
102
|
+
*/
|
|
103
|
+
function formatFinding(f, cwd) {
|
|
104
|
+
const rel = isAbsolute(f.file) ? relative(cwd, f.file) : f.file
|
|
105
|
+
return ` ${rel}:${f.line} ${f.rule} ${f.message}`
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Згрупований звіт: 🆕 introduced (виправ) + 🗄 pre-existing (борг файлу).
|
|
110
|
+
* @param {{ introduced: object[], preExisting: object[] }} classified результат `classifyFindings`
|
|
111
|
+
* @param {string} [cwd] корінь
|
|
112
|
+
* @returns {string} текст звіту
|
|
113
|
+
*/
|
|
114
|
+
export function renderFindings({ introduced, preExisting }, cwd = process.cwd()) {
|
|
115
|
+
const lines = []
|
|
116
|
+
if (introduced.length > 0) {
|
|
117
|
+
lines.push(` 🆕 introduced (${introduced.length}) — внесено цією зміною, виправ:`)
|
|
118
|
+
for (const f of introduced) lines.push(formatFinding(f, cwd))
|
|
119
|
+
}
|
|
120
|
+
if (preExisting.length > 0) {
|
|
121
|
+
lines.push(` 🗄 pre-existing (${preExisting.length}) — борг файлу, не з цієї зміни:`)
|
|
122
|
+
for (const f of preExisting) lines.push(formatFinding(f, cwd))
|
|
123
|
+
}
|
|
124
|
+
return lines.join('\n')
|
|
125
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "auto": { "glob": ["**/*.mjs", "**/*.cjs", "**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] } }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Перевірка JavaScript коду
|
|
3
|
+
globs: "**/{.oxlintrc.json,eslint.config.js,.jscpd.json,knip.json,package.json},**/*.{js,mjs,cjs,jsx,ts,tsx}"
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
version: '1.31'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
**oxlint**, **ESLint**, **jscpd**, **knip**. Запуск — **`n-rules lint js`** (локально; у CI — `--no-fix`, без **`--fix`** для oxlint/eslint). Без **prettier** і **@nitra/prettier-config**.
|
|
9
|
+
|
|
10
|
+
`eslint.config.js` — flat config з `getConfig` (`@nitra/eslint-config`). Аргументи `node: [...]`/`vue: [...]` мають відповідати воркспейс-типам репо (`workspaces` root `package.json`; vue-воркспейс = Vue-залежність у deps або `.vue` файли) — інакше `.vue` файли не парсяться. Відсутній конфіг створюється (scaffold), наявний — зазнає хірургічного merge (fix не перезаписує файл цілком).
|
|
11
|
+
|
|
12
|
+
## Швидкий gate через conftest
|
|
13
|
+
|
|
14
|
+
Rego-пакети — запускаються `npx @7n/rules lint js` або `conftest`:
|
|
15
|
+
|
|
16
|
+
- [.jscpd.json.snippet.json](./jscpd_config/template/.jscpd.json.snippet.json)
|
|
17
|
+
- [extensions.json.snippet.json](./vscode_extensions/template/extensions.json.snippet.json)
|
|
18
|
+
- [package.json.snippet.json](./package_json/template/package.json.snippet.json)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: fix-package_json.mjs
|
|
4
|
+
resource: plugins/lang-js/rules/js/package_json/fix-package_json.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: e7e3caa7
|
|
7
|
+
model: openai-codex/gpt-5.4-mini
|
|
8
|
+
score: 100
|
|
9
|
+
issues: judge:inaccurate:0.98
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Огляд
|
|
14
|
+
|
|
15
|
+
`patterns` забезпечує перевірку й звірку `package.json` з очікуваним шаблоном цього проєкту. Модуль читає `package.json` як основний конфіг, на який спирається код, і використовується для оцінки відповідності структури та вмісту файла вимогам проєкту. Робота read-only: змін у файловій системі чи базі даних не вносить.
|
|
16
|
+
|
|
17
|
+
## Поведінка
|
|
18
|
+
|
|
19
|
+
1. `patterns` надає набір правил, які приводять `package.json` до очікуваного шаблону для цього проєкту.
|
|
20
|
+
2. Кожне правило орієнтується на конфігурацію `package.json` і застосовується до нього як до цільового файлу.
|
|
21
|
+
3. `patterns` використовується як публічна точка входу для перевірки й вирівнювання структури `package.json` без змін у файловій системі чи базі даних.
|
|
22
|
+
|
|
23
|
+
## Гарантії поведінки
|
|
24
|
+
|
|
25
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## Rego-gate `package.json`
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `js_lint.package_json`
|
|
4
|
+
|
|
5
|
+
Цільовий файл: `package.json` (корінь і workspace-пакети).
|
|
6
|
+
|
|
7
|
+
Що перевіряється:
|
|
8
|
+
|
|
9
|
+
- `"type"` — точна відповідність `"module"` (з канон-snippet)
|
|
10
|
+
- `scripts.lint-js` — нормалізована точна відповідність (collapse whitespace)
|
|
11
|
+
- `engines.node` — semver-парсинг: major >= 24 (inverse, без template)
|
|
12
|
+
- `engines.bun` — semver-парсинг: >= 1.3 (inverse, без template)
|
|
13
|
+
- `devDependencies["@nitra/eslint-config"]` — наявність ключа + semver >= порогу зі snippet (`^3.10.0`); `workspace:*` завжди проходить
|
|
14
|
+
|
|
15
|
+
Канон-snippet: [package.json.snippet.json](./template/package.json.snippet.json)
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Перевірка `package.json` (js.mdc).
|
|
2
|
+
#
|
|
3
|
+
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
+
# Структура --data сформована з template/package.json.snippet.json
|
|
5
|
+
# (canonical `type` + `scripts.lint-js` + `devDependencies.@nitra/eslint-config` як мін-поріг).
|
|
6
|
+
#
|
|
7
|
+
# Мінімальна версія `@nitra/eslint-config` — ЄДИНЕ джерело в snippet
|
|
8
|
+
# (`devDependencies.@nitra/eslint-config`); rego лише парсить поріг і робить semver-порівняння.
|
|
9
|
+
#
|
|
10
|
+
# Логіка, що ЛИШАЄТЬСЯ у rego (inverse, без template-значення):
|
|
11
|
+
# - `engines.node` >= 24, `engines.bun` >= 1.3 (semver range parsing).
|
|
12
|
+
package js.package_json
|
|
13
|
+
|
|
14
|
+
import rego.v1
|
|
15
|
+
|
|
16
|
+
# ── deny: top-level scalar leafs (type) ─────────────────────────────────
|
|
17
|
+
|
|
18
|
+
banned_fastify_pkg := "@nitra/as-integrations-fastify"
|
|
19
|
+
|
|
20
|
+
deny contains msg if {
|
|
21
|
+
some key, expected_value in data.template.snippet
|
|
22
|
+
not is_object(expected_value)
|
|
23
|
+
actual := object.get(input, key, null)
|
|
24
|
+
actual != expected_value
|
|
25
|
+
msg := sprintf("package.json: \"%s\" має бути %q (js.mdc)", [key, expected_value])
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# ── deny: scripts (nested) — exact match із normalize ──────────────────
|
|
29
|
+
|
|
30
|
+
deny contains msg if {
|
|
31
|
+
some script_name, expected in data.template.snippet.scripts
|
|
32
|
+
actual := object.get(object.get(input, "scripts", {}), script_name, "")
|
|
33
|
+
normalize_script(actual) != expected
|
|
34
|
+
msg := sprintf("package.json: scripts.%s має бути %q (js.mdc)", [script_name, expected])
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# ── deny: engines.node >= 24 (inverse, у rego) ──────────────────────────
|
|
38
|
+
|
|
39
|
+
deny contains msg if {
|
|
40
|
+
engines := object.get(input, "engines", {})
|
|
41
|
+
not engines_node_meets(object.get(engines, "node", ""))
|
|
42
|
+
msg := "package.json: engines.node має бути >= 24 (js.mdc)"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
deny contains msg if {
|
|
46
|
+
engines := object.get(input, "engines", {})
|
|
47
|
+
not engines_bun_meets(object.get(engines, "bun", ""))
|
|
48
|
+
msg := "package.json: engines.bun має бути >= 1.3 (js.mdc)"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# ── deny: @nitra/eslint-config >= snippet-поріг ─────────────────────────
|
|
52
|
+
|
|
53
|
+
deny contains msg if {
|
|
54
|
+
dev := object.get(input, "devDependencies", {})
|
|
55
|
+
not "@nitra/eslint-config" in object.keys(dev)
|
|
56
|
+
msg := "package.json: відсутній @nitra/eslint-config у devDependencies (js.mdc)"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
deny contains msg if {
|
|
60
|
+
range := object.get(object.get(input, "devDependencies", {}), "@nitra/eslint-config", "")
|
|
61
|
+
range != ""
|
|
62
|
+
not eslint_config_meets_min(range)
|
|
63
|
+
msg := sprintf("package.json: @nitra/eslint-config має бути >= %s (зараз %q) (js.mdc)", [eslint_min_display, range])
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# ── deny: @nitra/as-integrations-fastify заборонений (dep-policy.mdc) ───
|
|
67
|
+
|
|
68
|
+
deny contains msg if {
|
|
69
|
+
deps := object.get(input, "dependencies", {})
|
|
70
|
+
banned_fastify_pkg in object.keys(deps)
|
|
71
|
+
msg := sprintf("package.json: dependencies.%s заборонений — використовуй @as-integrations/fastify (js.mdc dep-policy)", [banned_fastify_pkg])
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
deny contains msg if {
|
|
75
|
+
deps := object.get(input, "peerDependencies", {})
|
|
76
|
+
banned_fastify_pkg in object.keys(deps)
|
|
77
|
+
msg := sprintf("package.json: peerDependencies.%s заборонений — використовуй @as-integrations/fastify (js.mdc dep-policy)", [banned_fastify_pkg])
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# ── helpers ──────────────────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
# Канонічний мін-поріг `@nitra/eslint-config` із snippet (напр. "^3.10.0").
|
|
83
|
+
eslint_min_range := object.get(object.get(data.template.snippet, "devDependencies", {}), "@nitra/eslint-config", "")
|
|
84
|
+
|
|
85
|
+
# Поріг для повідомлення без діапазонних префіксів (напр. "3.10.0").
|
|
86
|
+
eslint_min_display := trim_left(eslint_min_range, "^~>=v ")
|
|
87
|
+
|
|
88
|
+
normalize_script(s) := regex.replace(trim_space(s), `\s+`, " ")
|
|
89
|
+
|
|
90
|
+
engines_node_meets(spec) if {
|
|
91
|
+
major := first_major(spec)
|
|
92
|
+
major >= 24
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
engines_bun_meets(spec) if {
|
|
96
|
+
parts := split_to_numbers(spec)
|
|
97
|
+
count(parts) >= 2
|
|
98
|
+
parts[0] > 1
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
engines_bun_meets(spec) if {
|
|
102
|
+
parts := split_to_numbers(spec)
|
|
103
|
+
count(parts) >= 2
|
|
104
|
+
parts[0] == 1
|
|
105
|
+
parts[1] >= 3
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
eslint_config_meets_min(range) if startswith(trim_space(range), "workspace:")
|
|
109
|
+
|
|
110
|
+
eslint_config_meets_min(range) if {
|
|
111
|
+
actual := split_to_numbers(range)
|
|
112
|
+
count(actual) >= 3
|
|
113
|
+
min_parts := split_to_numbers(eslint_min_range)
|
|
114
|
+
count(min_parts) >= 3
|
|
115
|
+
semver_gte(actual, min_parts)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# actual >= min_parts за major.minor.patch (лексикографічно).
|
|
119
|
+
semver_gte(a, b) if a[0] > b[0]
|
|
120
|
+
|
|
121
|
+
semver_gte(a, b) if {
|
|
122
|
+
a[0] == b[0]
|
|
123
|
+
a[1] > b[1]
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
semver_gte(a, b) if {
|
|
127
|
+
a[0] == b[0]
|
|
128
|
+
a[1] == b[1]
|
|
129
|
+
a[2] >= b[2]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
first_major(spec) := major if {
|
|
133
|
+
parts := split_to_numbers(spec)
|
|
134
|
+
count(parts) >= 1
|
|
135
|
+
major := parts[0]
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
split_to_numbers(spec) := nums if {
|
|
139
|
+
tokens := regex.split(`\D+`, spec)
|
|
140
|
+
non_empty := [t | some t in tokens; t != ""]
|
|
141
|
+
nums := [n | some t in non_empty; n := to_number(t)]
|
|
142
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://unpkg.com/knip@5/schema.json",
|
|
3
|
+
"entry": [
|
|
4
|
+
".pi/extensions/**/*.ts",
|
|
5
|
+
"eslint.config.{js,mjs,cjs}",
|
|
6
|
+
"stylelint.config.{js,cjs,mjs}",
|
|
7
|
+
"oxlint.config.{js,mjs}",
|
|
8
|
+
"jscpd.config.{js,mjs}",
|
|
9
|
+
"markdownlint-cli2.config.{js,mjs,cjs,jsonc}",
|
|
10
|
+
".markdownlint-cli2.{jsonc,cjs,mjs}",
|
|
11
|
+
"commitlint.config.{js,cjs,mjs}"
|
|
12
|
+
],
|
|
13
|
+
"project": ["**/*.{js,mjs,cjs,jsx,ts,tsx,mts,cts}"],
|
|
14
|
+
"ignore": ["**/__fixtures__/**"],
|
|
15
|
+
"ignoreDependencies": ["@nitra/cspell-dict", "/@cspell\\/dict-.+/", "graphql"],
|
|
16
|
+
"ignoreBinaries": [
|
|
17
|
+
"actionlint",
|
|
18
|
+
"cspell",
|
|
19
|
+
"eslint",
|
|
20
|
+
"git-ai",
|
|
21
|
+
"jscpd",
|
|
22
|
+
"markdownlint-cli2",
|
|
23
|
+
"oxfmt",
|
|
24
|
+
"oxlint",
|
|
25
|
+
"shellcheck",
|
|
26
|
+
"uvx",
|
|
27
|
+
"v8r",
|
|
28
|
+
"zizmor"
|
|
29
|
+
]
|
|
30
|
+
}
|