@nitra/cursor 1.13.76 → 1.13.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/CHANGELOG.md +89 -0
- package/README.md +5 -5
- package/bin/n-cursor.js +16 -21
- package/package.json +1 -1
- package/rules/abie/abie.mdc +12 -4
- package/rules/abie/fix.mjs +15 -0
- package/rules/abie/policy/base_deployment_preem/base_deployment_preem.rego +9 -11
- package/rules/abie/policy/health_check_policy/health_check_policy.rego +9 -10
- package/rules/abie/policy/http_route_base/http_route_base.rego +7 -8
- package/rules/abie/utils/k8s-tree.mjs +1 -1
- package/rules/adr/adr.mdc +1 -1
- package/rules/adr/fix.mjs +15 -0
- package/rules/bun/fix.mjs +15 -0
- package/rules/capacitor/fix.mjs +15 -0
- package/rules/changelog/changelog.mdc +1 -1
- package/rules/changelog/fix.mjs +15 -0
- package/rules/changelog/{fix → js}/consistency/check.mjs +16 -16
- package/{scripts/utils → rules/changelog/js/consistency}/package-manifest.mjs +1 -1
- package/rules/ci4/fix.mjs +15 -0
- package/rules/docker/docker.mdc +3 -3
- package/rules/docker/fix.mjs +15 -0
- package/rules/docker/{fix → js}/lint/check.mjs +3 -3
- package/{scripts/utils → rules/docker/js/lint}/docker-hadolint.mjs +3 -3
- package/rules/docker/lint/lint.mjs +2 -2
- package/rules/efes/fix.mjs +15 -0
- package/rules/feedback/fix.mjs +15 -0
- package/rules/ga/fix.mjs +15 -0
- package/rules/ga/lint/lint.mjs +5 -2
- package/rules/graphql/fix.mjs +15 -0
- package/rules/graphql/{fix → js}/tooling/check.mjs +1 -1
- package/{scripts/utils → rules/graphql/js/tooling}/graphql-gql-scan.mjs +47 -12
- package/rules/hasura/fix.mjs +15 -0
- package/rules/hasura/{fix → js}/internal_urls/check.mjs +1 -1
- package/rules/hasura/policy/svc_hl/svc_hl.rego +1 -1
- package/rules/image-avif/fix.mjs +15 -0
- package/rules/image-compress/fix.mjs +15 -0
- package/rules/js-bun-db/fix.mjs +15 -0
- package/{scripts/utils → rules/js-bun-db/js/safety}/bun-sql-scan.mjs +1 -1
- package/rules/js-bun-db/{fix → js}/safety/check.mjs +1 -1
- package/rules/js-bun-redis/fix.mjs +15 -0
- package/rules/js-bun-redis/policy/package_json/package_json.rego +1 -1
- package/rules/js-lint/fix.mjs +15 -0
- package/rules/js-lint/{fix → js}/tooling/check.mjs +3 -15
- package/{scripts/utils → rules/js-lint/js/tooling}/rebuild-oxlint-canonical.mjs +1 -1
- package/rules/js-lint/js-lint.mdc +2 -2
- package/rules/js-mssql/fix.mjs +15 -0
- package/rules/js-mssql/{fix → js}/deps/check.mjs +1 -1
- package/{scripts/utils → rules/js-mssql/js/deps}/mssql-pool-scan.mjs +1 -1
- package/rules/js-run/fix.mjs +15 -0
- package/{scripts/utils → rules/js-run/js/runtime}/bunyan-imports.mjs +1 -1
- package/{scripts/utils → rules/js-run/js/runtime}/check-env-scan.mjs +1 -1
- package/rules/js-run/{fix → js}/runtime/check.mjs +5 -5
- package/{scripts/utils → rules/js-run/js/runtime}/conn-file-rules.mjs +1 -1
- package/{scripts/utils → rules/js-run/js/runtime}/conn-imports-scan.mjs +1 -1
- package/{scripts/utils → rules/js-run/js/runtime}/promise-settimeout-scan.mjs +1 -1
- package/rules/k8s/fix.mjs +15 -0
- package/rules/k8s/k8s.mdc +2 -2
- package/rules/nginx-default-tpl/fix.mjs +15 -0
- package/rules/nginx-default-tpl/{fix → js}/template/check.mjs +1 -1
- package/rules/npm-module/fix.mjs +15 -0
- package/rules/npm-module/{fix → js}/package_structure/check.mjs +11 -1
- package/rules/php/fix.mjs +15 -0
- package/rules/rego/fix.mjs +15 -0
- package/rules/security/fix.mjs +15 -0
- package/rules/security/security.mdc +2 -2
- package/rules/style-lint/fix.mjs +15 -0
- package/rules/tauri/fix.mjs +15 -0
- package/rules/test/auto.md +1 -0
- package/rules/test/fix.mjs +15 -0
- package/rules/test/js/location/check.mjs +77 -0
- package/rules/test/test.mdc +60 -0
- package/rules/text/fix.mjs +15 -0
- package/rules/vue/fix.mjs +15 -0
- package/rules/vue/{fix → js}/packages/check.mjs +2 -2
- package/rules/vue/vue.mdc +1 -1
- package/scripts/auto-rules.mjs +3 -3
- package/scripts/sync-claude-config.mjs +2 -2
- package/scripts/utils/ast-scan-utils.mjs +3 -2
- package/scripts/utils/discover-checkable-rules.mjs +30 -18
- package/scripts/utils/list-rule-ids.mjs +23 -0
- package/scripts/utils/run-rule.mjs +7 -7
- package/scripts/utils/run-standard-rule.mjs +34 -0
- package/scripts/utils/walk-cache.mjs +24 -0
- package/scripts/utils/with-lock.mjs +120 -0
- package/scripts/utils/workspaces.mjs +1 -1
- package/scripts/utils/worktree-fingerprint.mjs +30 -0
- /package/rules/abie/{fix → js}/applies/check.mjs +0 -0
- /package/rules/abie/{fix → js}/env_dns/check.mjs +0 -0
- /package/rules/abie/{fix → js}/firebase_hosting/check.mjs +0 -0
- /package/rules/abie/{fix → js}/hc_pairing/check.mjs +0 -0
- /package/rules/abie/{fix → js}/ua_http_route/check.mjs +0 -0
- /package/rules/abie/{fix → js}/ua_node_selector/check.mjs +0 -0
- /package/rules/adr/{fix → js}/hooks/check.mjs +0 -0
- /package/rules/adr/{fix → js}/hooks/template/.gitignore.snippet +0 -0
- /package/rules/bun/{fix → js}/layout/check.mjs +0 -0
- /package/rules/capacitor/{fix → js}/platforms/check.mjs +0 -0
- /package/{scripts/utils → rules/docker/js/lint}/docker-mirror.mjs +0 -0
- /package/rules/ga/{fix → js}/workflows/check.mjs +0 -0
- /package/rules/image-avif/{fix → js}/avif_generation/check.mjs +0 -0
- /package/rules/image-compress/{fix → js}/package_setup/check.mjs +0 -0
- /package/rules/js-bun-redis/{fix → js}/imports/check.mjs +0 -0
- /package/{scripts/utils → rules/js-lint/js/tooling}/knip-canonical.json +0 -0
- /package/{scripts/utils → rules/js-lint/js/tooling}/oxlint-canonical-skeleton.json +0 -0
- /package/{scripts/utils → rules/js-lint/js/tooling}/oxlint-canonical.json +0 -0
- /package/{scripts/utils → rules/js-lint/js/tooling}/oxlint-rules.tsv +0 -0
- /package/rules/k8s/{fix → js}/kubescape_exceptions/template/.kubescape-exceptions.json.snippet.json +0 -0
- /package/rules/k8s/{fix → js}/manifests/check.mjs +0 -0
- /package/rules/php/{fix → js}/tooling/check.mjs +0 -0
- /package/rules/rego/{fix → js}/applies/check.mjs +0 -0
- /package/rules/security/{fix → js}/sample_secret/check.mjs +0 -0
- /package/rules/security/{fix → js}/trufflehog/check.mjs +0 -0
- /package/rules/security/{fix → js}/trufflehog/template/.trufflehog-exclude.snippet.txt +0 -0
- /package/rules/style-lint/{fix → js}/tooling/check.mjs +0 -0
- /package/rules/tauri/{fix → js}/tooling/check.mjs +0 -0
- /package/rules/text/{fix → js}/formatting/check.mjs +0 -0
- /package/{scripts/utils → rules/vue/js/packages}/vue-forbidden-imports.mjs +0 -0
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
manifestFilePath,
|
|
29
29
|
parsePyprojectFields,
|
|
30
30
|
readPackageManifest
|
|
31
|
-
} from '
|
|
31
|
+
} from './package-manifest.mjs'
|
|
32
32
|
|
|
33
33
|
const execFileAsync = promisify(execFile)
|
|
34
34
|
|
|
@@ -247,7 +247,7 @@ async function workspaceHasRelevantChangesAgainstBase(baseRef, ws, subWorkspaces
|
|
|
247
247
|
/**
|
|
248
248
|
* Версія з маніфесту на `baseRef`.
|
|
249
249
|
* @param {string} baseRef параметр
|
|
250
|
-
* @param {import('
|
|
250
|
+
* @param {import('./package-manifest.mjs').PackageManifest} manifest параметр
|
|
251
251
|
* @returns {Promise<string | null>} результат
|
|
252
252
|
*/
|
|
253
253
|
async function readBaseVersion(baseRef, manifest) {
|
|
@@ -308,8 +308,8 @@ async function defaultGetPublishedPyPiVersion(name) {
|
|
|
308
308
|
}
|
|
309
309
|
|
|
310
310
|
/**
|
|
311
|
-
* @param {import('
|
|
312
|
-
* @param {(name: string, kind?: import('
|
|
311
|
+
* @param {import('./package-manifest.mjs').PackageManifest} manifest параметр
|
|
312
|
+
* @param {(name: string, kind?: import('./package-manifest.mjs').PackageKind) => Promise<string | null>} getPublishedVersion параметр
|
|
313
313
|
* @returns {Promise<string | null>} результат
|
|
314
314
|
*/
|
|
315
315
|
function resolvePublishedVersion(manifest, getPublishedVersion) {
|
|
@@ -319,7 +319,7 @@ function resolvePublishedVersion(manifest, getPublishedVersion) {
|
|
|
319
319
|
|
|
320
320
|
/**
|
|
321
321
|
* @param {string} name пакет
|
|
322
|
-
* @param {import('
|
|
322
|
+
* @param {import('./package-manifest.mjs').PackageKind} [kind] тип пакета
|
|
323
323
|
* @returns {Promise<string | null>} опублікована версія або null
|
|
324
324
|
*/
|
|
325
325
|
function defaultGetPublishedVersion(name, kind = 'npm') {
|
|
@@ -330,14 +330,14 @@ function defaultGetPublishedVersion(name, kind = 'npm') {
|
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
/**
|
|
333
|
-
* @returns {(name: string, kind?: import('
|
|
333
|
+
* @returns {(name: string, kind?: import('./package-manifest.mjs').PackageKind) => Promise<string | null>} стандартний резолвер
|
|
334
334
|
*/
|
|
335
335
|
function createDefaultGetPublishedVersion() {
|
|
336
336
|
return defaultGetPublishedVersion
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
/**
|
|
340
|
-
* @param {import('
|
|
340
|
+
* @param {import('./package-manifest.mjs').PackageManifest} manifest параметр
|
|
341
341
|
* @param {(msg: string) => void} pass параметр
|
|
342
342
|
* @param {(msg: string) => void} fail параметр
|
|
343
343
|
*/
|
|
@@ -375,7 +375,7 @@ async function verifyChangelogEntry(ws, version, pass, fail) {
|
|
|
375
375
|
}
|
|
376
376
|
|
|
377
377
|
/**
|
|
378
|
-
* @param {import('
|
|
378
|
+
* @param {import('./package-manifest.mjs').PackageManifest} manifest параметр
|
|
379
379
|
* @returns {string} результат
|
|
380
380
|
*/
|
|
381
381
|
function workspaceLabel(manifest) {
|
|
@@ -383,7 +383,7 @@ function workspaceLabel(manifest) {
|
|
|
383
383
|
}
|
|
384
384
|
|
|
385
385
|
/**
|
|
386
|
-
* @param {import('
|
|
386
|
+
* @param {import('./package-manifest.mjs').PackageManifest} manifest параметр
|
|
387
387
|
* @param {string} Vcurrent параметр
|
|
388
388
|
* @param {string[]} subWorkspaces параметр
|
|
389
389
|
* @param {(msg: string) => void} pass параметр
|
|
@@ -438,9 +438,9 @@ async function checkPublishedWorkspacePendingGitChanges(manifest, Vcurrent, subW
|
|
|
438
438
|
}
|
|
439
439
|
|
|
440
440
|
/**
|
|
441
|
-
* @param {import('
|
|
441
|
+
* @param {import('./package-manifest.mjs').PackageManifest} manifest параметр
|
|
442
442
|
* @param {string[]} subWorkspaces параметр
|
|
443
|
-
* @param {(name: string, kind?: import('
|
|
443
|
+
* @param {(name: string, kind?: import('./package-manifest.mjs').PackageKind) => Promise<string | null>} getPublishedVersion параметр
|
|
444
444
|
* @param {(msg: string) => void} pass параметр
|
|
445
445
|
* @param {(msg: string) => void} fail параметр
|
|
446
446
|
* @returns {Promise<void>} результат
|
|
@@ -475,7 +475,7 @@ async function checkPublishedWorkspace(manifest, subWorkspaces, getPublishedVers
|
|
|
475
475
|
|
|
476
476
|
/**
|
|
477
477
|
* @param {string} comparisonRef ref/SHA для `git diff` / `git show`
|
|
478
|
-
* @param {import('
|
|
478
|
+
* @param {import('./package-manifest.mjs').PackageManifest} manifest параметр
|
|
479
479
|
* @param {string} baseLabel параметр
|
|
480
480
|
* @param {(msg: string) => void} pass параметр
|
|
481
481
|
* @param {(msg: string) => void} fail параметр
|
|
@@ -507,7 +507,7 @@ async function checkLocalOnlyChangedWorkspace(comparisonRef, manifest, baseLabel
|
|
|
507
507
|
}
|
|
508
508
|
|
|
509
509
|
/**
|
|
510
|
-
* @param {import('
|
|
510
|
+
* @param {import('./package-manifest.mjs').PackageManifest[]} localOnly параметр
|
|
511
511
|
* @param {string[]} subWorkspaces параметр
|
|
512
512
|
* @param {(msg: string) => void} pass параметр
|
|
513
513
|
* @param {(msg: string) => void} fail параметр
|
|
@@ -543,7 +543,7 @@ async function runLocalOnlyChecks(localOnly, subWorkspaces, pass, fail) {
|
|
|
543
543
|
|
|
544
544
|
/**
|
|
545
545
|
* @param {object} [opts] опції перевірки
|
|
546
|
-
* @param {(name: string, kind?: import('
|
|
546
|
+
* @param {(name: string, kind?: import('./package-manifest.mjs').PackageKind) => Promise<string | null>} [opts.getPublishedVersion] перевизначення npm/PyPI у тестах
|
|
547
547
|
* @returns {Promise<number>} exit-код перевірки
|
|
548
548
|
*/
|
|
549
549
|
export async function check(opts = {}) {
|
|
@@ -558,11 +558,11 @@ export async function check(opts = {}) {
|
|
|
558
558
|
const isMonorepoRoot = subWorkspaces.length > 0
|
|
559
559
|
|
|
560
560
|
/**
|
|
561
|
-
@type {import('
|
|
561
|
+
@type {import('./package-manifest.mjs').PackageManifest[]}
|
|
562
562
|
*/
|
|
563
563
|
const published = []
|
|
564
564
|
/**
|
|
565
|
-
@type {import('
|
|
565
|
+
@type {import('./package-manifest.mjs').PackageManifest[]}
|
|
566
566
|
*/
|
|
567
567
|
const localOnly = []
|
|
568
568
|
|
|
@@ -8,7 +8,7 @@ import { dirname, join, relative } from 'node:path'
|
|
|
8
8
|
|
|
9
9
|
import { parse as parseToml } from 'smol-toml'
|
|
10
10
|
|
|
11
|
-
import { getMonorepoPackageRootDirs, isIgnoredWorkspaceRoot } from '
|
|
11
|
+
import { getMonorepoPackageRootDirs, isIgnoredWorkspaceRoot } from '../../../../scripts/utils/workspaces.mjs'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* @typedef {'npm' | 'python'} PackageKind
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
package/rules/docker/docker.mdc
CHANGED
|
@@ -7,7 +7,7 @@ alwaysApply: false
|
|
|
7
7
|
|
|
8
8
|
# Docker — hadolint
|
|
9
9
|
|
|
10
|
-
Для образів з Docker Hub — **`oven/bun`**, **`alpine`**, **`nginxinc/nginx-unprivileged`**, **`node`** — у **`FROM`** треба вказувати дзеркало GCR, а не pull напряму з Hub: **`mirror.gcr.io/oven/bun`**, **`mirror.gcr.io/library/alpine`**, **`mirror.gcr.io/nginxinc/nginx-unprivileged`**, **`mirror.gcr.io/library/node`**. Перевіряє **`check-docker.mjs`**, деталі в **`npm/
|
|
10
|
+
Для образів з Docker Hub — **`oven/bun`**, **`alpine`**, **`nginxinc/nginx-unprivileged`**, **`node`** — у **`FROM`** треба вказувати дзеркало GCR, а не pull напряму з Hub: **`mirror.gcr.io/oven/bun`**, **`mirror.gcr.io/library/alpine`**, **`mirror.gcr.io/nginxinc/nginx-unprivileged`**, **`mirror.gcr.io/library/node`**. Перевіряє **`check-docker.mjs`**, деталі в **`npm/rules/docker/js/lint/docker-mirror.mjs`**.
|
|
11
11
|
|
|
12
12
|
Також Dockerfile/Containerfile **має бути multistage build**: окремий build stage (залежності/компіляція) і окремий runtime stage. У фінальному stage дозволені лише мінімальні базові образи:
|
|
13
13
|
|
|
@@ -99,7 +99,7 @@ CLI **`hadolint`** приймає лише **явні шляхи** (`[DOCKERFILE
|
|
|
99
99
|
|
|
100
100
|
**Область lint-docker (вужча, ніж `check docker`):** лише файли з іменем **`Dockerfile`** та **`*.Dockerfile`** (суфікс **`.dockerfile`** без урахування регістру, наприклад **`api.Dockerfile`**). Файли **`Dockerfile.prod`**, **`Containerfile`** тощо **не** входять у **`lint-docker`**; їх ловить **`check docker`** (`check-docker.mjs`).
|
|
101
101
|
|
|
102
|
-
Обхід: **`walkDir`** з тими самими пропусками каталогів, що й **`check-docker.mjs`**. Виклик **`hadolint`**: **`PATH`**, інакше **`docker run`** — спільна логіка **`npm/
|
|
102
|
+
Обхід: **`walkDir`** з тими самими пропусками каталогів, що й **`check-docker.mjs`**. Виклик **`hadolint`**: **`PATH`**, інакше **`docker run`** — спільна логіка **`npm/rules/docker/js/lint/docker-hadolint.mjs`**.
|
|
103
103
|
|
|
104
104
|
- Канон `package.json#scripts.lint-docker`: [package.json.snippet.json](./policy/package_json/template/package.json.snippet.json)
|
|
105
105
|
|
|
@@ -109,7 +109,7 @@ CLI **`hadolint`** приймає лише **явні шляхи** (`[DOCKERFILE
|
|
|
109
109
|
|
|
110
110
|
- Канон: [lint-docker.yml.snippet.yml](./policy/lint_docker_yml/template/lint-docker.yml.snippet.yml)
|
|
111
111
|
|
|
112
|
-
Узгоджуй версію hadolint **v2.12.0** з **`HADOLINT_IMAGE`** у **`npm/
|
|
112
|
+
Узгоджуй версію hadolint **v2.12.0** з **`HADOLINT_IMAGE`** у **`npm/rules/docker/js/lint/docker-hadolint.mjs`**.
|
|
113
113
|
|
|
114
114
|
Кореневий скрипт **`lint`** (див. **`n-bun.mdc`**) **обов'язково** містить **`bun run lint-docker`**, коли в проєкті підключено правило **`docker`**.
|
|
115
115
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Запускає hadolint для Dockerfile / Containerfile у всьому репозиторії (див. docker.mdc).
|
|
3
3
|
*
|
|
4
4
|
* Додатково переконуються, що образи `oven/bun`, `alpine`, `nginx`, `node` з Docker Hub
|
|
5
|
-
* вказуються через `mirror.gcr.io` (див.
|
|
5
|
+
* вказуються через `mirror.gcr.io` (див. `./docker-mirror.mjs`).
|
|
6
6
|
*
|
|
7
7
|
* Також перевіряє, що Dockerfile/Containerfile має **multistage build** і що фінальний stage
|
|
8
8
|
* використовує дозволений runtime-образ (див. docker.mdc):
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
import { readFile } from 'node:fs/promises'
|
|
31
31
|
import { basename } from 'node:path'
|
|
32
32
|
|
|
33
|
-
import { getMirrorGcrHint, getFromImageToken } from '
|
|
34
|
-
import { lintDockerfileWithHadolint, posixRel } from '
|
|
33
|
+
import { getMirrorGcrHint, getFromImageToken } from './docker-mirror.mjs'
|
|
34
|
+
import { lintDockerfileWithHadolint, posixRel } from './docker-hadolint.mjs'
|
|
35
35
|
import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
|
|
36
36
|
import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
|
|
37
37
|
import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Спільна логіка виклику hadolint для шляхів до Dockerfile (див. docker.mdc).
|
|
3
3
|
*
|
|
4
4
|
* Відносні шляхи з прямими слешами для контейнера; спочатку hadolint з PATH,
|
|
5
|
-
* інакше docker run з образом HADOLINT_IMAGE. Використовується check
|
|
6
|
-
*
|
|
5
|
+
* інакше docker run з образом HADOLINT_IMAGE. Використовується `./check.mjs`
|
|
6
|
+
* (check-docker) та `../../lint/lint.mjs` (run-docker).
|
|
7
7
|
*/
|
|
8
8
|
import { spawnSync } from 'node:child_process'
|
|
9
9
|
import { relative, sep } from 'node:path'
|
|
10
10
|
|
|
11
|
-
import { resolveCmd } from '
|
|
11
|
+
import { resolveCmd } from '../../../../scripts/utils/resolve-cmd.mjs'
|
|
12
12
|
|
|
13
13
|
/** Тег образу для резервного запуску (узгоджуй з docker.mdc). */
|
|
14
14
|
export const HADOLINT_IMAGE = 'hadolint/hadolint:v2.12.0'
|
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
* check docker, не обробляються Dockerfile.*, Containerfile тощо — лише канонічне ім’я
|
|
6
6
|
* Dockerfile та варіанти виду app.Dockerfile (регістр суфікса не важливий).
|
|
7
7
|
*
|
|
8
|
-
* Виклик hadolint — через
|
|
8
|
+
* Виклик hadolint — через ../js/lint/docker-hadolint.mjs (PATH або docker run).
|
|
9
9
|
*/
|
|
10
10
|
import { basename } from 'node:path'
|
|
11
11
|
|
|
12
12
|
import { isRunAsCli } from '../../../scripts/cli-entry.mjs'
|
|
13
|
-
import { lintDockerfileWithHadolint, posixRel } from '
|
|
13
|
+
import { lintDockerfileWithHadolint, posixRel } from '../js/lint/docker-hadolint.mjs'
|
|
14
14
|
import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
|
|
15
15
|
import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
|
|
16
16
|
import { walkDir } from '../../../scripts/utils/walkDir.mjs'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
package/rules/ga/fix.mjs
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
package/rules/ga/lint/lint.mjs
CHANGED
|
@@ -26,9 +26,10 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import { platform } from 'node:process'
|
|
28
28
|
|
|
29
|
-
import { check as checkGa } from '../
|
|
29
|
+
import { check as checkGa } from '../js/workflows/check.mjs'
|
|
30
30
|
import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
|
|
31
31
|
import { runLintStep } from '../../../scripts/utils/run-lint-step.mjs'
|
|
32
|
+
import { withLock } from '../../../scripts/utils/with-lock.mjs'
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* Опис залежності preflight-ом: бінарник, для чого потрібен, і команди встановлення.
|
|
@@ -147,7 +148,7 @@ function preflight(dep) {
|
|
|
147
148
|
* Першу помилку від actionlint/zizmor/check повертаємо як код виходу; наступні кроки не запускаються.
|
|
148
149
|
* @returns {Promise<number>} 0 — все OK, інакше — код першого кроку, що впав
|
|
149
150
|
*/
|
|
150
|
-
|
|
151
|
+
async function runLintGaSteps() {
|
|
151
152
|
let preflightOk = true
|
|
152
153
|
for (const dep of [SHELLCHECK_PREFLIGHT, UV_PREFLIGHT, CONFTEST_PREFLIGHT]) {
|
|
153
154
|
if (!preflight(dep)) preflightOk = false
|
|
@@ -163,3 +164,5 @@ export async function runLintGaCli() {
|
|
|
163
164
|
console.log('\n▶ check-ga (rego-полісі npm/policy/ga/ + JS cross-file перевірки)')
|
|
164
165
|
return await checkGa()
|
|
165
166
|
}
|
|
167
|
+
|
|
168
|
+
export const runLintGaCli = () => withLock('lint-ga', runLintGaSteps)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
isGqlScanSourceFile,
|
|
16
16
|
shouldSkipFileForGqlScan,
|
|
17
17
|
sourceFileHasGqlTaggedTemplate
|
|
18
|
-
} from '
|
|
18
|
+
} from './graphql-gql-scan.mjs'
|
|
19
19
|
import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
|
|
20
20
|
import { runConftestBatch } from '../../../../scripts/utils/run-conftest-batch.mjs'
|
|
21
21
|
import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
|
|
@@ -1,18 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Пошук tagged template **`gql\`…\``** у джерелах для правила graphql.mdc.
|
|
3
3
|
*
|
|
4
|
-
* Для **`.vue`** береться лише вміст `<script>` / `<script setup>` (
|
|
4
|
+
* Для **`.vue`** береться лише вміст `<script>` / `<script setup>` (паралельна реалізація екстрактора;
|
|
5
|
+
* аналог у `rules/vue/js/packages/vue-forbidden-imports.mjs` — модулі не діляться кодом, щоб уникати
|
|
6
|
+
* cross-rule імпортів і тримати кожне правило самодостатнім).
|
|
5
7
|
* Семантику визначає **oxc-parser** (`program`): рекурсивний обхід AST, збіг лише для **Identifier** з іменем **`gql`** як тега шаблону.
|
|
6
8
|
*/
|
|
7
9
|
import { parseSync } from 'oxc-parser'
|
|
8
10
|
|
|
9
|
-
import {
|
|
10
|
-
contentForVueImportScan,
|
|
11
|
-
isVueImportScanSourceFile,
|
|
12
|
-
shouldSkipFileForVueImportScan
|
|
13
|
-
} from './vue-forbidden-imports.mjs'
|
|
14
|
-
|
|
15
11
|
const VUE_EXTENSION_RE = /\.vue$/u
|
|
12
|
+
const SOURCE_FILE_RE = /\.(vue|[cm]?[jt]sx?)$/u
|
|
13
|
+
const VUE_SCRIPT_BLOCK_RE = /<script\b[^>]*>([\s\S]*?)<\/script>/gi
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Витягує з SFC лише код усередині `<script>` блоків, ігноруючи `<template>` і `<style>`.
|
|
17
|
+
* @param {string} sfc вміст .vue файлу
|
|
18
|
+
* @returns {string} конкатенований текст усіх блоків `<script>` (через подвійний переклад рядка)
|
|
19
|
+
*/
|
|
20
|
+
function extractVueScriptBlocks(sfc) {
|
|
21
|
+
const chunks = []
|
|
22
|
+
VUE_SCRIPT_BLOCK_RE.lastIndex = 0
|
|
23
|
+
let m = VUE_SCRIPT_BLOCK_RE.exec(sfc)
|
|
24
|
+
while (m) {
|
|
25
|
+
chunks.push(m[1])
|
|
26
|
+
m = VUE_SCRIPT_BLOCK_RE.exec(sfc)
|
|
27
|
+
}
|
|
28
|
+
return chunks.join('\n\n')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Підбирає текст для сканування: для .vue — лише script-блоки, інакше — увесь вміст.
|
|
33
|
+
* @param {string} content сирий вміст файлу
|
|
34
|
+
* @param {string} filePath відносний шлях (для вибору режиму)
|
|
35
|
+
* @returns {string} текст для `parseSync`
|
|
36
|
+
*/
|
|
37
|
+
function contentForGqlScan(content, filePath) {
|
|
38
|
+
if (filePath.endsWith('.vue')) {
|
|
39
|
+
return extractVueScriptBlocks(content)
|
|
40
|
+
}
|
|
41
|
+
return content
|
|
42
|
+
}
|
|
16
43
|
|
|
17
44
|
/**
|
|
18
45
|
* Мова для Oxc за шляхом файлу (розширення).
|
|
@@ -81,7 +108,7 @@ function astContainsGqlTag(node) {
|
|
|
81
108
|
* @returns {boolean} true, якщо знайдено `gql`…``
|
|
82
109
|
*/
|
|
83
110
|
export function sourceFileHasGqlTaggedTemplate(content, relativePath) {
|
|
84
|
-
const scan =
|
|
111
|
+
const scan = contentForGqlScan(content, relativePath)
|
|
85
112
|
const pathForLang = virtualPathForParse(relativePath)
|
|
86
113
|
const lang = langFromPath(pathForLang)
|
|
87
114
|
try {
|
|
@@ -96,19 +123,27 @@ export function sourceFileHasGqlTaggedTemplate(content, relativePath) {
|
|
|
96
123
|
}
|
|
97
124
|
|
|
98
125
|
/**
|
|
99
|
-
* Чи підлягає файл скануванню за розширенням (
|
|
126
|
+
* Чи підлягає файл скануванню за розширенням (`.vue`, `.[cm]?[jt]sx?`).
|
|
100
127
|
* @param {string} relativePath відносний шлях
|
|
101
128
|
* @returns {boolean} true якщо файл підлягає скануванню
|
|
102
129
|
*/
|
|
103
130
|
export function isGqlScanSourceFile(relativePath) {
|
|
104
|
-
return
|
|
131
|
+
return SOURCE_FILE_RE.test(relativePath)
|
|
105
132
|
}
|
|
106
133
|
|
|
107
134
|
/**
|
|
108
|
-
* Чи пропустити файл (декларації, auto-imports) —
|
|
135
|
+
* Чи пропустити файл (декларації, auto-imports/components.d.ts) — типові generated-файли,
|
|
136
|
+
* у яких немає авторського коду з gql-тегами.
|
|
109
137
|
* @param {string} relativePosix шлях з posix-слешами
|
|
110
138
|
* @returns {boolean} true якщо файл потрібно пропустити
|
|
111
139
|
*/
|
|
112
140
|
export function shouldSkipFileForGqlScan(relativePosix) {
|
|
113
|
-
|
|
141
|
+
const base = relativePosix.split('/').pop() || ''
|
|
142
|
+
if (base === 'auto-imports.d.ts' || base === 'components.d.ts') {
|
|
143
|
+
return true
|
|
144
|
+
}
|
|
145
|
+
if (relativePosix.endsWith('.d.ts')) {
|
|
146
|
+
return true
|
|
147
|
+
}
|
|
148
|
+
return false
|
|
114
149
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Запускається лише якщо в кореневому `package.json` поле `repository`
|
|
7
7
|
* вказує на `https://github.com/nitra/...` або `https://github.com/abinbevefes/...`
|
|
8
|
-
* (інші репозиторії пропускаються без помилок — як у
|
|
8
|
+
* (інші репозиторії пропускаються без помилок — як у abie-перевірках).
|
|
9
9
|
*
|
|
10
10
|
* Очікуваний формат URL — кластерний DNS-суфікс `<cluster>.internal`:
|
|
11
11
|
* - GKE / GCP: `http://<service>.<namespace>.svc.<cluster>.internal:<port>`
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
# conftest test hasura/k8s/base/svc-hl.yaml -p npm/rules/hasura/policy/svc_hl \
|
|
9
9
|
# --namespace hasura.svc_hl
|
|
10
10
|
#
|
|
11
|
-
# Cross-file (`HASURA_GRAPHQL_ENDPOINT` ↔ YAML) — `
|
|
11
|
+
# Cross-file (`HASURA_GRAPHQL_ENDPOINT` ↔ YAML) — `js/internal_urls/check.mjs`.
|
|
12
12
|
package hasura.svc_hl
|
|
13
13
|
|
|
14
14
|
import rego.v1
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
parseProgramOrNull,
|
|
28
28
|
templateQuasisText,
|
|
29
29
|
walkAstWithAncestors
|
|
30
|
-
} from '
|
|
30
|
+
} from '../../../../scripts/utils/ast-scan-utils.mjs'
|
|
31
31
|
|
|
32
32
|
const SOURCE_FILE_RE = /\.([cm]?[jt]sx?)$/u
|
|
33
33
|
const BUN_SQL_IMPORT_RE = /\bimport\s*\{[\s\S]*?\b(sql|SQL)\b[\s\S]*?\}\s*from\s*["']bun["']/u
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
isBunSqlScanSourceFile,
|
|
49
49
|
textHasBunSqlImport,
|
|
50
50
|
textHasPgLibImport
|
|
51
|
-
} from '
|
|
51
|
+
} from './bun-sql-scan.mjs'
|
|
52
52
|
import { findAllPackageJsonPaths } from '../../../../scripts/utils/find-package-json-paths.mjs'
|
|
53
53
|
import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
|
|
54
54
|
import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Канон надходить через --data: { "template": { "deny": ... } }
|
|
4
4
|
# Структура --data сформована з template/package.json.deny.json.
|
|
5
5
|
# AST-скан коду (`import`/`require`/dynamic `import()` тих самих пакетів)
|
|
6
|
-
# лишається у `js-bun-redis/
|
|
6
|
+
# лишається у `js-bun-redis/js/imports/check.mjs`.
|
|
7
7
|
package js_bun_redis.package_json
|
|
8
8
|
|
|
9
9
|
import rego.v1
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|