@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.
Files changed (116) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/README.md +5 -5
  3. package/bin/n-cursor.js +16 -21
  4. package/package.json +1 -1
  5. package/rules/abie/abie.mdc +12 -4
  6. package/rules/abie/fix.mjs +15 -0
  7. package/rules/abie/policy/base_deployment_preem/base_deployment_preem.rego +9 -11
  8. package/rules/abie/policy/health_check_policy/health_check_policy.rego +9 -10
  9. package/rules/abie/policy/http_route_base/http_route_base.rego +7 -8
  10. package/rules/abie/utils/k8s-tree.mjs +1 -1
  11. package/rules/adr/adr.mdc +1 -1
  12. package/rules/adr/fix.mjs +15 -0
  13. package/rules/bun/fix.mjs +15 -0
  14. package/rules/capacitor/fix.mjs +15 -0
  15. package/rules/changelog/changelog.mdc +1 -1
  16. package/rules/changelog/fix.mjs +15 -0
  17. package/rules/changelog/{fix → js}/consistency/check.mjs +16 -16
  18. package/{scripts/utils → rules/changelog/js/consistency}/package-manifest.mjs +1 -1
  19. package/rules/ci4/fix.mjs +15 -0
  20. package/rules/docker/docker.mdc +3 -3
  21. package/rules/docker/fix.mjs +15 -0
  22. package/rules/docker/{fix → js}/lint/check.mjs +3 -3
  23. package/{scripts/utils → rules/docker/js/lint}/docker-hadolint.mjs +3 -3
  24. package/rules/docker/lint/lint.mjs +2 -2
  25. package/rules/efes/fix.mjs +15 -0
  26. package/rules/feedback/fix.mjs +15 -0
  27. package/rules/ga/fix.mjs +15 -0
  28. package/rules/ga/lint/lint.mjs +5 -2
  29. package/rules/graphql/fix.mjs +15 -0
  30. package/rules/graphql/{fix → js}/tooling/check.mjs +1 -1
  31. package/{scripts/utils → rules/graphql/js/tooling}/graphql-gql-scan.mjs +47 -12
  32. package/rules/hasura/fix.mjs +15 -0
  33. package/rules/hasura/{fix → js}/internal_urls/check.mjs +1 -1
  34. package/rules/hasura/policy/svc_hl/svc_hl.rego +1 -1
  35. package/rules/image-avif/fix.mjs +15 -0
  36. package/rules/image-compress/fix.mjs +15 -0
  37. package/rules/js-bun-db/fix.mjs +15 -0
  38. package/{scripts/utils → rules/js-bun-db/js/safety}/bun-sql-scan.mjs +1 -1
  39. package/rules/js-bun-db/{fix → js}/safety/check.mjs +1 -1
  40. package/rules/js-bun-redis/fix.mjs +15 -0
  41. package/rules/js-bun-redis/policy/package_json/package_json.rego +1 -1
  42. package/rules/js-lint/fix.mjs +15 -0
  43. package/rules/js-lint/{fix → js}/tooling/check.mjs +3 -15
  44. package/{scripts/utils → rules/js-lint/js/tooling}/rebuild-oxlint-canonical.mjs +1 -1
  45. package/rules/js-lint/js-lint.mdc +2 -2
  46. package/rules/js-mssql/fix.mjs +15 -0
  47. package/rules/js-mssql/{fix → js}/deps/check.mjs +1 -1
  48. package/{scripts/utils → rules/js-mssql/js/deps}/mssql-pool-scan.mjs +1 -1
  49. package/rules/js-run/fix.mjs +15 -0
  50. package/{scripts/utils → rules/js-run/js/runtime}/bunyan-imports.mjs +1 -1
  51. package/{scripts/utils → rules/js-run/js/runtime}/check-env-scan.mjs +1 -1
  52. package/rules/js-run/{fix → js}/runtime/check.mjs +5 -5
  53. package/{scripts/utils → rules/js-run/js/runtime}/conn-file-rules.mjs +1 -1
  54. package/{scripts/utils → rules/js-run/js/runtime}/conn-imports-scan.mjs +1 -1
  55. package/{scripts/utils → rules/js-run/js/runtime}/promise-settimeout-scan.mjs +1 -1
  56. package/rules/k8s/fix.mjs +15 -0
  57. package/rules/k8s/k8s.mdc +2 -2
  58. package/rules/nginx-default-tpl/fix.mjs +15 -0
  59. package/rules/nginx-default-tpl/{fix → js}/template/check.mjs +1 -1
  60. package/rules/npm-module/fix.mjs +15 -0
  61. package/rules/npm-module/{fix → js}/package_structure/check.mjs +11 -1
  62. package/rules/php/fix.mjs +15 -0
  63. package/rules/rego/fix.mjs +15 -0
  64. package/rules/security/fix.mjs +15 -0
  65. package/rules/security/security.mdc +2 -2
  66. package/rules/style-lint/fix.mjs +15 -0
  67. package/rules/tauri/fix.mjs +15 -0
  68. package/rules/test/auto.md +1 -0
  69. package/rules/test/fix.mjs +15 -0
  70. package/rules/test/js/location/check.mjs +77 -0
  71. package/rules/test/test.mdc +60 -0
  72. package/rules/text/fix.mjs +15 -0
  73. package/rules/vue/fix.mjs +15 -0
  74. package/rules/vue/{fix → js}/packages/check.mjs +2 -2
  75. package/rules/vue/vue.mdc +1 -1
  76. package/scripts/auto-rules.mjs +3 -3
  77. package/scripts/sync-claude-config.mjs +2 -2
  78. package/scripts/utils/ast-scan-utils.mjs +3 -2
  79. package/scripts/utils/discover-checkable-rules.mjs +30 -18
  80. package/scripts/utils/list-rule-ids.mjs +23 -0
  81. package/scripts/utils/run-rule.mjs +7 -7
  82. package/scripts/utils/run-standard-rule.mjs +34 -0
  83. package/scripts/utils/walk-cache.mjs +24 -0
  84. package/scripts/utils/with-lock.mjs +120 -0
  85. package/scripts/utils/workspaces.mjs +1 -1
  86. package/scripts/utils/worktree-fingerprint.mjs +30 -0
  87. /package/rules/abie/{fix → js}/applies/check.mjs +0 -0
  88. /package/rules/abie/{fix → js}/env_dns/check.mjs +0 -0
  89. /package/rules/abie/{fix → js}/firebase_hosting/check.mjs +0 -0
  90. /package/rules/abie/{fix → js}/hc_pairing/check.mjs +0 -0
  91. /package/rules/abie/{fix → js}/ua_http_route/check.mjs +0 -0
  92. /package/rules/abie/{fix → js}/ua_node_selector/check.mjs +0 -0
  93. /package/rules/adr/{fix → js}/hooks/check.mjs +0 -0
  94. /package/rules/adr/{fix → js}/hooks/template/.gitignore.snippet +0 -0
  95. /package/rules/bun/{fix → js}/layout/check.mjs +0 -0
  96. /package/rules/capacitor/{fix → js}/platforms/check.mjs +0 -0
  97. /package/{scripts/utils → rules/docker/js/lint}/docker-mirror.mjs +0 -0
  98. /package/rules/ga/{fix → js}/workflows/check.mjs +0 -0
  99. /package/rules/image-avif/{fix → js}/avif_generation/check.mjs +0 -0
  100. /package/rules/image-compress/{fix → js}/package_setup/check.mjs +0 -0
  101. /package/rules/js-bun-redis/{fix → js}/imports/check.mjs +0 -0
  102. /package/{scripts/utils → rules/js-lint/js/tooling}/knip-canonical.json +0 -0
  103. /package/{scripts/utils → rules/js-lint/js/tooling}/oxlint-canonical-skeleton.json +0 -0
  104. /package/{scripts/utils → rules/js-lint/js/tooling}/oxlint-canonical.json +0 -0
  105. /package/{scripts/utils → rules/js-lint/js/tooling}/oxlint-rules.tsv +0 -0
  106. /package/rules/k8s/{fix → js}/kubescape_exceptions/template/.kubescape-exceptions.json.snippet.json +0 -0
  107. /package/rules/k8s/{fix → js}/manifests/check.mjs +0 -0
  108. /package/rules/php/{fix → js}/tooling/check.mjs +0 -0
  109. /package/rules/rego/{fix → js}/applies/check.mjs +0 -0
  110. /package/rules/security/{fix → js}/sample_secret/check.mjs +0 -0
  111. /package/rules/security/{fix → js}/trufflehog/check.mjs +0 -0
  112. /package/rules/security/{fix → js}/trufflehog/template/.trufflehog-exclude.snippet.txt +0 -0
  113. /package/rules/style-lint/{fix → js}/tooling/check.mjs +0 -0
  114. /package/rules/tauri/{fix → js}/tooling/check.mjs +0 -0
  115. /package/rules/text/{fix → js}/formatting/check.mjs +0 -0
  116. /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 '../../../../scripts/utils/package-manifest.mjs'
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('../../../../scripts/utils/package-manifest.mjs').PackageManifest} manifest параметр
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('../../../../scripts/utils/package-manifest.mjs').PackageManifest} manifest параметр
312
- * @param {(name: string, kind?: import('../../../../scripts/utils/package-manifest.mjs').PackageKind) => Promise<string | null>} getPublishedVersion параметр
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('../../../../scripts/utils/package-manifest.mjs').PackageKind} [kind] тип пакета
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('../../../../scripts/utils/package-manifest.mjs').PackageKind) => Promise<string | null>} стандартний резолвер
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('../../../../scripts/utils/package-manifest.mjs').PackageManifest} manifest параметр
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('../../../../scripts/utils/package-manifest.mjs').PackageManifest} manifest параметр
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('../../../../scripts/utils/package-manifest.mjs').PackageManifest} manifest параметр
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('../../../../scripts/utils/package-manifest.mjs').PackageManifest} manifest параметр
441
+ * @param {import('./package-manifest.mjs').PackageManifest} manifest параметр
442
442
  * @param {string[]} subWorkspaces параметр
443
- * @param {(name: string, kind?: import('../../../../scripts/utils/package-manifest.mjs').PackageKind) => Promise<string | null>} getPublishedVersion параметр
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('../../../../scripts/utils/package-manifest.mjs').PackageManifest} manifest параметр
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('../../../../scripts/utils/package-manifest.mjs').PackageManifest[]} localOnly параметр
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('../../../../scripts/utils/package-manifest.mjs').PackageKind) => Promise<string | null>} [opts.getPublishedVersion] перевизначення npm/PyPI у тестах
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('../../../../scripts/utils/package-manifest.mjs').PackageManifest[]}
561
+ @type {import('./package-manifest.mjs').PackageManifest[]}
562
562
  */
563
563
  const published = []
564
564
  /**
565
- @type {import('../../../../scripts/utils/package-manifest.mjs').PackageManifest[]}
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 './workspaces.mjs'
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
+ }
@@ -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/scripts/utils/docker-mirror.mjs`**.
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/scripts/utils/docker-hadolint.mjs`**.
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/scripts/utils/docker-hadolint.mjs`**.
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` (див. `utils/docker-mirror.mjs`).
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 '../../../../scripts/utils/docker-mirror.mjs'
34
- import { lintDockerfileWithHadolint, posixRel } from '../../../../scripts/utils/docker-hadolint.mjs'
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-docker.mjs та
6
- * run-docker.mjs.
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 './resolve-cmd.mjs'
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 — через utils/docker-hadolint.mjs (PATH або docker run).
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 '../../../scripts/utils/docker-hadolint.mjs'
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
+ }
@@ -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
+ }
@@ -26,9 +26,10 @@
26
26
  */
27
27
  import { platform } from 'node:process'
28
28
 
29
- import { check as checkGa } from '../fix/workflows/check.mjs'
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
- export async function runLintGaCli() {
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 '../../../../scripts/utils/graphql-gql-scan.mjs'
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>` (спільна логіка з **vue-forbidden-imports**).
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 = contentForVueImportScan(content, relativePath)
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
- * Чи підлягає файл скануванню за розширенням (узгоджено з vue-import scan).
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 isVueImportScanSourceFile(relativePath)
131
+ return SOURCE_FILE_RE.test(relativePath)
105
132
  }
106
133
 
107
134
  /**
108
- * Чи пропустити файл (декларації, auto-imports) — ті самі критерії, що для vue-import scan.
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
- return shouldSkipFileForVueImportScan(relativePosix)
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
- * (інші репозиторії пропускаються без помилок — як у check-abie).
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) — `fix/internal_urls/check.mjs`.
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 './ast-scan-utils.mjs'
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 '../../../../scripts/utils/bun-sql-scan.mjs'
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/fix/imports/check.mjs`.
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
+ }