@7n/rules-lang-js 0.3.1 → 0.4.1
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 +12 -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 +31 -0
- package/rules/js/knip/knip.mdc +15 -0
- package/rules/js/knip/main.mjs +89 -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,297 @@
|
|
|
1
|
+
/** @see ./docs/deps.md */
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { readFile } from 'node:fs/promises'
|
|
4
|
+
import { join, relative } from 'node:path'
|
|
5
|
+
|
|
6
|
+
import { createViolationReporter } from '@7n/rules/scripts/lib/lint-surface/violation-reporter.mjs'
|
|
7
|
+
import { findAllPackageJsonPaths } from '@7n/rules/scripts/utils/find-package-json-paths.mjs'
|
|
8
|
+
import {
|
|
9
|
+
findMssqlPerRequestConnectionInText,
|
|
10
|
+
findSharedMssqlRequestInText,
|
|
11
|
+
findUnsafeMssqlQueryTemplateCallInText,
|
|
12
|
+
findUnsafeMssqlDynamicSqlListInText,
|
|
13
|
+
findUnsafeMssqlInListUnparsedInText,
|
|
14
|
+
findUnsafeMssqlInListMissingEmptyGuardInText,
|
|
15
|
+
isMssqlScanSourceFile
|
|
16
|
+
} from '../lib/mssql-pool-scan.mjs'
|
|
17
|
+
import { loadCursorIgnorePaths } from '@7n/rules/scripts/lib/load-cursor-config.mjs'
|
|
18
|
+
import { walkDir } from '@7n/rules/scripts/utils/walkDir.mjs'
|
|
19
|
+
|
|
20
|
+
const VERSION_PREFIX_RE = /^[\^~>=<]+\s*/u
|
|
21
|
+
const SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)/u
|
|
22
|
+
|
|
23
|
+
/** Мінімальна дозволена версія mssql (js-mssql.mdc). */
|
|
24
|
+
const MIN_MSSQL_VERSION = { major: 12, minor: 5, patch: 0 }
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Збирає абсолютні шляхи JS/TS джерел у репозиторії для скану mssql.
|
|
28
|
+
* @param {string} repoRoot абсолютний шлях до кореня репозиторію
|
|
29
|
+
* @param {string[]} ignorePaths абсолютні шляхи каталогів, повністю виключених з обходу
|
|
30
|
+
* @returns {Promise<string[]>} абсолютні шляхи, відсортовані за відносним шляхом
|
|
31
|
+
*/
|
|
32
|
+
async function findAllSourcePathsForMssqlScan(repoRoot, ignorePaths) {
|
|
33
|
+
/** @type {string[]} */
|
|
34
|
+
const paths = []
|
|
35
|
+
await walkDir(
|
|
36
|
+
repoRoot,
|
|
37
|
+
absPath => {
|
|
38
|
+
const rel = relative(repoRoot, absPath).split('\\').join('/')
|
|
39
|
+
if (isMssqlScanSourceFile(rel)) {
|
|
40
|
+
paths.push(absPath)
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
ignorePaths
|
|
44
|
+
)
|
|
45
|
+
paths.sort((a, b) => relative(repoRoot, a).localeCompare(relative(repoRoot, b)))
|
|
46
|
+
return paths
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {unknown} v parsed JSON
|
|
51
|
+
* @returns {Record<string, unknown>} object або {}
|
|
52
|
+
*/
|
|
53
|
+
function asObject(v) {
|
|
54
|
+
if (!v || typeof v !== 'object' || Array.isArray(v)) return {}
|
|
55
|
+
return /** @type {Record<string, unknown>} */ (v)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Витягає рядок версії `dependencies.mssql`, якщо він існує.
|
|
60
|
+
* @param {unknown} deps deps з package.json
|
|
61
|
+
* @returns {string | null} версія або null
|
|
62
|
+
*/
|
|
63
|
+
function getMssqlDependencyRange(deps) {
|
|
64
|
+
const o = asObject(deps)
|
|
65
|
+
const v = o.mssql
|
|
66
|
+
return typeof v === 'string' && v.trim() ? v.trim() : null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Парсить першу semver з діапазону виду "^12.5.0", ">=12.5.0", "12.5.0".
|
|
71
|
+
* @param {string} range версійний діапазон
|
|
72
|
+
* @returns {{ major: number, minor: number, patch: number } | null} semver або null
|
|
73
|
+
*/
|
|
74
|
+
function parseLeadingSemver(range) {
|
|
75
|
+
const cleaned = String(range).trim().replace(VERSION_PREFIX_RE, '')
|
|
76
|
+
const m = cleaned.match(SEMVER_RE)
|
|
77
|
+
if (!m) return null
|
|
78
|
+
const major = Number(m[1])
|
|
79
|
+
const minor = Number(m[2])
|
|
80
|
+
const patch = Number(m[3])
|
|
81
|
+
if ([major, minor, patch].some(n => Number.isNaN(n))) return null
|
|
82
|
+
return { major, minor, patch }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @param {{ major: number, minor: number, patch: number }} a перша semver
|
|
87
|
+
* @param {{ major: number, minor: number, patch: number }} b друга semver
|
|
88
|
+
* @returns {boolean} true, якщо a >= b
|
|
89
|
+
*/
|
|
90
|
+
function semverGte(a, b) {
|
|
91
|
+
if (a.major !== b.major) return a.major > b.major
|
|
92
|
+
if (a.minor !== b.minor) return a.minor > b.minor
|
|
93
|
+
return a.patch >= b.patch
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Аудит одного package.json на dependencies.mssql: версія має бути >=12.5.0.
|
|
98
|
+
* Повертає інкремент для лічильників `{ found, bad }`.
|
|
99
|
+
* @param {string} rel шлях у людино-читабельному вигляді
|
|
100
|
+
* @param {unknown} parsed розпарений package.json
|
|
101
|
+
* @param {(msg: string) => void} pass pass callback
|
|
102
|
+
* @param {(msg: string) => void} fail fail callback
|
|
103
|
+
* @returns {{ found: 0 | 1, bad: 0 | 1 }} прирости лічильників
|
|
104
|
+
*/
|
|
105
|
+
function auditMssqlVersionInPackageJson(rel, parsed, pass, fail) {
|
|
106
|
+
const range = getMssqlDependencyRange(asObject(parsed).dependencies)
|
|
107
|
+
if (!range) return { found: 0, bad: 0 }
|
|
108
|
+
|
|
109
|
+
const parsedVer = parseLeadingSemver(range)
|
|
110
|
+
if (!parsedVer) {
|
|
111
|
+
fail(`js-mssql: ${rel}: dependencies.mssql має нечитабельну версію: ${JSON.stringify(range)} (js-mssql.mdc)`)
|
|
112
|
+
return { found: 1, bad: 1 }
|
|
113
|
+
}
|
|
114
|
+
if (semverGte(parsedVer, MIN_MSSQL_VERSION)) {
|
|
115
|
+
pass(`js-mssql: ${rel}: dependencies.mssql ${JSON.stringify(range)} (>=12.5.0)`)
|
|
116
|
+
return { found: 1, bad: 0 }
|
|
117
|
+
}
|
|
118
|
+
fail(`js-mssql: ${rel}: dependencies.mssql ${JSON.stringify(range)} — має бути >=12.5.0 (js-mssql.mdc)`)
|
|
119
|
+
return { found: 1, bad: 1 }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Прогін усіх package.json: рахує знайдені mssql і ті, що не задовольняють мінімум.
|
|
124
|
+
* @param {string} repoRoot корінь репозиторію
|
|
125
|
+
* @param {string[]} pkgJsonPaths абсолютні шляхи до package.json
|
|
126
|
+
* @param {(msg: string) => void} pass pass callback
|
|
127
|
+
* @param {(msg: string) => void} fail fail callback
|
|
128
|
+
* @returns {Promise<{ found: number, bad: number }>} підсумкові лічильники
|
|
129
|
+
*/
|
|
130
|
+
async function aggregateMssqlVersionsAcrossPackages(repoRoot, pkgJsonPaths, pass, fail) {
|
|
131
|
+
let found = 0
|
|
132
|
+
let bad = 0
|
|
133
|
+
for (const absPath of pkgJsonPaths) {
|
|
134
|
+
const rel = relative(repoRoot, absPath).split('\\').join('/')
|
|
135
|
+
let parsed
|
|
136
|
+
try {
|
|
137
|
+
parsed = JSON.parse(await readFile(absPath, 'utf8'))
|
|
138
|
+
} catch {
|
|
139
|
+
fail(`js-mssql: ${rel} — невалідний JSON`)
|
|
140
|
+
continue
|
|
141
|
+
}
|
|
142
|
+
const inc = auditMssqlVersionInPackageJson(rel, parsed, pass, fail)
|
|
143
|
+
found += inc.found
|
|
144
|
+
bad += inc.bad
|
|
145
|
+
}
|
|
146
|
+
return { found, bad }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Підрахунок порушень у одному файлі джерела mssql.
|
|
151
|
+
* Кожен лічильник інкрементується відповідним сканером, повідомлення йдуть у `fail`.
|
|
152
|
+
* @param {string} rel relative-шлях файлу
|
|
153
|
+
* @param {string} content вихідний код
|
|
154
|
+
* @param {Record<string, number>} counters агрегатор лічильників
|
|
155
|
+
* @param {(msg: string) => void} fail fail callback
|
|
156
|
+
*/
|
|
157
|
+
function scanMssqlOneSourceFile(rel, content, counters, fail) {
|
|
158
|
+
for (const v of findMssqlPerRequestConnectionInText(content, rel)) {
|
|
159
|
+
counters.violations++
|
|
160
|
+
fail(
|
|
161
|
+
`js-mssql: ${rel}:${v.line} — не створюй new sql.ConnectionPool(...) на кожен запит; використовуй singleton sql.ConnectionPool: ${v.snippet}`
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
for (const v of findSharedMssqlRequestInText(content, rel)) {
|
|
165
|
+
counters.sharedRequestViolations++
|
|
166
|
+
fail(
|
|
167
|
+
`js-mssql: ${rel}:${v.line} — заборонено шарити Request (наприклад export const request = pool.request()); створюй pool.request() щоразу заново (js-mssql.mdc): ${v.snippet}`
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
for (const v of findUnsafeMssqlQueryTemplateCallInText(content, rel)) {
|
|
171
|
+
counters.unsafeQueryCalls++
|
|
172
|
+
fail(
|
|
173
|
+
`js-mssql: ${rel}:${v.line} — заборонено query(\`...\`): це не tagged template; використовуй pool.request().query\`...\` (js-mssql.mdc): ${v.snippet}`
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
for (const v of findUnsafeMssqlDynamicSqlListInText(content, rel)) {
|
|
177
|
+
counters.unsafeDynamicSqlLists++
|
|
178
|
+
fail(
|
|
179
|
+
`js-mssql: ${rel}:${v.line} — заборонено підставляти у SQL динамічні списки через .join(',') (типово IN (...) / VALUES (...)); використовуй TVP (sql.Table) + JOIN/INSERT (js-mssql.mdc): ${v.snippet}`
|
|
180
|
+
)
|
|
181
|
+
}
|
|
182
|
+
for (const v of findUnsafeMssqlInListUnparsedInText(content, rel)) {
|
|
183
|
+
counters.unparsedInLists++
|
|
184
|
+
fail(
|
|
185
|
+
`js-mssql: ${rel}:${v.line} — у SQL IN (\${...}) значення мають бути попередньо приведені числовим парсером (parseInt/Number/BigInt/parseFloat) і відфільтровані від NaN, інакше можливий SQL injection (js-mssql.mdc): ${v.snippet}`
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
for (const v of findUnsafeMssqlInListMissingEmptyGuardInText(content, rel)) {
|
|
189
|
+
counters.inListGuardViolations++
|
|
190
|
+
if (v.reason === 'missing_guard') {
|
|
191
|
+
fail(
|
|
192
|
+
`js-mssql: ${rel}:${v.line} — перед IN-списком ${JSON.stringify(v.name)} потрібна перевірка на пустоту з throw ` +
|
|
193
|
+
`(наприклад if (!${v.name}.length) throw ...), інакше можливі некоректні запити (js-mssql.mdc): ${v.snippet}`
|
|
194
|
+
)
|
|
195
|
+
} else {
|
|
196
|
+
fail(
|
|
197
|
+
`js-mssql: ${rel}:${v.line} — значення для IN (\${...}) у template literal треба винести в окрему змінну ` +
|
|
198
|
+
`і перевірити на пустоту (throw), не підставляти вираз напряму (js-mssql.mdc): ${v.snippet}`
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Звіт про відсутність порушень у джерелах mssql: кожен лічильник із 0 → один pass-рядок.
|
|
206
|
+
* @param {Record<string, number>} counters лічильники після проходу всіх файлів
|
|
207
|
+
* @param {(msg: string) => void} pass pass callback
|
|
208
|
+
*/
|
|
209
|
+
function reportZeroMssqlSourceViolations(counters, pass) {
|
|
210
|
+
if (counters.violations === 0) {
|
|
211
|
+
pass('js-mssql: немає створення new sql.ConnectionPool(...) всередині функцій (singleton pool)')
|
|
212
|
+
}
|
|
213
|
+
if (counters.sharedRequestViolations === 0) {
|
|
214
|
+
pass('js-mssql: немає shared Request (export const request = pool.request())')
|
|
215
|
+
}
|
|
216
|
+
if (counters.unsafeQueryCalls === 0) {
|
|
217
|
+
pass('js-mssql: немає небезпечних викликів query(`...`) (потрібно query`...`)')
|
|
218
|
+
}
|
|
219
|
+
if (counters.unsafeDynamicSqlLists === 0) {
|
|
220
|
+
pass("js-mssql: немає небезпечних динамічних SQL-списків через .join(',') у IN/VALUES")
|
|
221
|
+
}
|
|
222
|
+
if (counters.unparsedInLists === 0) {
|
|
223
|
+
pass(`js-mssql: немає підстановок IN (\${...}) без числового парсера значень`)
|
|
224
|
+
}
|
|
225
|
+
if (counters.inListGuardViolations === 0) {
|
|
226
|
+
pass('js-mssql: усі IN-списки винесені у змінні та мають перевірку на пустоту з throw')
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Аудит усіх JS/TS-джерел репо щодо безпечного використання mssql.
|
|
232
|
+
* @param {string} repoRoot корінь репозиторію
|
|
233
|
+
* @param {string[]} ignorePaths абсолютні шляхи каталогів, повністю виключених з обходу
|
|
234
|
+
* @param {(msg: string) => void} pass pass callback
|
|
235
|
+
* @param {(msg: string) => void} fail fail callback
|
|
236
|
+
* @returns {Promise<void>} визначається по завершенню аудиту всіх знайдених джерел
|
|
237
|
+
*/
|
|
238
|
+
async function auditMssqlSources(repoRoot, ignorePaths, pass, fail) {
|
|
239
|
+
const sourcePaths = await findAllSourcePathsForMssqlScan(repoRoot, ignorePaths)
|
|
240
|
+
if (sourcePaths.length === 0) {
|
|
241
|
+
pass('js-mssql: немає JS/TS файлів для скану singleton ConnectionPool')
|
|
242
|
+
return
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const counters = {
|
|
246
|
+
violations: 0,
|
|
247
|
+
sharedRequestViolations: 0,
|
|
248
|
+
unsafeQueryCalls: 0,
|
|
249
|
+
unsafeDynamicSqlLists: 0,
|
|
250
|
+
unparsedInLists: 0,
|
|
251
|
+
inListGuardViolations: 0
|
|
252
|
+
}
|
|
253
|
+
for (const absPath of sourcePaths) {
|
|
254
|
+
const rel = relative(repoRoot, absPath).split('\\').join('/')
|
|
255
|
+
const content = await readFile(absPath, 'utf8')
|
|
256
|
+
scanMssqlOneSourceFile(rel, content, counters, fail)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
reportZeroMssqlSourceViolations(counters, pass)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Перевіряє відповідність проєкту правилу js-mssql.mdc
|
|
264
|
+
* @param {import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст лінту
|
|
265
|
+
* @returns {Promise<import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintResult>} перелік порушень
|
|
266
|
+
*/
|
|
267
|
+
export async function lint(ctx) {
|
|
268
|
+
const reporter = createViolationReporter(ctx)
|
|
269
|
+
const { pass, fail } = reporter
|
|
270
|
+
|
|
271
|
+
const repoRoot = ctx.cwd
|
|
272
|
+
if (!existsSync(join(repoRoot, 'package.json'))) {
|
|
273
|
+
pass('js-mssql: package.json у корені відсутній — перевірку пропущено')
|
|
274
|
+
return reporter.result()
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const ignorePaths = await loadCursorIgnorePaths(repoRoot)
|
|
278
|
+
const pkgJsonPaths = await findAllPackageJsonPaths(repoRoot, ignorePaths)
|
|
279
|
+
if (pkgJsonPaths.length === 0) {
|
|
280
|
+
pass('js-mssql: package.json не знайдено — перевірку пропущено')
|
|
281
|
+
return reporter.result()
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const { found, bad } = await aggregateMssqlVersionsAcrossPackages(repoRoot, pkgJsonPaths, pass, fail)
|
|
285
|
+
|
|
286
|
+
if (found === 0) {
|
|
287
|
+
pass('js-mssql: пакет mssql не знайдено в dependencies жодного package.json')
|
|
288
|
+
return reporter.result()
|
|
289
|
+
}
|
|
290
|
+
if (bad === 0) {
|
|
291
|
+
pass(`js-mssql: всі знайдені dependencies.mssql відповідають мінімальній версії 12.5.0 (${found})`)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
await auditMssqlSources(repoRoot, ignorePaths, pass, fail)
|
|
295
|
+
|
|
296
|
+
return reporter.result()
|
|
297
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/js-mssql/lib
|
|
4
|
+
resource: plugins/lang-js/rules/js-mssql/lib/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/js-mssql/lib
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------- | --------- |
|
|
11
|
+
| [mssql-pool-scan.mjs](mssql-pool-scan.md) | JS Module |
|