@7n/rules-lang-js 0.3.1 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/package.json +14 -4
- package/rules/bun/bunfig/bunfig.mdc +17 -0
- package/rules/bun/bunfig/bunfig.rego +29 -0
- package/rules/bun/bunfig/concern.json +9 -0
- package/rules/bun/bunfig/template/bunfig.toml.snippet.toml +2 -0
- package/rules/bun/docs/index.md +11 -0
- package/rules/bun/layout/concern.json +16 -0
- package/rules/bun/layout/docs/fix-layout.md +29 -0
- package/rules/bun/layout/docs/main.md +34 -0
- package/rules/bun/layout/fix-layout.mjs +63 -0
- package/rules/bun/layout/layout.mdc +60 -0
- package/rules/bun/layout/main.mjs +53 -0
- package/rules/bun/licensee/concern.json +7 -0
- package/rules/bun/licensee/docs/fix-licensee.md +27 -0
- package/rules/bun/licensee/docs/index.md +12 -0
- package/rules/bun/licensee/docs/main.md +30 -0
- package/rules/bun/licensee/fix-licensee.mjs +31 -0
- package/rules/bun/licensee/main.mjs +68 -0
- package/rules/bun/lint-surface/concern.json +3 -0
- package/rules/bun/lint-surface/lint-surface.mdc +13 -0
- package/rules/bun/main.json +1 -0
- package/rules/bun/main.mdc +11 -0
- package/rules/bun/package_json/concern.json +9 -0
- package/rules/bun/package_json/docs/fix-package_json.md +28 -0
- package/rules/bun/package_json/docs/index.md +9 -0
- package/rules/bun/package_json/fix-package_json.mjs +311 -0
- package/rules/bun/package_json/package_json.mdc +14 -0
- package/rules/bun/package_json/package_json.rego +64 -0
- package/rules/bun/package_json/template/package.json.deny.json +4 -0
- package/rules/js/check/check.mdc +26 -0
- package/rules/js/check/concern.json +19 -0
- package/rules/js/check/docs/eslint-config.md +56 -0
- package/rules/js/check/docs/fix-check.md +48 -0
- package/rules/js/check/docs/index.md +13 -0
- package/rules/js/check/docs/main.md +48 -0
- package/rules/js/check/eslint-config.mjs +262 -0
- package/rules/js/check/fix-check.mjs +82 -0
- package/rules/js/check/main.mjs +310 -0
- package/rules/js/dep-policy/concern.json +4 -0
- package/rules/js/dep-policy/dep-policy.mdc +36 -0
- package/rules/js/dep-policy/docs/main.md +35 -0
- package/rules/js/dep-policy/main.mjs +99 -0
- package/rules/js/docs/index.md +11 -0
- package/rules/js/eslint/concern.json +8 -0
- package/rules/js/eslint/docs/fix-eslint.md +50 -0
- package/rules/js/eslint/docs/fix-worker.md +31 -0
- package/rules/js/eslint/docs/index.md +11 -0
- package/rules/js/eslint/docs/main.md +35 -0
- package/rules/js/eslint/fix-eslint.mjs +160 -0
- package/rules/js/eslint/fix-worker.mjs +139 -0
- package/rules/js/eslint/main.mjs +115 -0
- package/rules/js/file-extensions/concern.json +3 -0
- package/rules/js/file-extensions/file-extensions.mdc +12 -0
- package/rules/js/jscpd_config/concern.json +11 -0
- package/rules/js/jscpd_config/docs/fix-jscpd_config.md +25 -0
- package/rules/js/jscpd_config/docs/index.md +9 -0
- package/rules/js/jscpd_config/fix-jscpd_config.mjs +3 -0
- package/rules/js/jscpd_config/jscpd_config.mdc +42 -0
- package/rules/js/jscpd_config/jscpd_config.rego +44 -0
- package/rules/js/jscpd_config/template/.jscpd.json.snippet.json +7 -0
- package/rules/js/jscpd_duplicates/concern.json +7 -0
- package/rules/js/jscpd_duplicates/docs/main.md +29 -0
- package/rules/js/jscpd_duplicates/main.mjs +69 -0
- package/rules/js/knip/concern.json +7 -0
- package/rules/js/knip/docs/main.md +31 -0
- package/rules/js/knip/knip.mdc +15 -0
- package/rules/js/knip/main.mjs +89 -0
- package/rules/js/lint-findings/concern.json +3 -0
- package/rules/js/lint-findings/docs/main.md +40 -0
- package/rules/js/lint-findings/main.mjs +125 -0
- package/rules/js/main.json +1 -0
- package/rules/js/main.mdc +18 -0
- package/rules/js/package_json/concern.json +9 -0
- package/rules/js/package_json/docs/fix-package_json.md +25 -0
- package/rules/js/package_json/docs/index.md +9 -0
- package/rules/js/package_json/fix-package_json.mjs +3 -0
- package/rules/js/package_json/package_json.mdc +15 -0
- package/rules/js/package_json/package_json.rego +142 -0
- package/rules/js/package_json/template/package.json.snippet.json +6 -0
- package/rules/js/tooling/concern.json +3 -0
- package/rules/js/tooling/data/tooling/knip-canonical.json +30 -0
- package/rules/js/tooling/data/tooling/oxlint-canonical.json +400 -0
- package/rules/js/tooling/docs/main.md +53 -0
- package/rules/js/tooling/main.mjs +183 -0
- package/rules/js/utils_imports/concern.json +4 -0
- package/rules/js/utils_imports/docs/main.md +50 -0
- package/rules/js/utils_imports/main.mjs +185 -0
- package/rules/js/utils_imports/utils_imports.mdc +15 -0
- package/rules/js/vscode_extensions/concern.json +11 -0
- package/rules/js/vscode_extensions/docs/fix-vscode_extensions.md +24 -0
- package/rules/js/vscode_extensions/docs/index.md +11 -0
- package/rules/js/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/js/vscode_extensions/template/extensions.json.snippet.json +6 -0
- package/rules/js/vscode_extensions/vscode_extensions.mdc +11 -0
- package/rules/js/vscode_extensions/vscode_extensions.rego +12 -0
- package/rules/js-bun-db/connection/concern.json +3 -0
- package/rules/js-bun-db/connection/connection.mdc +42 -0
- package/rules/js-bun-db/docs/index.md +11 -0
- package/rules/js-bun-db/lib/bun-sql-scan.mjs +1047 -0
- package/rules/js-bun-db/lib/docs/bun-sql-scan.md +63 -0
- package/rules/js-bun-db/lib/docs/index.md +11 -0
- package/rules/js-bun-db/main.json +1 -0
- package/rules/js-bun-db/main.mdc +8 -0
- package/rules/js-bun-db/package_json/concern.json +9 -0
- package/rules/js-bun-db/package_json/package_json.mdc +31 -0
- package/rules/js-bun-db/package_json/package_json.rego +15 -0
- package/rules/js-bun-db/package_json/template/package.json.deny.json +6 -0
- package/rules/js-bun-db/pg_format_identifiers/concern.json +3 -0
- package/rules/js-bun-db/pg_format_identifiers/pg_format_identifiers.mdc +104 -0
- package/rules/js-bun-db/safety/concern.json +4 -0
- package/rules/js-bun-db/safety/docs/main.md +34 -0
- package/rules/js-bun-db/safety/main.mjs +430 -0
- package/rules/js-bun-db/safety/safety.mdc +458 -0
- package/rules/js-bun-redis/docs/index.md +11 -0
- package/rules/js-bun-redis/imports/concern.json +4 -0
- package/rules/js-bun-redis/imports/docs/main.md +36 -0
- package/rules/js-bun-redis/imports/imports.mdc +47 -0
- package/rules/js-bun-redis/imports/main.mjs +88 -0
- package/rules/js-bun-redis/lib/docs/index.md +11 -0
- package/rules/js-bun-redis/lib/docs/redis-imports.md +227 -0
- package/rules/js-bun-redis/lib/redis-imports.mjs +130 -0
- package/rules/js-bun-redis/main.json +1 -0
- package/rules/js-bun-redis/main.mdc +8 -0
- package/rules/js-bun-redis/package_json/concern.json +9 -0
- package/rules/js-bun-redis/package_json/package_json.mdc +11 -0
- package/rules/js-bun-redis/package_json/package_json.rego +15 -0
- package/rules/js-bun-redis/package_json/template/package.json.deny.json +12 -0
- package/rules/js-mssql/deps/concern.json +4 -0
- package/rules/js-mssql/deps/docs/main.md +33 -0
- package/rules/js-mssql/deps/main.mjs +297 -0
- package/rules/js-mssql/docs/index.md +11 -0
- package/rules/js-mssql/lib/docs/index.md +11 -0
- package/rules/js-mssql/lib/docs/mssql-pool-scan.md +380 -0
- package/rules/js-mssql/lib/mssql-pool-scan.mjs +610 -0
- package/rules/js-mssql/main.json +1 -0
- package/rules/js-mssql/main.mdc +144 -0
- package/rules/js-mssql/mssql-tvp/concern.json +3 -0
- package/rules/js-mssql/mssql-tvp/mssql-tvp.mdc +77 -0
- package/rules/js-mssql/package_json/concern.json +9 -0
- package/rules/js-mssql/package_json/package_json.mdc +9 -0
- package/rules/js-mssql/package_json/package_json.rego +57 -0
- package/rules/js-run/configmap/concern.json +9 -0
- package/rules/js-run/configmap/configmap.mdc +37 -0
- package/rules/js-run/configmap/configmap.rego +21 -0
- package/rules/js-run/configmap/template/configmap.yaml.contains.yml +4 -0
- package/rules/js-run/docs/index.md +11 -0
- package/rules/js-run/jsconfig/concern.json +9 -0
- package/rules/js-run/jsconfig/docs/fix-jsconfig.md +28 -0
- package/rules/js-run/jsconfig/docs/index.md +9 -0
- package/rules/js-run/jsconfig/fix-jsconfig.mjs +119 -0
- package/rules/js-run/jsconfig/jsconfig.mdc +48 -0
- package/rules/js-run/jsconfig/jsconfig.rego +59 -0
- package/rules/js-run/jsconfig/template/jsconfig.json.snippet.json +10 -0
- package/rules/js-run/lib/bunyan-imports.mjs +98 -0
- package/rules/js-run/lib/check-env-scan.mjs +338 -0
- package/rules/js-run/lib/conn-file-rules.mjs +214 -0
- package/rules/js-run/lib/conn-imports-scan.mjs +154 -0
- package/rules/js-run/lib/docs/bunyan-imports.md +121 -0
- package/rules/js-run/lib/docs/check-env-scan.md +438 -0
- package/rules/js-run/lib/docs/conn-file-rules.md +304 -0
- package/rules/js-run/lib/docs/conn-imports-scan.md +208 -0
- package/rules/js-run/lib/docs/index.md +16 -0
- package/rules/js-run/lib/docs/promise-settimeout-scan.md +334 -0
- package/rules/js-run/lib/docs/temporal-scan.md +29 -0
- package/rules/js-run/lib/promise-settimeout-scan.mjs +128 -0
- package/rules/js-run/lib/temporal-scan.mjs +52 -0
- package/rules/js-run/main.json +1 -0
- package/rules/js-run/main.mdc +16 -0
- package/rules/js-run/package_json/concern.json +9 -0
- package/rules/js-run/package_json/package_json.mdc +44 -0
- package/rules/js-run/package_json/package_json.rego +37 -0
- package/rules/js-run/package_json/template/package.json.deny.json +22 -0
- package/rules/js-run/project-structure/concern.json +3 -0
- package/rules/js-run/project-structure/project-structure.mdc +11 -0
- package/rules/js-run/runtime/concern.json +12 -0
- package/rules/js-run/runtime/docs/fix-runtime.md +27 -0
- package/rules/js-run/runtime/docs/main.md +35 -0
- package/rules/js-run/runtime/fix-runtime.mjs +46 -0
- package/rules/js-run/runtime/main.mjs +496 -0
- package/rules/js-run/runtime/runtime.mdc +184 -0
- package/rules/js-run/scope/concern.json +3 -0
- package/rules/js-run/scope/scope.mdc +11 -0
- package/rules/npm-module/docs/index.md +11 -0
- package/rules/npm-module/emit_types_config/concern.json +9 -0
- package/rules/npm-module/emit_types_config/docs/fix-emit_types_config.md +25 -0
- package/rules/npm-module/emit_types_config/docs/index.md +9 -0
- package/rules/npm-module/emit_types_config/emit_types_config.mdc +43 -0
- package/rules/npm-module/emit_types_config/emit_types_config.rego +28 -0
- package/rules/npm-module/emit_types_config/fix-emit_types_config.mjs +5 -0
- package/rules/npm-module/emit_types_config/template/tsconfig.emit-types.json.snippet.json +9 -0
- package/rules/npm-module/header_doc_pointer/concern.json +5 -0
- package/rules/npm-module/header_doc_pointer/docs/main.md +40 -0
- package/rules/npm-module/header_doc_pointer/header_doc_pointer.mdc +18 -0
- package/rules/npm-module/header_doc_pointer/main.mjs +131 -0
- package/rules/npm-module/main.json +1 -0
- package/rules/npm-module/main.mdc +36 -0
- package/rules/npm-module/npm_package_json/concern.json +9 -0
- package/rules/npm-module/npm_package_json/docs/fix-npm_package_json.md +26 -0
- package/rules/npm-module/npm_package_json/docs/index.md +9 -0
- package/rules/npm-module/npm_package_json/fix-npm_package_json.mjs +5 -0
- package/rules/npm-module/npm_package_json/npm_package_json.mdc +57 -0
- package/rules/npm-module/npm_package_json/npm_package_json.rego +73 -0
- package/rules/npm-module/npm_package_json/template/package.json.snippet.json +1 -0
- package/rules/npm-module/package_structure/concern.json +5 -0
- package/rules/npm-module/package_structure/docs/main.md +37 -0
- package/rules/npm-module/package_structure/main.mjs +448 -0
- package/rules/npm-module/package_structure/package_structure.mdc +63 -0
- package/rules/npm-module/root_package_json/concern.json +9 -0
- package/rules/npm-module/root_package_json/docs/fix-root_package_json.md +25 -0
- package/rules/npm-module/root_package_json/docs/index.md +9 -0
- package/rules/npm-module/root_package_json/fix-root_package_json.mjs +5 -0
- package/rules/npm-module/root_package_json/root_package_json.mdc +41 -0
- package/rules/npm-module/root_package_json/root_package_json.rego +28 -0
- package/rules/npm-module/root_package_json/template/package.json.snippet.json +1 -0
- package/rules/npm-module/rule_meta/concern.json +8 -0
- package/rules/npm-module/rule_meta/docs/main.md +35 -0
- package/rules/npm-module/rule_meta/main.mjs +119 -0
- package/rules/npm-module/rule_meta/rule_meta.mdc +11 -0
- package/rules/npm-module/skill_meta/concern.json +5 -0
- package/rules/npm-module/skill_meta/docs/main.md +149 -0
- package/rules/npm-module/skill_meta/main.mjs +91 -0
- package/rules/npm-module/skill_meta/skill_meta.mdc +11 -0
- package/rules/tool-surface/docs/index.md +11 -0
- package/rules/tool-surface/main.json +6 -0
- package/rules/tool-surface/main.mdc +72 -0
- package/rules/vue/composition-api/composition-api.mdc +82 -0
- package/rules/vue/composition-api/concern.json +3 -0
- package/rules/vue/docs/index.md +11 -0
- package/rules/vue/lib/docs/index.md +11 -0
- package/rules/vue/lib/docs/vue-forbidden-imports.md +265 -0
- package/rules/vue/lib/vue-forbidden-imports.mjs +240 -0
- package/rules/vue/main.json +1 -0
- package/rules/vue/main.mdc +18 -0
- package/rules/vue/nheader-layout/concern.json +3 -0
- package/rules/vue/nheader-layout/nheader-layout.mdc +171 -0
- package/rules/vue/package_json/concern.json +9 -0
- package/rules/vue/package_json/package_json.mdc +30 -0
- package/rules/vue/package_json/package_json.rego +140 -0
- package/rules/vue/packages/concern.json +6 -0
- package/rules/vue/packages/docs/index.md +11 -0
- package/rules/vue/packages/docs/main.md +35 -0
- package/rules/vue/packages/main.mjs +575 -0
- package/rules/vue/packages/packages.mdc +56 -0
- package/rules/vue/quasar-ui/concern.json +3 -0
- package/rules/vue/quasar-ui/quasar-ui.mdc +32 -0
- package/rules/vue/structure/concern.json +3 -0
- package/rules/vue/structure/structure.mdc +101 -0
- package/rules/vue/testing/concern.json +3 -0
- package/rules/vue/testing/testing.mdc +40 -0
- package/rules/vue/tfm-translations/concern.json +7 -0
- package/rules/vue/tfm-translations/docs/main.md +29 -0
- package/rules/vue/tfm-translations/main.mjs +55 -0
- package/rules/vue/tfm-translations/tfm-translations.mdc +32 -0
- package/rules/vue/vite-config/concern.json +3 -0
- package/rules/vue/vite-config/vite-config.mdc +153 -0
- package/rules/vue/vite-env/concern.json +3 -0
- package/rules/vue/vite-env/vite-env.mdc +61 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
## Runtime у `package.json#scripts`
|
|
2
|
+
|
|
3
|
+
У **backend**-пакетах (без `vite` у `devDependencies`) код запускають через **Bun**, не через бінарник **`node`** у значеннях `scripts`:
|
|
4
|
+
|
|
5
|
+
- `"start": "node src/index.js"` → `"start": "bun src/index.js"` (або `bun run …`, якщо так прийнято в репо);
|
|
6
|
+
- `node --watch app.js` → `bun --watch app.js`;
|
|
7
|
+
- `NODE_OPTIONS=… node app.js` → `NODE_OPTIONS=… bun app.js`.
|
|
8
|
+
- `env $(cat .env .env.local) bun src/index.js` → `bun --env-file=.env --env-file=.env.local src/index.js` (нативне завантаження env у Bun, без `env`/`cat`).
|
|
9
|
+
|
|
10
|
+
Заборонено викликати **`node`** у ланцюжках (`&&`, `;`, `|`). Заборонено обгортку **`env $(cat …) bun`** — файли з `cat` перелічуй у **`--env-file=`** (по одному прапорцю на файл, порядок як у `cat`). Допустимо: `bun`, `bunx`, `npx` (див. **bun.mdc**), інші CLI, якщо вони не підміняють рантайм на `node`.
|
|
11
|
+
|
|
12
|
+
Це **не** стосується поля `engines.node` (мінімальна версія Node для сумісності інструментів) і **не** стосується frontend-пакетів з `vite` у `devDependencies`.
|
|
13
|
+
|
|
14
|
+
Канон заборонених патернів у `scripts`: [package.json.deny.json](./policy/package_json/template/package.json.deny.json) (`scriptsForbidden`).
|
|
15
|
+
|
|
16
|
+
## CheckEnv та заборона прямого `process.env`
|
|
17
|
+
|
|
18
|
+
### CheckEnv
|
|
19
|
+
|
|
20
|
+
Усі змінні оточення, які використовуються в коді, повинні бути перевірені за допомогою `checkEnv` з пакету `@nitra/check-env`. Це гарантує, що всі необхідні змінні оточення встановлені перед запуском програми.
|
|
21
|
+
|
|
22
|
+
```javascript title="Приклад підключення до PostgreSQL в /src/conn/pg.mjs"
|
|
23
|
+
import { checkEnv, env } from '@nitra/check-env'
|
|
24
|
+
import { SQL } from 'bun'
|
|
25
|
+
|
|
26
|
+
checkEnv(['PG_CONN'])
|
|
27
|
+
|
|
28
|
+
export const db = new SQL({ url: env.PG_CONN })
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### process.env
|
|
33
|
+
|
|
34
|
+
Прямий доступ до `process.env.X` у коді заборонений — його треба замінити на `env`:
|
|
35
|
+
|
|
36
|
+
> Стосується лише backend-пакетів (див. **Область застосування**). У frontend-пакетах (`vite` у `devDependencies`) — **не змінюй** `process.env.*` і **не додавай** імпорт `node:process`.
|
|
37
|
+
|
|
38
|
+
- **обов'язкова змінна** — `import { checkEnv, env } from '@nitra/check-env'` плюс `checkEnv(['X'])`
|
|
39
|
+
у тому ж файлі (приклад див. вище в розділі **CheckEnv**);
|
|
40
|
+
- **опційна змінна** — `import { env } from 'node:process'`:
|
|
41
|
+
|
|
42
|
+
```javascript title="Опційна змінна — env з node:process"
|
|
43
|
+
import { env } from 'node:process'
|
|
44
|
+
|
|
45
|
+
console.log(env.OPTIONAL_ENV_VAR)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Тимчасово приглушити перевірку для конкретного рядка можна коментарем
|
|
49
|
+
`// @7n/rules ignore-next-line checkEnv` безпосередньо перед використанням
|
|
50
|
+
(escape-hatch для legacy-коду, не для нових файлів).
|
|
51
|
+
|
|
52
|
+
Перевірка (JS-сканер): `../lib/check-env-scan.mjs`.
|
|
53
|
+
|
|
54
|
+
## Внутрішні аліаси для підключень до БД і GraphQL
|
|
55
|
+
|
|
56
|
+
Якщо в проекті є підключення до баз даних, зовнішніх graphql на кшталт:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
import { SQL } from 'bun'
|
|
60
|
+
|
|
61
|
+
// або
|
|
62
|
+
|
|
63
|
+
import sql from 'mssql'
|
|
64
|
+
|
|
65
|
+
// або
|
|
66
|
+
|
|
67
|
+
import { GraphQLClient } from '@nitra/graphql-request'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
то ці підключення повинні бути винесені в окремий файл, наприклад `/src/conn/pg.mjs`, в package.json повинні бути додано аліас:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"imports": {
|
|
75
|
+
"#conn/*": "./src/conn/*"
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
так виглядатиме підключення до PostgreSQL в коді:
|
|
82
|
+
|
|
83
|
+
```javascript title="Приклад підключення до PostgreSQL в /src/conn/pg.mjs"
|
|
84
|
+
import { checkEnv, env } from '@nitra/check-env'
|
|
85
|
+
import { SQL } from 'bun'
|
|
86
|
+
|
|
87
|
+
checkEnv(['PG_CONN'])
|
|
88
|
+
|
|
89
|
+
export const db = new SQL({ url: env.PG_CONN })
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
а так до GraphQL:
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
import { checkEnv, env } from '@nitra/check-env'
|
|
97
|
+
import { GraphQLClient } from '@nitra/graphql-request'
|
|
98
|
+
|
|
99
|
+
checkEnv(['QL', 'X_HASURA_ADMIN_SECRET'])
|
|
100
|
+
|
|
101
|
+
export { gql } from '@nitra/graphql-request'
|
|
102
|
+
|
|
103
|
+
export const graphQLClientSmart = new GraphQLClient(env.QL, {
|
|
104
|
+
headers: {
|
|
105
|
+
'X-Hasura-Admin-Secret': env.X_HASURA_ADMIN_SECRET
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
а в коді повинно бути використано:
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
import { pool } from '#conn/pg.mjs'
|
|
114
|
+
|
|
115
|
+
// або
|
|
116
|
+
|
|
117
|
+
import { gql, graphQLClient } from '@nitra/graphql-request'
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Нейминг файлів у `src/conn/`
|
|
121
|
+
|
|
122
|
+
Назва файла в `src/conn/` має одразу повідомляти, **до чого** підключаємось і **в якому режимі**:
|
|
123
|
+
|
|
124
|
+
- **GraphQL** — префікс `ql-`, далі ідентифікатор endpoint:
|
|
125
|
+
- `src/conn/ql-contract.mjs`
|
|
126
|
+
- `src/conn/ql-smart.mjs`
|
|
127
|
+
- **PostgreSQL** — префікс `pg-`, далі тип підключення (репліка vs мастер): `read` або `write`:
|
|
128
|
+
- `src/conn/pg-read.mjs`
|
|
129
|
+
- `src/conn/pg-write.mjs`
|
|
130
|
+
- **PostgreSQL до кількох БД** — додатково ідентифікатор підключення після типу:
|
|
131
|
+
- `src/conn/pg-read-smart.mjs`
|
|
132
|
+
- `src/conn/pg-write-contract.mjs`
|
|
133
|
+
- **MySQL** — префікс `mysql-` за тією ж схемою (`mysql-read.mjs`, `mysql-write-<id>.mjs` тощо).
|
|
134
|
+
- **MSSQL** — префікс `mssql-` за тією ж схемою (`mssql-read.mjs`, `mssql-write-<id>.mjs` тощо). Хоча npm-пакет один (`mssql`), а драйвер MS SQL Server під капотом T-SQL — у файловій назві відрізняємо MS SQL Server від MySQL, бо це різні СУБД, різні діалекти, різні рантаймні залежності. Якщо проєкт історично використовує `mysql-…` для MSSQL-підключень — він валідний і далі (для backward-compat), але новий код пишемо з префіксом `mssql-`.
|
|
135
|
+
|
|
136
|
+
Підключення до БД **обов'язково** має бути ідентифіковано як `read` (репліка) або `write` (мастер). Якщо з імені змінної оточення (наприклад, `env.PG_CONN`) це не очевидно — визнач режим за операціями в коді: якщо немає операцій зміни даних (`INSERT`/`UPDATE`/`DELETE`/DDL) — це `pg-read.mjs`, інакше `pg-write.mjs`.
|
|
137
|
+
|
|
138
|
+
### Експорти у файлах `src/conn/`
|
|
139
|
+
|
|
140
|
+
У файлах підключень **заборонений** `export default`. Експорт має бути **іменований** і збігатися з назвою файла в camelCase.
|
|
141
|
+
|
|
142
|
+
Приклад — `src/conn/ql-smart.mjs`:
|
|
143
|
+
|
|
144
|
+
```javascript title="❌ Так не можна"
|
|
145
|
+
export default new GraphQLClient(env.SMART_QL, {
|
|
146
|
+
headers: {
|
|
147
|
+
'X-Hasura-Admin-Secret': env.SMART_X_HASURA_ADMIN_SECRET
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
```javascript title="✅ Канон: іменований експорт за іменем файла"
|
|
153
|
+
export const qlSmart = new GraphQLClient(env.SMART_QL, {
|
|
154
|
+
headers: {
|
|
155
|
+
'X-Hasura-Admin-Secret': env.SMART_X_HASURA_ADMIN_SECRET
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Відповідно: `pg-read.mjs` → `export const pgRead = …`, `pg-write-contract.mjs` → `export const pgWriteContract = …`, `ql-contract.mjs` → `export const qlContract = …`.
|
|
161
|
+
|
|
162
|
+
Файли `index.*` у conn-каталозі пропускаються як можливий reexport-барель.
|
|
163
|
+
|
|
164
|
+
Перевірка (JS-сканери): `../lib/conn-file-rules.mjs` (нейминг, експорти), `../lib/conn-imports-scan.mjs` (факторні імпорти поза `src/conn/`); декларація аліаса `imports["#conn/*"]` у `package.json` — `checkConnAliasDeclaration` у `main.mjs`.
|
|
165
|
+
|
|
166
|
+
## Паузи через setTimeout
|
|
167
|
+
|
|
168
|
+
Заборонено робити паузи через `await new Promise(resolve => setTimeout(resolve, ms))` — таку обгортку треба замінити на promise-варіант `setTimeout` з `node:timers/promises`:
|
|
169
|
+
|
|
170
|
+
```javascript title="Замість new Promise + setTimeout"
|
|
171
|
+
import { setTimeout } from 'node:timers/promises'
|
|
172
|
+
|
|
173
|
+
await setTimeout(500)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Імпорт `setTimeout` з `node:timers/promises` затіняє глобальний таймер у файлі — якщо в тому ж файлі потрібен callback-варіант, імпортуй його під іншим іменем (наприклад, `import { setTimeout as setTimeoutCb } from 'node:timers'`).
|
|
177
|
+
|
|
178
|
+
Перевірка (JS-сканер): `../lib/promise-settimeout-scan.mjs`.
|
|
179
|
+
|
|
180
|
+
## Temporal API (заборона у Bun runtime)
|
|
181
|
+
|
|
182
|
+
У backend/Bun runtime-коді **не використовуй `Temporal`** (`Temporal.Now`, `Temporal.Instant`, імпорти з polyfill тощо). Bun 1.3.x (діапазон версій репозиторію — `bun >= 1.3`) ще не має глобального `Temporal` (`typeof Temporal === "undefined"`), тому агентам треба лишатися на сумісному `Date` API або передавати timestamp у чисті функції через параметр.
|
|
183
|
+
|
|
184
|
+
Перевірка `npx @7n/rules check` (AST-сканер `../lib/temporal-scan.mjs`) сканує JS/TS-код на identifier `Temporal` у backend workspace-коді.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Область застосування
|
|
2
|
+
|
|
3
|
+
Правило стосується **виключно backend Node.js workspace-пакетів** (jobs, GraphQL/HTTP-сервери, CLI). **Не застосовується** до frontend-пакетів, які бандляться в браузер: маркер — наявність `vite` у `devDependencies` пакета (`site/`, мобільні Capacitor-пакети, будь-яка Vue/Quasar SPA).
|
|
4
|
+
|
|
5
|
+
У браузерному середовищі:
|
|
6
|
+
|
|
7
|
+
- немає `node:process` — імпорт `import { env } from 'node:process'` resolve'иться у `undefined`, і `env.X` падає з `TypeError: Cannot read properties of undefined`;
|
|
8
|
+
- `process.env.X` у джерелах пакета відсутнє в рантаймі — Vite або взагалі не підставляє його, або підставляє лише `process.env.NODE_ENV`;
|
|
9
|
+
- усі змінні оточення для frontend задаються через `VITE_*` і доступні як `import.meta.env.VITE_X` (типобезпечно через `vite-check-env`); режим — `import.meta.env.MODE` / `import.meta.env.PROD`.
|
|
10
|
+
|
|
11
|
+
Тому **у frontend-пакетах не торкайся `process.env.*`** і **не додавай** `import { env } from 'node:process'`. Якщо натрапив на `process.env.NODE_ENV` у frontend-коді — заміна, якщо взагалі потрібна, лише на `import.meta.env.MODE`.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: fix-emit_types_config.mjs
|
|
4
|
+
resource: plugins/lang-js/rules/npm-module/emit_types_config/fix-emit_types_config.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: c13c69a5
|
|
7
|
+
model: openai-codex/gpt-5.4-mini
|
|
8
|
+
score: 100
|
|
9
|
+
issues: judge:inaccurate:0.99
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Огляд
|
|
14
|
+
|
|
15
|
+
`patterns` читає `tsconfig.emit-types.json` як базовий конфіг, щоб перевіряти й підтримувати узгодженість шаблонного правила для emit-types. Це read-only джерело поведінки: воно формує очікування для контракту конфіга без записів у ФС чи БД.
|
|
16
|
+
|
|
17
|
+
## Поведінка
|
|
18
|
+
|
|
19
|
+
1. `patterns` визначає набір правил для синхронізації шаблонного конфіга `tsconfig.emit-types.json` у `npm/tsconfig.emit-types.json`.
|
|
20
|
+
2. `patterns` слугує джерелом одного цільового виправлення для підтримки узгодженості між базовим конфігом і npm-варіантом.
|
|
21
|
+
3. `patterns` не виконує запис у файлову систему чи базу даних самостійно; воно лише описує, що саме має бути виправлено.
|
|
22
|
+
|
|
23
|
+
## Гарантії поведінки
|
|
24
|
+
|
|
25
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/npm-module/emit_types_config
|
|
4
|
+
resource: plugins/lang-js/rules/npm-module/emit_types_config/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
| Файл | Тип |
|
|
8
|
+
| ----------------------------------------------------- | --------- |
|
|
9
|
+
| [fix-emit_types_config.mjs](fix-emit_types_config.md) | JS Module |
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
## Rego-gate: конфігурація генерації типів `npm/tsconfig.emit-types.json`
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `npm-module.emit_types_config`
|
|
4
|
+
|
|
5
|
+
Цільовий файл: `npm/tsconfig.emit-types.json`
|
|
6
|
+
|
|
7
|
+
### Що перевіряється
|
|
8
|
+
|
|
9
|
+
Leaf-by-leaf порівняння з канонічним сніпетом (через `--data`): кожне поле всередині `compilerOptions` має точно відповідати очікуваному значенню. Якщо секція `compilerOptions` відсутня або не є обʼєктом — окрема deny-помилка.
|
|
10
|
+
|
|
11
|
+
Канонічний сніпет: [tsconfig.emit-types.json.snippet.json](./template/tsconfig.emit-types.json.snippet.json)
|
|
12
|
+
|
|
13
|
+
### Допустимі відхилення
|
|
14
|
+
|
|
15
|
+
Додаткові поля у `compilerOptions` (наприклад `rootDir`, `baseUrl`) не спричиняють помилку — перевіряється лише наявність і коректність обовʼязкових ключів зі сніпету.
|
|
16
|
+
|
|
17
|
+
### Приклади
|
|
18
|
+
|
|
19
|
+
✓ Правильно:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"compilerOptions": {
|
|
24
|
+
"allowJs": true,
|
|
25
|
+
"declaration": true,
|
|
26
|
+
"emitDeclarationOnly": true,
|
|
27
|
+
"outDir": "types",
|
|
28
|
+
"skipLibCheck": true
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
✗ Неправильно — неправильний `outDir`:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{ "compilerOptions": { "outDir": "dist" } }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
✗ Неправильно — відсутній `compilerOptions`:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{}
|
|
43
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Перевірка `npm/tsconfig.emit-types.json` (npm-module.mdc).
|
|
2
|
+
#
|
|
3
|
+
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
+
# Структура --data сформована з template/tsconfig.emit-types.json.snippet.json.
|
|
5
|
+
# Snippet — 2-рівнева мапа (section → key → expected). Walker такий самий,
|
|
6
|
+
# як для ga.vscode_settings / bun.bunfig.
|
|
7
|
+
package npm_module.emit_types_config
|
|
8
|
+
|
|
9
|
+
import rego.v1
|
|
10
|
+
|
|
11
|
+
# Leaf-by-leaf: коли section присутня й обʼєкт.
|
|
12
|
+
deny contains msg if {
|
|
13
|
+
some section, expected_inner in data.template.snippet
|
|
14
|
+
inner := object.get(input, section, {})
|
|
15
|
+
is_object(inner)
|
|
16
|
+
some leaf_key, expected_value in expected_inner
|
|
17
|
+
actual := object.get(inner, leaf_key, null)
|
|
18
|
+
actual != expected_value
|
|
19
|
+
msg := sprintf("npm/tsconfig.emit-types.json: %s.%s має бути %v (npm-module.mdc)", [section, leaf_key, expected_value])
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# Section відсутня (null) або не обʼєкт.
|
|
23
|
+
deny contains msg if {
|
|
24
|
+
some section in object.keys(data.template.snippet)
|
|
25
|
+
raw := object.get(input, section, null)
|
|
26
|
+
not is_object(raw)
|
|
27
|
+
msg := sprintf("npm/tsconfig.emit-types.json: відсутній %s (npm-module.mdc)", [section])
|
|
28
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: main.mjs
|
|
4
|
+
resource: plugins/lang-js/rules/npm-module/header_doc_pointer/main.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: 63a40982
|
|
7
|
+
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
+
score: 100
|
|
9
|
+
issues: judge:inaccurate:0.98
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Огляд
|
|
14
|
+
|
|
15
|
+
Файл забезпечує валідацію відповідності конвенціям документації для файлів правил, розташованих у директорії `.cursor/rules/`, та файлів навичок у `.cursor/skills/`. Він сканує кодову базу у директорії `js/` для пошуку файлів документації, перевіряючи, чи не перевищує JSDoc-блок довжину одного рядка для опису поведінки кожного файлу правила або навички.
|
|
16
|
+
|
|
17
|
+
## Поведінка
|
|
18
|
+
|
|
19
|
+
Поведінка:
|
|
20
|
+
|
|
21
|
+
1. Викликається `main`.
|
|
22
|
+
2. Створюється репортер.
|
|
23
|
+
3. Для сегментів `npm/rules` та `npm/skills` сканується кожен піддиректорія правил або скілів.
|
|
24
|
+
4. Для кожної піддиректорії перевіряється її каталог `js/`.
|
|
25
|
+
5. У каталозі `js/` скануються всі файли з розширенням `.mjs`, окрім тестів.
|
|
26
|
+
6. Для кожного знайденого файлу:
|
|
27
|
+
а. Визначається відповідний файл документації у `docs/`, використовуючи ім'я без розширення.
|
|
28
|
+
б. Якщо такий файл документації існує, аналізується перше заголовочне JSDoc-блоку у коді.
|
|
29
|
+
в. Якщо JSDoc-блок відсутній, перехід до наступного файлу.
|
|
30
|
+
г. Якщо JSDoc-блок присутній, рахується кількість непустіших рядків у його тілі, ігноруючи відступ.
|
|
31
|
+
д. Якщо ця кількість перевищує один, це реєструється як порушення, оскільки документ повинен лише посилатися на поведінку.
|
|
32
|
+
7. Після обробки всіх файлів повертається код виходу репортера.
|
|
33
|
+
|
|
34
|
+
## Публічний API
|
|
35
|
+
|
|
36
|
+
main — сканує файли правил у директоріях `npm/rules/*\/js/*.mjs` та `npm/skills/*\/js/*.mjs`, а також керує генерацією документації, посилаючись на існуючі файли `docs/<stem>.md`.
|
|
37
|
+
|
|
38
|
+
## Гарантії поведінки
|
|
39
|
+
|
|
40
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## Module-level JSDoc як pointer
|
|
2
|
+
|
|
3
|
+
Якщо поряд із `js/<stem>.mjs` є файл `js/docs/<stem>.md` — module-level JSDoc у `.mjs` має бути **pointer** (не більше одного непорожнього рядка), а не повноцінний наратив.
|
|
4
|
+
|
|
5
|
+
Логіка перевірки (`header_doc_pointer.mjs`):
|
|
6
|
+
|
|
7
|
+
- Сканується перший JSDoc-блок (`/** … */`) до першого `import`/`export` у файлі.
|
|
8
|
+
- Підраховуються непорожні рядки тіла (після зрізання `*`-відступу).
|
|
9
|
+
- Якщо їх більше одного — `check` падає з повідомленням про те, що `docs/<stem>.md` вже описує поведінку і module-level JSDoc має залишатись коротким.
|
|
10
|
+
|
|
11
|
+
**Покриття:** `npm/rules/*/js/*.mjs` і `npm/skills/*/js/*.mjs` (не тестові файли `*.test.mjs`). Якщо `docs/<stem>.md` відсутня — обмежень на довжину JSDoc немає.
|
|
12
|
+
|
|
13
|
+
**Приклад правильного pointer-JSDoc:**
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
/** @see ./docs/package_structure.md */
|
|
17
|
+
import { existsSync } from 'node:fs'
|
|
18
|
+
```
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/** Контракт: ./docs/header_doc_pointer.md */
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { readFile, readdir } from 'node:fs/promises'
|
|
4
|
+
import { basename, join } from 'node:path'
|
|
5
|
+
|
|
6
|
+
import { createViolationReporter } from '@7n/rules/scripts/lib/lint-surface/violation-reporter.mjs'
|
|
7
|
+
|
|
8
|
+
/** Перший JSDoc-блок у файлі (не-жадібний). */
|
|
9
|
+
const MODULE_JSDOC_RE = /\/\*\*[\s\S]*?\*\//
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `import` або `export` на початку рядка — межа між module-level і body.
|
|
13
|
+
* Regex, не AST: нас цікавить тільки текстова позиція, не семантика JS.
|
|
14
|
+
*/
|
|
15
|
+
const CODE_START_RE = /^(?:import|export)\b/m
|
|
16
|
+
|
|
17
|
+
const NON_WHITESPACE_RE = /\S/
|
|
18
|
+
const STAR_INDENT_RE = /^\s*\*\s?/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Кількість непорожніх рядків між `/**` і `*\/` (після зрізання `*`-відступу).
|
|
22
|
+
* @param {string} block повний текст JSDoc-блоку з обрамленням
|
|
23
|
+
* @returns {number} кількість непорожніх рядків у тілі
|
|
24
|
+
*/
|
|
25
|
+
function contentLineCount(block) {
|
|
26
|
+
return block
|
|
27
|
+
.split('\n')
|
|
28
|
+
.slice(1, -1)
|
|
29
|
+
.filter(l => NON_WHITESPACE_RE.test(l.replace(STAR_INDENT_RE, ''))).length
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Повертає module-level JSDoc або `null`, якщо його немає.
|
|
34
|
+
* @param {string} source вміст mjs-файлу
|
|
35
|
+
* @returns {string|null} текст module-level JSDoc-блоку або null
|
|
36
|
+
*/
|
|
37
|
+
function moduleJsDoc(source) {
|
|
38
|
+
const codeStart = CODE_START_RE.exec(source)
|
|
39
|
+
const prefix = codeStart ? source.slice(0, codeStart.index) : source
|
|
40
|
+
const m = MODULE_JSDOC_RE.exec(prefix)
|
|
41
|
+
return m ? m[0] : null
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Чи `.mjs`-файл, що не є тестом (`*.test.mjs`).
|
|
46
|
+
* @param {import('node:fs').Dirent} fileEntry запис каталогу
|
|
47
|
+
* @returns {boolean} true для звичайних source-файлів
|
|
48
|
+
*/
|
|
49
|
+
function isSourceMjs(fileEntry) {
|
|
50
|
+
return fileEntry.isFile() && fileEntry.name.endsWith('.mjs') && !fileEntry.name.endsWith('.test.mjs')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Перевіряє один source-файл: якщо поряд є `docs/<stem>.md` і module-level JSDoc
|
|
55
|
+
* містить >1 непорожній рядок — репортить порушення.
|
|
56
|
+
* @param {string} jsDir каталог `js/`
|
|
57
|
+
* @param {import('node:fs').Dirent} fileEntry запис файлу
|
|
58
|
+
* @param {string} cwd корінь репозиторію
|
|
59
|
+
* @param {ReturnType<typeof createViolationReporter>} reporter репортер
|
|
60
|
+
* @returns {Promise<void>}
|
|
61
|
+
*/
|
|
62
|
+
async function checkSourceFile(jsDir, fileEntry, cwd, reporter) {
|
|
63
|
+
const stem = basename(fileEntry.name, '.mjs')
|
|
64
|
+
const docsPath = join(jsDir, 'docs', `${stem}.md`)
|
|
65
|
+
if (!existsSync(docsPath)) return
|
|
66
|
+
|
|
67
|
+
const filePath = join(jsDir, fileEntry.name)
|
|
68
|
+
const source = await readFile(filePath, 'utf8')
|
|
69
|
+
const block = moduleJsDoc(source)
|
|
70
|
+
if (!block) return
|
|
71
|
+
|
|
72
|
+
const count = contentLineCount(block)
|
|
73
|
+
if (count > 1) {
|
|
74
|
+
reporter.fail(
|
|
75
|
+
`${filePath.slice(cwd.length + 1)}: docs/${stem}.md вже описує поведінку — module-level JSDoc має бути pointer (≤1 рядок, зараз ${count})`
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Перевіряє всі source-файли в одному `js/`-каталозі правила/скіла.
|
|
82
|
+
* @param {string} jsDir каталог `js/`
|
|
83
|
+
* @param {string} cwd корінь репозиторію
|
|
84
|
+
* @param {ReturnType<typeof createViolationReporter>} reporter репортер
|
|
85
|
+
* @returns {Promise<void>}
|
|
86
|
+
*/
|
|
87
|
+
async function checkJsDir(jsDir, cwd, reporter) {
|
|
88
|
+
for (const fileEntry of await readdir(jsDir, { withFileTypes: true })) {
|
|
89
|
+
if (!isSourceMjs(fileEntry)) continue
|
|
90
|
+
await checkSourceFile(jsDir, fileEntry, cwd, reporter)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Перевіряє один base-сегмент (`npm/rules` чи `npm/skills`): обходить піддиректорії
|
|
96
|
+
* правил/скілів і їхні `js/`-каталоги.
|
|
97
|
+
* @param {string} absBase абсолютний шлях до base-сегмента
|
|
98
|
+
* @param {string} cwd корінь репозиторію
|
|
99
|
+
* @param {ReturnType<typeof createViolationReporter>} reporter репортер
|
|
100
|
+
* @returns {Promise<void>}
|
|
101
|
+
*/
|
|
102
|
+
async function checkBaseSegment(absBase, cwd, reporter) {
|
|
103
|
+
for (const ruleEntry of await readdir(absBase, { withFileTypes: true })) {
|
|
104
|
+
if (!ruleEntry.isDirectory() || ruleEntry.name.startsWith('.')) continue
|
|
105
|
+
|
|
106
|
+
const jsDir = join(absBase, ruleEntry.name, 'js')
|
|
107
|
+
if (!existsSync(jsDir)) continue
|
|
108
|
+
|
|
109
|
+
await checkJsDir(jsDir, cwd, reporter)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Сканує `npm/rules/*\/js/*.mjs` і `npm/skills/*\/js/*.mjs`.
|
|
115
|
+
* Якщо поряд існує `docs/<stem>.md` — module-level JSDoc має бути pointer (≤1 рядок),
|
|
116
|
+
* а не наратив; якщо docs немає — без обмежень.
|
|
117
|
+
* @param {import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст лінту (cwd, репортер).
|
|
118
|
+
* @returns {Promise<import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintResult>} результат перевірки з pass/fail.
|
|
119
|
+
*/
|
|
120
|
+
export async function lint(ctx) {
|
|
121
|
+
const cwd = ctx.cwd
|
|
122
|
+
const reporter = createViolationReporter(ctx)
|
|
123
|
+
|
|
124
|
+
for (const baseSegment of ['npm/rules', 'npm/skills']) {
|
|
125
|
+
const absBase = join(cwd, baseSegment)
|
|
126
|
+
if (!existsSync(absBase)) continue
|
|
127
|
+
await checkBaseSegment(absBase, cwd, reporter)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return reporter.result()
|
|
131
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "auto": { "glob": "npm/**" } }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Оформлення репозиторію для npm модуля
|
|
3
|
+
globs: "npm/**,**/package.json,**/hk.pkl,.github/workflows/npm-publish.yml,**/tsconfig*.json"
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
version: '1.14'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Bun monorepo: workspace **`npm/`**, кореневий **`package.json`**, **`.github/workflows/`**; опційно **`demo/`**.
|
|
9
|
+
|
|
10
|
+
## Версія та CHANGELOG
|
|
11
|
+
|
|
12
|
+
Версію (`version` у **`npm/package.json`**) і **`npm/CHANGELOG.md`** **не редагуй вручну** — навіть для hotfix. Єдиний артефакт зміни — **change-файл** (`npx @7n/n ch [--bump <major|minor|patch>] [--section <Added|Changed|Fixed|Removed>] [--message "<…>"]`); bump `version` і генерацію секції CHANGELOG робить `n-rules release` у CI на `main`. Будь-який ручний bump `version` поза CI завалює `check changelog` — навіть із change-файлом.
|
|
13
|
+
|
|
14
|
+
Повна модель (база порівняння, інверсія шляхів, формат CHANGELOG, post-release-інваріант «верхня секція CHANGELOG == `version`») — у **`n-changelog.mdc`** (джерело істини). Це правило їй підпорядковане й власних інструкцій bump/CHANGELOG не дублює.
|
|
15
|
+
|
|
16
|
+
### Канонічний крок `npm-changelog` у hk.pkl
|
|
17
|
+
|
|
18
|
+
У v14 команду `check` прибрано (уніфікована поверхня `lint`) — виклик `npx @7n/rules check changelog` у hk.pkl **завалить** кожен коміт з `❌ Невідома команда: check`. Канонічний pre-commit-крок (hk `amends hk@1.42.0`):
|
|
19
|
+
|
|
20
|
+
```pkl
|
|
21
|
+
["npm-changelog"] {
|
|
22
|
+
glob = List("npm/**")
|
|
23
|
+
check_first = false
|
|
24
|
+
fix = "N_RULES_CHANGELOG_AUTOFIX=1 bun ./npm/bin/n-rules.js lint changelog"
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Лише `fix` (без `check`): env-прапорець `N_RULES_CHANGELOG_AUTOFIX=1` вмикає autofix-режим — за відсутності change-файлу правило само створює його (`patch`/`Changed`, subject останнього коміту) і одразу ставить у git-індекс (`git add`) через `writeChange`/`reportOrFixMissingChangeFile`. Тому додатковий `stage = List("npm/.changes/**")` у цьому wiring **не потрібен** — індексація вже всередині JS-кроку. `package_structure` (`npx @7n/rules lint npm-module`) валідує цей крок: fail на застарілий `check changelog` і fail, якщо кроку `npm-changelog` немає взагалі.
|
|
29
|
+
|
|
30
|
+
## Швидкий gate через conftest
|
|
31
|
+
|
|
32
|
+
Rego-пакети (запускаються через `npx @7n/rules fix`):
|
|
33
|
+
|
|
34
|
+
- [package.json.snippet.json](./npm_package_json/template/package.json.snippet.json)
|
|
35
|
+
- [package.json.snippet.json](./root_package_json/template/package.json.snippet.json)
|
|
36
|
+
- [tsconfig.emit-types.json.snippet.json](./emit_types_config/template/tsconfig.emit-types.json.snippet.json)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: fix-npm_package_json.mjs
|
|
4
|
+
resource: plugins/lang-js/rules/npm-module/npm_package_json/fix-npm_package_json.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: 4c61a5ff
|
|
7
|
+
model: openai-codex/gpt-5.4-mini
|
|
8
|
+
score: 100
|
|
9
|
+
issues: judge:inaccurate:0.96
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Огляд
|
|
14
|
+
|
|
15
|
+
`patterns` формує узгоджений набір правил для `package.json`, щоб проєктні package-файли лишалися в очікуваному стані за контрактом, який спирається на конфіг з `package.json`. Read-only: не пише у ФС чи БД.
|
|
16
|
+
|
|
17
|
+
## Поведінка
|
|
18
|
+
|
|
19
|
+
1. `patterns` визначає набір правил для вирівнювання `npm/package.json` з еталонним шаблоном.
|
|
20
|
+
2. Під час застосування кожне правило бере до уваги конфігурацію з `package.json` і використовує її як основу для корекції цільового файлу.
|
|
21
|
+
3. Мета `patterns` — забезпечити однакову структуру й очікуваний вміст `npm/package.json` у межах проєкту.
|
|
22
|
+
4. Значення `patterns` не виконує записів у файлову систему чи базу даних; воно лише описує, що і як має бути приведено до узгодженого стану.
|
|
23
|
+
|
|
24
|
+
## Гарантії поведінки
|
|
25
|
+
|
|
26
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/npm-module/npm_package_json
|
|
4
|
+
resource: plugins/lang-js/rules/npm-module/npm_package_json/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
| Файл | Тип |
|
|
8
|
+
| --------------------------------------------------- | --------- |
|
|
9
|
+
| [fix-npm_package_json.mjs](fix-npm_package_json.md) | JS Module |
|