@nitra/cursor 1.11.3 → 1.11.6
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 +32 -3
- package/bin/n-cursor.js +40 -6
- package/package.json +2 -1
- package/rules/abie/js/applies/check.mjs +4 -4
- package/rules/abie/js/env_dns/check.mjs +1 -1
- package/rules/abie/js/firebase_hosting/check.mjs +1 -1
- package/rules/abie/js/hc_pairing/check.mjs +3 -3
- package/rules/abie/js/ua_http_route/check.mjs +3 -3
- package/rules/abie/js/ua_node_selector/check.mjs +4 -2
- package/rules/abie/policy/base_deployment_preem/target.json +1 -5
- package/rules/abie/utils/enabled.mjs +1 -1
- package/rules/abie/utils/env-dns.mjs +4 -4
- package/rules/abie/utils/http-route.mjs +5 -5
- package/rules/abie/utils/k8s-tree.mjs +23 -15
- package/rules/abie/utils/kustomization-patches.mjs +20 -20
- package/rules/abie/utils/overlay-paths.mjs +8 -8
- package/rules/abie/utils/yaml.mjs +4 -4
- package/rules/adr/adr.mdc +2 -2
- package/rules/adr/js/hooks/check.mjs +5 -5
- package/rules/docker/docker.mdc +2 -2
- package/rules/docker/js/run.mjs +3 -2
- package/rules/docker/policy/package_json/package_json.rego +1 -1
- package/rules/ga/js/lint.mjs +3 -26
- package/rules/hasura/js/internal_urls/check.mjs +1 -1
- package/rules/js-bun-redis/js/imports/check.mjs +5 -1
- package/rules/js-run/js/runtime/check.mjs +4 -1
- package/rules/k8s/js/run.mjs +3 -2
- package/rules/k8s/k8s.mdc +2 -4
- package/rules/k8s/policy/base_manifest/target.json +1 -5
- package/rules/nginx-default-tpl/js/template/check.mjs +4 -2
- package/rules/npm-module/js/package_structure/check.mjs +8 -3
- package/rules/npm-module/npm-module.mdc +3 -3
- package/rules/rego/js/applies/check.mjs +2 -2
- package/rules/rego/js/lint.mjs +4 -1
- package/rules/rego/policy/package_json/package_json.rego +5 -3
- package/rules/rego/rego.mdc +3 -3
- package/rules/style-lint/js/tooling/check.mjs +1 -1
- package/rules/style-lint/style-lint.mdc +1 -1
- package/rules/tauri/js/tooling/check.mjs +3 -1
- package/rules/text/js/formatting/check.mjs +8 -24
- package/rules/text/js/lint.mjs +34 -0
- package/rules/text/js/run-shellcheck.mjs +2 -2
- package/rules/text/js/run-v8r.mjs +2 -2
- package/rules/text/text.mdc +5 -5
- package/schemas/v8r-catalog.json +6 -0
- package/scripts/auto-skills.mjs +3 -7
- package/scripts/utils/discover-checkable-rules.mjs +4 -3
- package/scripts/utils/resolve-target-files.mjs +1 -1
- package/scripts/utils/run-lint-step.mjs +33 -0
- package/scripts/utils/run-rule.mjs +5 -3
- package/skills/abie-clean/SKILL.md +13 -11
- package/skills/adr-normalize/SKILL.md +0 -1
- package/skills/fix/SKILL.md +3 -7
- package/rules/abie/policy/base_deployment_preem/base_deployment_preem_test.rego +0 -60
- package/rules/abie/policy/clean_merged_ignore_branches/clean_merged_ignore_branches_test.rego +0 -48
- package/rules/abie/policy/health_check_policy/health_check_policy_test.rego +0 -99
- package/rules/abie/policy/http_route_base/http_route_base_test.rego +0 -64
- package/rules/bun/policy/package_json/package_json_test.rego +0 -109
- package/rules/docker/policy/lint_docker_yml/lint_docker_yml_test.rego +0 -104
- package/rules/docker/policy/package_json/package_json_test.rego +0 -42
- package/rules/graphql/policy/vscode_extensions/vscode_extensions_test.rego +0 -34
- package/rules/image-avif/policy/package_json/package_json_test.rego +0 -69
- package/rules/js-lint/policy/package_json/package_json_test.rego +0 -130
- package/rules/js-run/policy/jsconfig/jsconfig_test.rego +0 -88
- package/rules/k8s/policy/base_kustomization/base_kustomization_test.rego +0 -73
- package/rules/k8s/policy/base_manifest/base_manifest_test.rego +0 -94
- package/rules/k8s/policy/gateway/gateway_test.rego +0 -122
- package/rules/k8s/policy/hasura_configmap/hasura_configmap_test.rego +0 -49
- package/rules/k8s/policy/hasura_httproute/hasura_httproute_test.rego +0 -148
- package/rules/k8s/policy/hpa_pdb/hpa_pdb_test.rego +0 -101
- package/rules/k8s/policy/kustomization/kustomization_test.rego +0 -128
- package/rules/k8s/policy/manifest/manifest_test.rego +0 -309
- package/rules/k8s/policy/svc_hl_yaml/svc_hl_yaml_test.rego +0 -42
- package/rules/k8s/policy/svc_yaml/svc_yaml_test.rego +0 -41
- package/rules/nginx-default-tpl/policy/vscode_extensions/vscode_extensions_test.rego +0 -30
- package/rules/nginx-default-tpl/policy/vscode_settings/vscode_settings_test.rego +0 -53
- package/rules/npm-module/policy/npm_package_json/npm_package_json_test.rego +0 -81
- package/rules/rego/policy/package_json/package_json_test.rego +0 -42
- package/rules/rego/policy/vscode_extensions/vscode_extensions_test.rego +0 -34
- package/rules/rego/policy/vscode_settings/vscode_settings_test.rego +0 -55
- package/rules/style-lint/policy/vscode_extensions/vscode_extensions_test.rego +0 -39
- package/rules/style-lint/policy/vscode_settings/vscode_settings_test.rego +0 -49
- package/rules/tauri/policy/vscode_extensions/vscode_extensions_test.rego +0 -44
- package/rules/text/policy/markdownlint/markdownlint_test.rego +0 -98
- package/rules/text/policy/vscode_extensions/vscode_extensions_test.rego +0 -51
- package/rules/text/policy/vscode_settings/vscode_settings_test.rego +0 -85
package/rules/adr/adr.mdc
CHANGED
|
@@ -39,7 +39,7 @@ Stop-hook `normalize-decisions.sh` спрацьовує на тому самом
|
|
|
39
39
|
LLM повертає масив операцій:
|
|
40
40
|
|
|
41
41
|
| `op` | Семантика | Поля |
|
|
42
|
-
|
|
42
|
+
| --- | --- | --- |
|
|
43
43
|
| `delete` | Чернетка тривіальна / повністю покрита іншим clean-ADR-ом. | `file`, `reason` |
|
|
44
44
|
| `rewrite` | Чернетка стає окремим clean-файлом: frontmatter знімається, ім'я → `<slug>.md`, додаються `**Status: Accepted**` і `**Date:**` з `captured`. | `file`, `slug`, `content` |
|
|
45
45
|
| `merge-into` | Чернетка повторює тему вже існуючого clean-файлу; дописуємо `## Update YYYY-MM-DD` у кінець `target`. | `file`, `target`, `additions` |
|
|
@@ -55,7 +55,7 @@ LLM повертає масив операцій:
|
|
|
55
55
|
Інший LLM CLI, який запустить normalize, успадковує `ADR_NORMALIZE_RUNNING=1` — внутрішній Stop-hook вийде відразу. Доступні ENV:
|
|
56
56
|
|
|
57
57
|
| Змінна | Default | Призначення |
|
|
58
|
-
|
|
58
|
+
| --- | --- | --- |
|
|
59
59
|
| `ADR_NORMALIZE_THRESHOLD` | `30` | Поріг чернеток для запуску фази. |
|
|
60
60
|
| `ADR_NORMALIZE_BATCH` | `30` | Максимум чернеток у одному виклику LLM. |
|
|
61
61
|
| `ADR_NORMALIZE_MIN_INTERVAL_HOURS` | `6` | Мінімум між спробами (навіть якщо поріг). |
|
|
@@ -79,7 +79,7 @@ function gitignoreLineCoversHookLog(line, logPath) {
|
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
81
|
* Перевіряє наявність і канонічність одного hook-скрипта.
|
|
82
|
-
* @param {import('
|
|
82
|
+
* @param {import('../../../../scripts/utils/check-reporter.mjs').CheckReporter} reporter репортер для збору результатів
|
|
83
83
|
* @param {string} scriptName базове ім'я скрипта (наприклад `capture-decisions.sh`)
|
|
84
84
|
* @returns {Promise<void>}
|
|
85
85
|
*/
|
|
@@ -108,7 +108,7 @@ async function checkHookScript(reporter, scriptName) {
|
|
|
108
108
|
* `.claude/settings.local.json`. Структуру (`hooks.Stop[]` містить групу з
|
|
109
109
|
* `capture-decisions.sh`; `settings.local.json` не дублює) валідують
|
|
110
110
|
* `npm/policy/adr/settings_json/` і `npm/policy/adr/settings_local_json/`.
|
|
111
|
-
* @param {import('
|
|
111
|
+
* @param {import('../../../../scripts/utils/check-reporter.mjs').CheckReporter} reporter репортер
|
|
112
112
|
*/
|
|
113
113
|
function checkProjectSettings(reporter) {
|
|
114
114
|
const { pass, fail } = reporter
|
|
@@ -121,7 +121,7 @@ function checkProjectSettings(reporter) {
|
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
123
|
* Перевіряє `.gitignore` на ігнорування лог-файлу одного хука.
|
|
124
|
-
* @param {import('
|
|
124
|
+
* @param {import('../../../../scripts/utils/check-reporter.mjs').CheckReporter} reporter репортер для збору результатів
|
|
125
125
|
* @param {string} logName базове ім'я лог-файлу (наприклад `capture-decisions.log`)
|
|
126
126
|
* @param {string} gitignoreContent попередньо прочитаний вміст `.gitignore`
|
|
127
127
|
* @returns {void}
|
|
@@ -142,7 +142,7 @@ function checkGitignoreForLog(reporter, logName, gitignoreContent) {
|
|
|
142
142
|
|
|
143
143
|
/**
|
|
144
144
|
* Перевіряє `.gitignore` для всіх hook-логів одним проходом.
|
|
145
|
-
* @param {import('
|
|
145
|
+
* @param {import('../../../../scripts/utils/check-reporter.mjs').CheckReporter} reporter репортер для збору результатів
|
|
146
146
|
* @returns {Promise<void>}
|
|
147
147
|
*/
|
|
148
148
|
async function checkGitignore(reporter) {
|
|
@@ -182,7 +182,7 @@ function isBinaryInPath(name) {
|
|
|
182
182
|
/**
|
|
183
183
|
* Інформативна перевірка: чи доступний бодай один LLM CLI (`claude` або `cursor-agent`).
|
|
184
184
|
* Якщо жодного немає — це warning (`pass` з підказкою), бо хук просто мовчки no-op'ає.
|
|
185
|
-
* @param {import('
|
|
185
|
+
* @param {import('../../../../scripts/utils/check-reporter.mjs').CheckReporter} reporter репортер для збору результатів
|
|
186
186
|
* @returns {void}
|
|
187
187
|
*/
|
|
188
188
|
function checkLlmCliAvailable(reporter) {
|
package/rules/docker/docker.mdc
CHANGED
|
@@ -97,7 +97,7 @@ CMD ["./app"]
|
|
|
97
97
|
|
|
98
98
|
## lint-docker
|
|
99
99
|
|
|
100
|
-
CLI **`hadolint`** приймає лише **явні шляхи** (`[DOCKERFILE...]` у **`hadolint --help`**); обхід репозиторію робить
|
|
100
|
+
CLI **`hadolint`** приймає лише **явні шляхи** (`[DOCKERFILE...]` у **`hadolint --help`**); обхід репозиторію робить CLI **`n-cursor lint-docker`** (реалізація — **`npm/rules/docker/js/run.mjs`**).
|
|
101
101
|
|
|
102
102
|
**Область lint-docker (вужча, ніж `check docker`):** лише файли з іменем **`Dockerfile`** та **`*.Dockerfile`** (суфікс **`.dockerfile`** без урахування регістру, наприклад **`api.Dockerfile`**). Файли **`Dockerfile.prod`**, **`Containerfile`** тощо **не** входять у **`lint-docker`**; їх ловить **`check docker`** (`check-docker.mjs`).
|
|
103
103
|
|
|
@@ -106,7 +106,7 @@ CLI **`hadolint`** приймає лише **явні шляхи** (`[DOCKERFILE
|
|
|
106
106
|
```json title="package.json"
|
|
107
107
|
{
|
|
108
108
|
"scripts": {
|
|
109
|
-
"lint-docker": "
|
|
109
|
+
"lint-docker": "n-cursor lint-docker"
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
```
|
package/rules/docker/js/run.mjs
CHANGED
|
@@ -47,9 +47,10 @@ export async function findLintDockerfilePaths(root, ignorePaths = []) {
|
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Запуск hadolint по Dockerfile та *.Dockerfile.
|
|
50
|
+
* Експортовано як `runLintDocker` — використовується з `bin/n-cursor.js` як підкоманда `lint-docker`.
|
|
50
51
|
* @returns {Promise<number>} 0 — OK, 1 — зауваження або помилка
|
|
51
52
|
*/
|
|
52
|
-
async function
|
|
53
|
+
export async function runLintDocker() {
|
|
53
54
|
const reporter = createCheckReporter()
|
|
54
55
|
const { pass, fail } = reporter
|
|
55
56
|
|
|
@@ -80,5 +81,5 @@ async function main() {
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
if (isRunAsCli()) {
|
|
83
|
-
process.exitCode = await
|
|
84
|
+
process.exitCode = await runLintDocker()
|
|
84
85
|
}
|
|
@@ -19,7 +19,7 @@ package docker.package_json
|
|
|
19
19
|
|
|
20
20
|
import rego.v1
|
|
21
21
|
|
|
22
|
-
canonical_lint_docker := "
|
|
22
|
+
canonical_lint_docker := "n-cursor lint-docker"
|
|
23
23
|
|
|
24
24
|
lint_docker_template := concat(" ", [
|
|
25
25
|
"package.json: scripts.lint-docker має бути %q",
|
package/rules/ga/js/lint.mjs
CHANGED
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
*
|
|
20
20
|
* Експортовано окремо `runLintGaCli` — використовується з `bin/n-cursor.js` як підкоманда `lint-ga`.
|
|
21
21
|
*/
|
|
22
|
-
import { spawnSync } from 'node:child_process'
|
|
23
22
|
import { platform } from 'node:process'
|
|
24
23
|
|
|
25
24
|
import { check as checkGa } from './workflows/check.mjs'
|
|
26
25
|
import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
|
|
26
|
+
import { runLintStep } from '../../../scripts/utils/run-lint-step.mjs'
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Опис залежності preflight-ом: бінарник, для чого потрібен, і команди встановлення.
|
|
@@ -112,29 +112,6 @@ function preflight(dep) {
|
|
|
112
112
|
return false
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
/**
|
|
116
|
-
* Запускає крок lint-ga з відображенням команди користувачу. Stdout/stderr дочірнього процесу
|
|
117
|
-
* передається користувачу як є (`stdio: 'inherit'`), щоб виглядало як прямий виклик у shell.
|
|
118
|
-
* @param {string} title заголовок для логу (наприклад `actionlint`)
|
|
119
|
-
* @param {string} cmd ім'я команди (`bunx`, `uvx`)
|
|
120
|
-
* @param {string[]} args аргументи команди
|
|
121
|
-
* @returns {number} код виходу дочірнього процесу (0 — OK, інше — помилка)
|
|
122
|
-
*/
|
|
123
|
-
function runStep(title, cmd, args) {
|
|
124
|
-
console.log(`\n▶ ${title}: ${cmd} ${args.join(' ')}`)
|
|
125
|
-
const resolved = resolveCmd(cmd)
|
|
126
|
-
if (!resolved) {
|
|
127
|
-
console.error(`❌ ${cmd} не знайдено в PATH (${title}).`)
|
|
128
|
-
return 127
|
|
129
|
-
}
|
|
130
|
-
const r = spawnSync(resolved, args, { stdio: 'inherit', env: process.env })
|
|
131
|
-
if (r.error) {
|
|
132
|
-
console.error(`❌ Не вдалося запустити ${cmd}: ${r.error.message}`)
|
|
133
|
-
return 1
|
|
134
|
-
}
|
|
135
|
-
return r.status ?? 1
|
|
136
|
-
}
|
|
137
|
-
|
|
138
115
|
/**
|
|
139
116
|
* Виконує канонічний `lint-ga` з preflight-перевірками і делегує до `check-ga.check()`.
|
|
140
117
|
*
|
|
@@ -160,10 +137,10 @@ export async function runLintGaCli() {
|
|
|
160
137
|
}
|
|
161
138
|
if (!preflightOk) return 1
|
|
162
139
|
|
|
163
|
-
const actionlintCode =
|
|
140
|
+
const actionlintCode = runLintStep('actionlint', 'bunx', ['github-actionlint'])
|
|
164
141
|
if (actionlintCode !== 0) return actionlintCode
|
|
165
142
|
|
|
166
|
-
const zizmorCode =
|
|
143
|
+
const zizmorCode = runLintStep('zizmor', 'uvx', ['zizmor', '--offline', '--collect=workflows', '.'])
|
|
167
144
|
if (zizmorCode !== 0) return zizmorCode
|
|
168
145
|
|
|
169
146
|
console.log('\n▶ check-ga (rego-полісі npm/policy/ga/ + JS cross-file перевірки)')
|
|
@@ -143,7 +143,7 @@ async function checkEnvFile(relPath, expected, reporter) {
|
|
|
143
143
|
const value = m[1].trim()
|
|
144
144
|
const parsed = parseInternalHasuraEndpoint(value)
|
|
145
145
|
if (!parsed.ok) {
|
|
146
|
-
const example =
|
|
146
|
+
const example = 'https://<service>.<namespace>.svc.<cluster>.internal:<port>'
|
|
147
147
|
fail(
|
|
148
148
|
`${relPath}: HASURA_GRAPHQL_ENDPOINT="${value}" — потрібен внутрішній кластерний URL виду ${example} (hasura.mdc)`
|
|
149
149
|
)
|
|
@@ -16,7 +16,11 @@ import { join, relative } from 'node:path'
|
|
|
16
16
|
|
|
17
17
|
import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
|
|
18
18
|
import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
findRedisImportsInText,
|
|
21
|
+
isRedisScanSourceFile,
|
|
22
|
+
shouldSkipFileForRedisScan
|
|
23
|
+
} from '../../../../scripts/utils/redis-imports.mjs'
|
|
20
24
|
import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
|
|
21
25
|
|
|
22
26
|
/**
|
|
@@ -49,7 +49,10 @@ import {
|
|
|
49
49
|
resolveConnDirFromPackageJson
|
|
50
50
|
} from '../../../../scripts/utils/conn-imports-scan.mjs'
|
|
51
51
|
import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
|
|
52
|
-
import {
|
|
52
|
+
import {
|
|
53
|
+
findPromiseSetTimeoutInText,
|
|
54
|
+
isPromiseSetTimeoutScanSourceFile
|
|
55
|
+
} from '../../../../scripts/utils/promise-settimeout-scan.mjs'
|
|
53
56
|
import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
|
|
54
57
|
import { getMonorepoPackageRootDirs } from '../../../../scripts/utils/workspaces.mjs'
|
|
55
58
|
|
package/rules/k8s/js/run.mjs
CHANGED
|
@@ -146,9 +146,10 @@ function runKubescape(dirs) {
|
|
|
146
146
|
|
|
147
147
|
/**
|
|
148
148
|
* Головна точка входу: kubeconform + kubescape для усіх знайдених дерев `k8s`.
|
|
149
|
+
* Експортовано як `runLintK8s` — використовується з `bin/n-cursor.js` як підкоманда `lint-k8s`.
|
|
149
150
|
* @returns {Promise<number>} код виходу для `process.exitCode` (0 — успіх або пропуск)
|
|
150
151
|
*/
|
|
151
|
-
async function
|
|
152
|
+
export async function runLintK8s() {
|
|
152
153
|
const root = process.cwd()
|
|
153
154
|
const ignorePaths = await loadCursorIgnorePaths(root)
|
|
154
155
|
const dirs = await findK8sRoots(root, ignorePaths)
|
|
@@ -169,5 +170,5 @@ async function main() {
|
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
if (isRunAsCli()) {
|
|
172
|
-
process.exitCode = await
|
|
173
|
+
process.exitCode = await runLintK8s()
|
|
173
174
|
}
|
package/rules/k8s/k8s.mdc
CHANGED
|
@@ -38,20 +38,18 @@ alwaysApply: false
|
|
|
38
38
|
|
|
39
39
|
**kubescape:** типово **`kubescape scan <каталог-k8s>`**; поріг серйозності підлаштуй під проєкт (наприклад **`--severity-threshold high`**). Перший запуск може завантажувати артефакти — у CI потрібна мережа або [offline](https://github.com/kubescape/kubescape#readme). На відміну від kubeconform, у **kubescape scan** немає прапорця **`-kubernetes-version`**: перевірка йде за **framework/control** (NSA, MITRE, CIS тощо), а не проти OpenAPI-схеми конкретного релізу Kubernetes. **Орієнтир** для репозиторію той самий, що й для kubeconform — кластер **v1.33.9** (див. **`-kubernetes-version 1.33.9`** вище); для CIS і подібних наближень обирай актуальний framework під політику команди (**`kubescape list frameworks`**, див. [CLI reference](https://github.com/kubescape/kubescape/blob/master/docs/cli-reference.md)).
|
|
40
40
|
|
|
41
|
-
У репозиторії пакета **`@nitra/cursor`** скрипт **`lint-k8s`** делегує
|
|
41
|
+
У репозиторії пакета **`@nitra/cursor`** скрипт **`lint-k8s`** делегує до CLI **`n-cursor lint-k8s`** (реалізація — **`npm/rules/k8s/js/run.mjs`**). У інших проєктах достатньо встановити **`@nitra/cursor`** у `devDependencies` — бінарка **`n-cursor`** буде у **`node_modules/.bin/`**.
|
|
42
42
|
|
|
43
43
|
```json title="package.json"
|
|
44
44
|
{
|
|
45
45
|
"scripts": {
|
|
46
|
-
"lint-k8s": "
|
|
46
|
+
"lint-k8s": "n-cursor lint-k8s"
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
Якщо правило **`k8s`** підключено в **`.n-cursor.json`** (масив **`rules`**), у **кореневому** `package.json` **мають** бути скрипт **`lint-k8s`** і виклик **`bun run lint-k8s`** у агрегованому **`lint`** (див. **`bun.mdc`**). Це перевіряє **`npx @nitra/cursor check bun`**.
|
|
52
52
|
|
|
53
|
-
Шлях до скрипта підстав свій (`./scripts/…` після копіювання, `node_modules/@nitra/cursor/scripts/…` якщо пакет у залежностях).
|
|
54
|
-
|
|
55
53
|
Додай workflow **`.github/workflows/lint-k8s.yml`** (гілки **`dev`** і **`main`**, лише **`.yml`**, узгоджено з **`ga.mdc`**). **Не** дублюй **`setup-node`**, **`oven-sh/setup-bun`**, **`actions/cache`** і **`bun install`** у job — після **`checkout`** використовуй локальний composite **`setup-bun-deps`** (шлях **`./.github/actions/setup-bun-deps`** або **`./npm/github-actions/setup-bun-deps`**, як у репозиторії). Встановлення **kubeconform** / **kubescape** лишаються окремими кроками.
|
|
56
54
|
|
|
57
55
|
```yaml title=".github/workflows/lint-k8s.yml"
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://unpkg.com/@nitra/cursor/schemas/target.json",
|
|
3
3
|
"files": {
|
|
4
|
-
"walkGlob": [
|
|
5
|
-
"**/k8s/**/base/**/*.yaml",
|
|
6
|
-
"**/k8s/**/base/**/*.yml",
|
|
7
|
-
"!**/k8s/**/base/**/kustomization.yaml"
|
|
8
|
-
]
|
|
4
|
+
"walkGlob": ["**/k8s/**/base/**/*.yaml", "**/k8s/**/base/**/*.yml", "!**/k8s/**/base/**/kustomization.yaml"]
|
|
9
5
|
}
|
|
10
6
|
}
|
|
@@ -34,7 +34,9 @@ const GZIP_CMD_RE = /\bgzip\b/u
|
|
|
34
34
|
const GZIP_EXTENSION_RE = /\*\.(?:js|css)/u
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* Збирає абсолютні шляхи до **default.conf.template** у репозиторії;
|
|
37
|
+
* Збирає абсолютні шляхи до **default.conf.template** у репозиторії; будь-який сегмент
|
|
38
|
+
* `fixtures/` у шляху виключається — це тестові артефакти (як `tests/fixtures/` так і
|
|
39
|
+
* co-located `rules/<rule>/js/<concern>/fixtures/`).
|
|
38
40
|
* @param {string} root корінь cwd
|
|
39
41
|
* @param {string[]} ignorePaths абсолютні шляхи каталогів, повністю виключених з обходу
|
|
40
42
|
* @returns {Promise<string[]>} відсортовані абсолютні шляхи до шаблонів
|
|
@@ -47,7 +49,7 @@ export async function findDefaultConfTemplatePaths(root, ignorePaths = []) {
|
|
|
47
49
|
p => {
|
|
48
50
|
if (basename(p) !== 'default.conf.template') return
|
|
49
51
|
const rel = relative(root, p).replaceAll('\\', '/')
|
|
50
|
-
if (rel.includes('
|
|
52
|
+
if (rel.split('/').includes('fixtures')) return
|
|
51
53
|
out.push(p)
|
|
52
54
|
},
|
|
53
55
|
ignorePaths
|
|
@@ -32,7 +32,12 @@ import { promisify } from 'node:util'
|
|
|
32
32
|
|
|
33
33
|
import { parseSync } from 'oxc-parser'
|
|
34
34
|
|
|
35
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
dynamicImportModule,
|
|
37
|
+
langFromPath,
|
|
38
|
+
requireCallModule,
|
|
39
|
+
walkAstWithAncestors
|
|
40
|
+
} from '../../../../scripts/utils/ast-scan-utils.mjs'
|
|
36
41
|
import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
|
|
37
42
|
import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
|
|
38
43
|
import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
|
|
@@ -491,8 +496,8 @@ async function checkNoTestsInPublishedFiles(pass, fail) {
|
|
|
491
496
|
}
|
|
492
497
|
for (const v of violations) {
|
|
493
498
|
fail(
|
|
494
|
-
`npm/${v.file}: ${v.reason} —
|
|
495
|
-
'(наприклад "!**/*_test.rego")
|
|
499
|
+
`npm/${v.file}: ${v.reason} — додай у "files" у npm/package.json негативний glob, ` +
|
|
500
|
+
'що виключає цей файл з tarball (наприклад "!**/*.test.mjs", "!**/fixtures/**", "!**/*_test.rego") (npm-module.mdc)'
|
|
496
501
|
)
|
|
497
502
|
}
|
|
498
503
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Оформлення репозиторію для npm модуля
|
|
3
3
|
alwaysApply: true
|
|
4
|
-
version: '1.
|
|
4
|
+
version: '1.12'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
Bun monorepo: workspace **`npm/`**, кореневий **`package.json`**, **`.github/workflows/`**; опційно **`demo/`**.
|
|
@@ -11,13 +11,13 @@ Bun monorepo: workspace **`npm/`**, кореневий **`package.json`**, **`.g
|
|
|
11
11
|
Мета — **максимально компактний** опублікований пакет: у npm потрапляє тільки те, що потрібно під час `require`/`import` користувачем.
|
|
12
12
|
|
|
13
13
|
- **`"files"` обовʼязковий** у `npm/package.json` як **whitelist** того, що публікується (без `"files"` npm пакує майже все — це антипатерн для цього правила).
|
|
14
|
-
- **Тести й фікстури —
|
|
14
|
+
- **Тести й фікстури не публікуються — через негативні glob-патерни у `"files"`.** Тести можна (і зазвичай зручніше) тримати **поруч з кодом** усередині шляхів, перелічених у `"files"` (наприклад `*.test.mjs` поруч з модулем чи `fixtures/` під `rules/<id>/js/`). Щоб вони не потрапляли у tarball, `"files"` **обовʼязково має містити негативні glob-патерни**, що їх виключають. Покрий усі форми тестового: фреймворк-тести (`bun:test`, `node:test`, `vitest`, `@jest/globals`, `mocha`, …), test-style каталоги (`tests/`, `__tests__/`, `fixtures/`, `__fixtures__/`, `spec/`, `test/`), файли за патернами `*.test.*` / `*.spec.*`. Орієнтовний набір: `"!**/*.test.*"`, `"!**/*.spec.*"`, `"!**/test-helpers.*"`, `"!**/fixtures/**"`, `"!**/__tests__/**"`. **Rego (`*_test.rego`):** за конвенцією conftest юніт-тест лежить поруч з полісі у тому самому `package` — `*_test.rego` усередині опублікованого `policy/` дозволені; якщо потрібна максимальна компактність, додай `"!**/*_test.rego"` явно (як у самому `@nitra/cursor`).
|
|
15
15
|
- **Лише runtime-залежності у `npm/package.json`.** `devDependencies` тримай у **кореневому** `package.json` монорепо — тоді `npm install @nitra/<pkg>` не тягне інструментарій, потрібний лише для розробки самого пакета.
|
|
16
16
|
|
|
17
17
|
Деталі алгоритму перевірки:
|
|
18
18
|
|
|
19
19
|
- Пер-документні правила для `npm/package.json` (whitelist `files`, заборона `devDependencies`, форма `types`) — у rego-пакеті `npm_module.npm_package_json` (`npm/policy/npm_module/npm_package_json/`).
|
|
20
|
-
-
|
|
20
|
+
- Walk шляхів з `"files"` з застосуванням негативних patterns і скан залишку на тест-патерни (walking + AST JS/TS) — у `check.mjs::checkNoTestsInPublishedFiles` (FS / AST не лягають у rego). Якщо після застосування негативних patterns у tarball лишається test-style файл — `check` падає з вказівкою, який саме негативний glob треба додати у `"files"`.
|
|
21
21
|
|
|
22
22
|
## TypeScript declaration (`npm/types`)
|
|
23
23
|
|
|
@@ -45,9 +45,9 @@ export async function applies() {
|
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* Друкує короткий context-pass — самі полісі прогонить CLI через `policy/<name>/target.json`.
|
|
48
|
-
* @returns {
|
|
48
|
+
* @returns {number} 0 — все ок (фактичні порушення повертають policy-концерни)
|
|
49
49
|
*/
|
|
50
|
-
export
|
|
50
|
+
export function check() {
|
|
51
51
|
const reporter = createCheckReporter()
|
|
52
52
|
reporter.pass('Знайдено *.rego у дереві — перевіряємо канонічні конфіги rego.mdc')
|
|
53
53
|
return reporter.getExitCode()
|
package/rules/rego/js/lint.mjs
CHANGED
|
@@ -26,6 +26,7 @@ import { spawnSync } from 'node:child_process'
|
|
|
26
26
|
import { existsSync } from 'node:fs'
|
|
27
27
|
import { resolve } from 'node:path'
|
|
28
28
|
|
|
29
|
+
import { isRunAsCli } from '../../../scripts/cli-entry.mjs'
|
|
29
30
|
import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
|
|
30
31
|
|
|
31
32
|
/** Шляхи з Rego-полісі (відносно cwd). Існують не всі на ранніх стадіях — фільтруємо нижче. */
|
|
@@ -128,4 +129,6 @@ export function runLintRego(cwd = process.cwd()) {
|
|
|
128
129
|
return runStep(conftest, ['verify', ...targets.flatMap(t => ['-p', t])], root)
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
|
|
132
|
+
if (isRunAsCli()) {
|
|
133
|
+
process.exitCode = runLintRego()
|
|
134
|
+
}
|
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
# Викликається з `check-rego.mjs` через `runConftestBatch` лише ПІСЛЯ виявлення
|
|
4
4
|
# `.rego` файлів у дереві. Глобально у `lint-conftest` НЕ реєструється.
|
|
5
5
|
#
|
|
6
|
-
# Canonical (rego.mdc): scripts.lint-rego має бути "
|
|
6
|
+
# Canonical (rego.mdc): scripts.lint-rego має бути "n-cursor lint-rego" — CLI пакета `@nitra/cursor`
|
|
7
|
+
# (бінарка з `node_modules/.bin/`) робить preflight `opa`/`regal` і прогонить
|
|
8
|
+
# `opa check --strict` → `regal lint` → опц. `conftest verify` (`@nitra/cursor lint-rego`).
|
|
7
9
|
#
|
|
8
10
|
# Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
|
|
9
11
|
package rego.package_json
|
|
10
12
|
|
|
11
13
|
import rego.v1
|
|
12
14
|
|
|
13
|
-
canonical_lint_rego := "
|
|
15
|
+
canonical_lint_rego := "n-cursor lint-rego"
|
|
14
16
|
|
|
15
17
|
lint_rego_template := concat(" ", [
|
|
16
18
|
"package.json: scripts.lint-rego має бути %q",
|
|
@@ -22,7 +24,7 @@ deny contains msg if {
|
|
|
22
24
|
not "lint-rego" in object.keys(scripts)
|
|
23
25
|
msg := concat(" ", [
|
|
24
26
|
"package.json: відсутній scripts.lint-rego — додай",
|
|
25
|
-
"\"lint-rego\": \"
|
|
27
|
+
"\"lint-rego\": \"n-cursor lint-rego\" (rego.mdc)",
|
|
26
28
|
])
|
|
27
29
|
}
|
|
28
30
|
|
package/rules/rego/rego.mdc
CHANGED
|
@@ -36,13 +36,13 @@ alwaysApply: false
|
|
|
36
36
|
bun run lint-rego
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Скрипт делегує до `
|
|
39
|
+
Скрипт делегує до CLI `n-cursor lint-rego` (бінарка з `node_modules/.bin/` пакету `@nitra/cursor`). Послідовність:
|
|
40
40
|
|
|
41
41
|
1. **preflight** — наявність `opa` і `regal` у `PATH`; якщо хоча б одного нема — exit 1 з підказкою встановлення;
|
|
42
42
|
2. `opa check --strict <targets>` — компіляція з типами та `--strict` (мертвий код, неоднозначні правила, незадекларовані змінні);
|
|
43
43
|
3. `regal lint <targets>` — статичний лінтер Rego ([Styra Regal](https://docs.styra.com/regal)): ловить v0-синтаксис, неявні set-rules і відхилення від `rego.v1`, плюс bugs/idiomatic/style-правила.
|
|
44
44
|
|
|
45
|
-
Цілі — `npm/policy/` (де живуть Rego-полісі пакета). Інші *.rego поза деревом додай у `LINT_TARGETS` у `lint
|
|
45
|
+
Цілі — `npm/policy/` (де живуть Rego-полісі пакета). Інші *.rego поза деревом додай у `LINT_TARGETS` у `npm/rules/rego/js/lint.mjs`.
|
|
46
46
|
|
|
47
47
|
### Встановлення інструментів
|
|
48
48
|
|
|
@@ -58,7 +58,7 @@ bun run lint-rego
|
|
|
58
58
|
```json title="package.json"
|
|
59
59
|
{
|
|
60
60
|
"scripts": {
|
|
61
|
-
"lint-rego": "
|
|
61
|
+
"lint-rego": "n-cursor lint-rego"
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
```
|
|
@@ -25,7 +25,7 @@ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mj
|
|
|
25
25
|
* Альтернатива полю `stylelint` у `package.json` — зовнішній файл конфігу. Якщо
|
|
26
26
|
* поля немає і файлу немає, фейлимося; якщо є хоч щось — пропускаємо. Поле
|
|
27
27
|
* `stylelint.extends == "@nitra/stylelint-config"` сам формат — у Rego.
|
|
28
|
-
* @param {import('
|
|
28
|
+
* @param {import('../../../../scripts/utils/check-reporter.mjs').CheckReporter} reporter репортер
|
|
29
29
|
*/
|
|
30
30
|
async function checkStylelintConfigPresence(reporter) {
|
|
31
31
|
const { pass, fail } = reporter
|
|
@@ -9,7 +9,7 @@ alwaysApply: false
|
|
|
9
9
|
|
|
10
10
|
- **Джерело правил:** перед тим як писати або суттєво змінювати **`.css`**, **`.scss`** або стилі в **`.vue`**, переглянь у корені проєкту (і в релевантних пакетах монорепо, якщо є) поле **`stylelint`** у **`package.json`** (зокрема `extends`), наявні **`.stylelintrc.*`**, **`stylelint.config.*`** та **`.stylelintignore`**. Не покладайся на «типові» правила stylelint з пам’яті — дотримуйся **проєктного** **`@nitra/stylelint-config`** і будь-яких локальних доповнень у репозиторії.
|
|
11
11
|
- **Форматування** узгоджуй з **`n-text.mdc`** (oxfmt / `.oxfmtrc.json` для css, scss тощо), щоб форматер і stylelint не суперечили один одному.
|
|
12
|
-
- **Запуск stylelint:** лише **`npx stylelint`**. Локально — через скрипт **`lint-style`** (`bun run lint-style`); у **GitHub Actions** у кроці **`run`** викликай `npx stylelint '**/*.{css,scss,vue}' --fix` напряму (не через **`bun run lint-style`**). Не використовуй **`bunx stylelint`**. Після змін запускай **`bun run lint-style`** і виправляй усе, що лишилось після auto-fix; за потреби — повний
|
|
12
|
+
- **Запуск stylelint:** лише **`npx stylelint`**. Локально — через скрипт **`lint-style`** (`bun run lint-style`); у **GitHub Actions** у кроці **`run`** викликай `npx stylelint '**/*.{css,scss,vue}' --fix` напряму (не через **`bun run lint-style`**). Не використовуй **`bunx stylelint`**. Після змін запускай **`bun run lint-style`** і виправляй усе, що лишилось після auto-fix; за потреби — повний `bun run lint` (навичка **`/n-lint`**).
|
|
13
13
|
- **Не розширюй винятки:** не додавай зайві **`stylelint-disable`** без потреби; краще підлаштувати стилі під правила проєкту.
|
|
14
14
|
|
|
15
15
|
**VSCode:** у **`.vscode/extensions.json`** рекомендуй **`stylelint.vscode-stylelint`**. У **`.vscode/settings.json`** вимкни вбудовану валідацію CSS/SCSS/Less і увімкни явні code actions:
|
|
@@ -70,7 +70,9 @@ export async function check() {
|
|
|
70
70
|
|
|
71
71
|
const extPath = '.vscode/extensions.json'
|
|
72
72
|
if (!existsSync(extPath)) {
|
|
73
|
-
fail(
|
|
73
|
+
fail(
|
|
74
|
+
`${extPath} не існує — створи з recommendations "tauri-apps.tauri-vscode" і "rust-lang.rust-analyzer" (tauri.mdc)`
|
|
75
|
+
)
|
|
74
76
|
return reporter.getExitCode()
|
|
75
77
|
}
|
|
76
78
|
const violations = runConftestBatch({
|
|
@@ -147,36 +147,20 @@ async function checkPackageJsonText(passFn, failFn) {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
/**
|
|
150
|
-
* Перевіряє скрипт lint-text
|
|
151
|
-
*
|
|
150
|
+
* Перевіряє скрипт lint-text: канонічний — `n-cursor lint-text` (CLI пакета `@nitra/cursor` робить
|
|
151
|
+
* `cspell` → `runShellcheckText()` → `bunx markdownlint-cli2 --fix` → `runV8rWithGlobs()`).
|
|
152
|
+
* Дозволено whitespace навколо команди.
|
|
153
|
+
* @param {unknown} lintText значення `scripts.lint-text` з package.json
|
|
152
154
|
* @param {(msg: string) => void} passFn callback при успішній перевірці
|
|
153
155
|
* @param {(msg: string) => void} failFn callback при помилці
|
|
154
156
|
*/
|
|
155
157
|
function checkLintTextScript(lintText, passFn, failFn) {
|
|
156
|
-
const lt = typeof lintText === 'string' ? lintText : ''
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const eq98Hints = (lt.match(/eq 98/g) || []).length
|
|
160
|
-
const legacyV8r = v8rCalls >= 4 && eq98Hints >= 4
|
|
161
|
-
const quietBundled = quietCalls === 1
|
|
162
|
-
const quietLegacy4x = quietCalls >= 4
|
|
163
|
-
const v8rTextOk = legacyV8r || quietBundled || quietLegacy4x
|
|
164
|
-
const globsRequired = legacyV8r || quietLegacy4x
|
|
165
|
-
const globsOk =
|
|
166
|
-
lt.includes('**/*.json') && lt.includes('**/*.yml') && lt.includes('**/*.yaml') && lt.includes('**/*.toml')
|
|
167
|
-
const ok =
|
|
168
|
-
lt &&
|
|
169
|
-
lt.includes('cspell') &&
|
|
170
|
-
lt.includes('run-shellcheck-text.mjs') &&
|
|
171
|
-
lt.includes('bunx markdownlint-cli2') &&
|
|
172
|
-
lt.includes('**/*.mdc') &&
|
|
173
|
-
v8rTextOk &&
|
|
174
|
-
(!globsRequired || globsOk)
|
|
175
|
-
if (ok) {
|
|
176
|
-
passFn('package.json: lint-text — shellcheck (run-shellcheck-text.mjs), v8r: run-v8r.mjs або чотири bunx v8r')
|
|
158
|
+
const lt = typeof lintText === 'string' ? lintText.trim() : ''
|
|
159
|
+
if (lt === 'n-cursor lint-text') {
|
|
160
|
+
passFn('lint-text делегує CLI n-cursor lint-text (cspell + shellcheck + markdownlint + v8r)')
|
|
177
161
|
} else {
|
|
178
162
|
failFn(
|
|
179
|
-
'package.json: lint-text
|
|
163
|
+
'package.json: lint-text має бути "n-cursor lint-text" — CLI пакета @nitra/cursor виконує cspell → shellcheck → markdownlint-cli2 → v8r (text.mdc)'
|
|
180
164
|
)
|
|
181
165
|
}
|
|
182
166
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI-обгортка над канонічним `lint-text` (text.mdc): послідовно
|
|
3
|
+
* 1) `cspell .` — перевірка правопису з `@nitra/cspell-dict`;
|
|
4
|
+
* 2) `runShellcheckText()` — авто-фікс і фінальна перевірка `*.sh` через `shellcheck`;
|
|
5
|
+
* 3) `bunx markdownlint-cli2 --fix "**\/*.md" "**\/*.mdc"` — авто-фікс Markdown;
|
|
6
|
+
* 4) `runV8rWithGlobs()` — schema-валідація json/json5/yaml/yml/toml через v8r з каталогом `@nitra/cursor`.
|
|
7
|
+
*
|
|
8
|
+
* Перший ненульовий код з ланцюжка повертається як код виходу; наступні кроки не запускаються.
|
|
9
|
+
* Експортовано як `runLintTextCli` — використовується з `bin/n-cursor.js` як підкоманда `lint-text`.
|
|
10
|
+
*/
|
|
11
|
+
import { runLintStep } from '../../../scripts/utils/run-lint-step.mjs'
|
|
12
|
+
import { runShellcheckText } from './run-shellcheck.mjs'
|
|
13
|
+
import { runV8rWithGlobs } from './run-v8r.mjs'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Виконує канонічний `lint-text`: cspell → run-shellcheck → markdownlint-cli2 → run-v8r.
|
|
17
|
+
* Першу помилку повертаємо як код виходу; наступні кроки не запускаються.
|
|
18
|
+
* Усі кроки синхронні (`spawnSync` + sync-ентрі з пакета), тому функція не async.
|
|
19
|
+
* @returns {number} 0 — все OK, інакше — код першого кроку, що впав
|
|
20
|
+
*/
|
|
21
|
+
export function runLintTextCli() {
|
|
22
|
+
const cspellCode = runLintStep('cspell', 'npx', ['cspell', '.'])
|
|
23
|
+
if (cspellCode !== 0) return cspellCode
|
|
24
|
+
|
|
25
|
+
console.log('\n▶ shellcheck (авто-фікс + фінальна перевірка *.sh)')
|
|
26
|
+
const shellcheckCode = runShellcheckText()
|
|
27
|
+
if (shellcheckCode !== 0) return shellcheckCode
|
|
28
|
+
|
|
29
|
+
const markdownlintCode = runLintStep('markdownlint', 'bunx', ['markdownlint-cli2', '--fix', '**/*.md', '**/*.mdc'])
|
|
30
|
+
if (markdownlintCode !== 0) return markdownlintCode
|
|
31
|
+
|
|
32
|
+
console.log('\n▶ v8r (schema-валідація json/json5/yaml/yml/toml)')
|
|
33
|
+
return runV8rWithGlobs()
|
|
34
|
+
}
|
|
@@ -82,7 +82,7 @@ export function listShellScriptPaths(cwd) {
|
|
|
82
82
|
return []
|
|
83
83
|
}
|
|
84
84
|
const files = ls.stdout.split('\0').filter(Boolean)
|
|
85
|
-
return new Set(files).toSorted()
|
|
85
|
+
return [...new Set(files)].toSorted()
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -90,7 +90,7 @@ export function listShellScriptPaths(cwd) {
|
|
|
90
90
|
cwd,
|
|
91
91
|
exclude: p => p.includes('node_modules') || p.startsWith(`node_modules/`) || p.split('/').includes('node_modules')
|
|
92
92
|
})
|
|
93
|
-
return new Set(fromGlob.map(p => p.replaceAll('\\', '/'))).toSorted()
|
|
93
|
+
return [...new Set(fromGlob.map(p => p.replaceAll('\\', '/')))].toSorted()
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/**
|
|
@@ -24,8 +24,8 @@ import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
|
|
|
24
24
|
/** Типові glob-и для форматів, які обробляє v8r (див. опис CLI v8r). */
|
|
25
25
|
export const DEFAULT_V8R_GLOBS = ['**/*.json', '**/*.json5', '**/*.yml', '**/*.yaml', '**/*.toml']
|
|
26
26
|
|
|
27
|
-
/** Абсолютний шлях до `schemas/v8r-catalog.json`
|
|
28
|
-
export const V8R_CATALOG_PATH = join(dirname(fileURLToPath(import.meta.url)), '
|
|
27
|
+
/** Абсолютний шлях до `schemas/v8r-catalog.json` у корені пакета `@nitra/cursor` (`npm/schemas/`). */
|
|
28
|
+
export const V8R_CATALOG_PATH = join(dirname(fileURLToPath(import.meta.url)), '../../../schemas/v8r-catalog.json')
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Повертає шлях до каталогу схем v8r для пакета (для тестів і діагностики).
|