@nitra/cursor 12.8.5 → 12.8.7
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/bin/n-cursor.js +5 -5
- package/package.json +1 -1
- package/rules/abie/js/http_route_base.mdc +25 -0
- package/rules/abie/js/ua_http_route.mdc +1 -1
- package/rules/abie/main.mdc +12 -0
- package/rules/adr/js/hooks.mdc +32 -0
- package/rules/adr/js/madr_format.mdc +96 -0
- package/rules/adr/js/settings_policy.mdc +34 -0
- package/rules/adr/main.mdc +13 -95
- package/rules/bun/js/bunfig.mdc +12 -0
- package/rules/bun/js/layout.mdc +60 -0
- package/rules/bun/js/lint.mdc +9 -0
- package/rules/bun/js/package_json.mdc +19 -0
- package/rules/bun/main.mdc +9 -61
- package/rules/capacitor/js/ios_spm.mdc +69 -0
- package/rules/capacitor/js/version.mdc +29 -0
- package/rules/capacitor/main.mdc +8 -22
- package/rules/changelog/js/agent-workflow.mdc +15 -0
- package/rules/changelog/js/changelog-format.mdc +33 -0
- package/rules/changelog/js/comparison-models.mdc +40 -0
- package/rules/changelog/main.mdc +4 -98
- package/rules/ci4/js/marksman_config.mdc +31 -0
- package/rules/ci4/js/vscode_extensions.mdc +33 -0
- package/rules/ci4/main.mdc +14 -14
- package/rules/docker/js/compile.mdc +44 -0
- package/rules/docker/js/hadolint.mdc +50 -0
- package/rules/docker/js/mirror.mdc +13 -0
- package/rules/docker/js/multistage.mdc +13 -0
- package/rules/docker/js/native-addon.mdc +43 -0
- package/rules/docker/js/nginx-tag.mdc +7 -0
- package/rules/docker/js/nginx-user.mdc +37 -0
- package/rules/docker/js/non-root.mdc +39 -0
- package/rules/docker/main.mdc +15 -196
- package/rules/ga/js/lint_toolchain.mdc +15 -0
- package/rules/ga/js/required_workflows.mdc +35 -0
- package/rules/ga/js/vscode.mdc +17 -0
- package/rules/ga/js/workflow_common.mdc +108 -0
- package/rules/ga/js/workflows.mdc +32 -0
- package/rules/ga/js/zizmor.mdc +7 -0
- package/rules/ga/main.mdc +17 -125
- package/rules/graphql/js/tooling.mdc +13 -0
- package/rules/graphql/js/vscode_extensions.mdc +13 -0
- package/rules/graphql/main.mdc +3 -22
- package/rules/hasura/js/internal_urls.mdc +27 -0
- package/rules/hasura/js/migrations.mdc +13 -0
- package/rules/hasura/js/svc_hl.mdc +17 -0
- package/rules/hasura/main.mdc +8 -30
- package/rules/image-avif/js/avif_generation.mdc +26 -0
- package/rules/image-avif/js/package_json_optout.mdc +21 -0
- package/rules/image-avif/main.mdc +7 -34
- package/rules/image-compress/js/package_json.mdc +7 -0
- package/rules/image-compress/js/package_setup.mdc +13 -0
- package/rules/image-compress/main.mdc +4 -12
- package/rules/js/docs/index.md +3 -3
- package/rules/js/js/dep-policy.mdc +17 -0
- package/rules/js/js/eslint-config.mdc +28 -0
- package/rules/js/js/extensions.mdc +8 -0
- package/rules/js/js/file-extensions.mdc +12 -0
- package/rules/js/js/for-in.mdc +26 -0
- package/rules/js/js/jscpd.mdc +42 -0
- package/rules/js/js/knip.mdc +15 -0
- package/rules/js/js/lint-js-workflow.mdc +58 -0
- package/rules/js/js/oxlintrc.mdc +20 -0
- package/rules/js/js/package-json.mdc +31 -0
- package/rules/js/js/tests.mdc +9 -0
- package/rules/js/js/utils-lib-structure.mdc +15 -0
- package/rules/js/main.mdc +21 -214
- package/rules/js-bun-db/js/bun-sql-migration.mdc +15 -0
- package/rules/js-bun-db/js/connection.mdc +42 -0
- package/rules/js-bun-db/js/pg-format-identifiers.mdc +102 -0
- package/rules/js-bun-db/js/pg-format-shim.mdc +99 -0
- package/rules/js-bun-db/js/pg-leftover.mdc +27 -0
- package/rules/js-bun-db/js/pg-listen-notify.mdc +51 -0
- package/rules/js-bun-db/js/query-safety.mdc +117 -0
- package/rules/js-bun-db/js/sql-array.mdc +88 -0
- package/rules/js-bun-db/js/unsafe.mdc +65 -0
- package/rules/js-bun-db/main.mdc +15 -605
- package/rules/js-bun-redis/js/imports.mdc +47 -0
- package/rules/js-bun-redis/js/package_json.mdc +44 -0
- package/rules/js-bun-redis/main.mdc +3 -11
- package/rules/js-mssql/js/mssql-in-list.mdc +38 -0
- package/rules/js-mssql/js/mssql-pool.mdc +56 -0
- package/rules/js-mssql/js/mssql-query-template.mdc +33 -0
- package/rules/js-mssql/js/mssql-tvp.mdc +75 -0
- package/rules/js-mssql/js/mssql-version.mdc +7 -0
- package/rules/js-mssql/main.mdc +10 -198
- package/rules/js-run/js/check-env.mdc +35 -0
- package/rules/js-run/js/conn-aliases.mdc +109 -0
- package/rules/js-run/js/jsconfig.mdc +20 -0
- package/rules/js-run/js/otel-configmap.mdc +6 -0
- package/rules/js-run/js/pino.mdc +6 -0
- package/rules/js-run/js/project-structure.mdc +11 -0
- package/rules/js-run/js/runtime.mdc +14 -0
- package/rules/js-run/js/scope.mdc +11 -0
- package/rules/js-run/js/settimeout.mdc +11 -0
- package/rules/js-run/js/temporal.mdc +5 -0
- package/rules/js-run/main.mdc +16 -218
- package/rules/k8s/js/configmap.mdc +41 -0
- package/rules/k8s/js/deployment_resources.mdc +49 -0
- package/rules/k8s/js/hasura_httproute.mdc +91 -0
- package/rules/k8s/js/hpa_apiversion.mdc +27 -0
- package/rules/k8s/js/ingress_gateway.mdc +16 -0
- package/rules/k8s/js/kustomize_structure.mdc +144 -0
- package/rules/k8s/js/lint_k8s.mdc +72 -0
- package/rules/k8s/js/multidoc_yaml.mdc +5 -0
- package/rules/k8s/js/network_policy.mdc +136 -0
- package/rules/k8s/js/schema_modeline.mdc +57 -0
- package/rules/k8s/js/service.mdc +44 -0
- package/rules/k8s/js/topology_hpa_pdb.mdc +181 -0
- package/rules/k8s/main.mdc +30 -843
- package/rules/nginx-default-tpl/js/dockerfile.mdc +36 -0
- package/rules/nginx-default-tpl/js/http-route.mdc +41 -0
- package/rules/nginx-default-tpl/js/ini-keys.mdc +21 -0
- package/rules/nginx-default-tpl/js/template-structure.mdc +86 -0
- package/rules/nginx-default-tpl/js/vscode.mdc +37 -0
- package/rules/nginx-default-tpl/main.mdc +6 -112
- package/rules/npm-module/js/docs/index.md +5 -5
- package/rules/npm-module/js/docs/rule_meta.md +6 -6
- package/rules/npm-module/js/docs/skill_meta.md +8 -8
- package/rules/npm-module/js/header_doc_pointer.mdc +18 -0
- package/rules/npm-module/js/package_structure.mdc +62 -0
- package/rules/npm-module/js/rule_meta.mdc +11 -0
- package/rules/npm-module/js/skill_meta.mdc +11 -0
- package/rules/npm-module/main.mdc +10 -55
- package/rules/php/js/lint_php_yml.mdc +12 -0
- package/rules/php/js/tooling.mdc +66 -0
- package/rules/php/main.mdc +7 -66
- package/rules/python/js/lint_python_yml.mdc +23 -0
- package/rules/python/js/pyproject_toml.mdc +32 -0
- package/rules/python/js/tooling.mdc +23 -0
- package/rules/python/main.mdc +9 -33
- package/rules/rego/js/rego-lint.mdc +31 -0
- package/rules/rego/js/vscode_extensions.mdc +11 -0
- package/rules/rego/js/vscode_settings.mdc +13 -0
- package/rules/rego/main.mdc +8 -24
- package/rules/rust/js/coverage.mdc +28 -0
- package/rules/rust/js/lint.mdc +22 -0
- package/rules/rust/js/tauri_composition.mdc +8 -0
- package/rules/rust/js/vscode_extensions.mdc +12 -0
- package/rules/rust/main.mdc +8 -38
- package/rules/security/js/rego_policies.mdc +15 -0
- package/rules/security/js/sample_secret.mdc +19 -0
- package/rules/security/js/trufflehog.mdc +21 -0
- package/rules/security/main.mdc +7 -35
- package/rules/style/js/admin-table.mdc +88 -0
- package/rules/style/js/colors.mdc +21 -0
- package/rules/style/js/gap.mdc +22 -0
- package/rules/style/js/quasar-fixes.mdc +32 -0
- package/rules/style/js/quasar.mdc +7 -0
- package/rules/style/js/tooling.mdc +85 -0
- package/rules/style/main.mdc +13 -253
- package/rules/tauri/js/cargo_mutants_config.mdc +39 -0
- package/rules/tauri/js/tool_surface.mdc +21 -0
- package/rules/tauri/js/tooling.mdc +25 -0
- package/rules/tauri/main.mdc +8 -78
- package/rules/test/js/cargo_mutants_config.mdc +18 -0
- package/rules/test/js/docs/index.md +7 -7
- package/rules/test/js/location.mdc +52 -0
- package/rules/test/js/no-console-store-restore.mdc +11 -0
- package/rules/test/js/no-process-chdir.mdc +15 -0
- package/rules/test/js/no-relative-fs-path.mdc +22 -0
- package/rules/test/js/sandbox-aware-test.mdc +28 -0
- package/rules/test/js/stryker_config.mdc +26 -0
- package/rules/test/js/vitest-config-pool-forks.mdc +33 -0
- package/rules/test/main.mdc +18 -184
- package/rules/text/js/ci-lint-text.mdc +15 -0
- package/rules/text/js/cspell.mdc +81 -0
- package/rules/text/js/dotenv-linter.mdc +16 -0
- package/rules/text/js/forbidden-prettier.mdc +13 -0
- package/rules/text/js/markdownlint.mdc +25 -0
- package/rules/text/js/oxfmt.mdc +35 -0
- package/rules/text/js/package-json.mdc +26 -0
- package/rules/text/js/shellcheck.mdc +18 -0
- package/rules/text/js/v8r.mdc +23 -0
- package/rules/text/js/vscode.mdc +86 -0
- package/rules/text/main.mdc +20 -237
- package/rules/vue/js/composition-api.mdc +82 -0
- package/rules/vue/js/nheader-layout.mdc +171 -0
- package/rules/vue/js/node-imports.mdc +25 -0
- package/rules/vue/js/quasar-ui.mdc +32 -0
- package/rules/vue/js/structure.mdc +101 -0
- package/rules/vue/js/testing.mdc +32 -0
- package/rules/vue/js/tfm-translations.mdc +26 -0
- package/rules/vue/js/vite-config.mdc +126 -0
- package/rules/vue/js/vite-env.mdc +55 -0
- package/rules/vue/js/vue-imports.mdc +25 -0
- package/rules/vue/main.mdc +16 -640
- package/scripts/auto-rules.mjs +6 -6
- package/scripts/auto-skills.mjs +3 -3
- package/scripts/docs/auto-rules.md +17 -31
- package/scripts/docs/auto-skills.md +18 -163
- package/scripts/docs/index.md +16 -16
- package/scripts/lib/docs/index.md +36 -36
- package/scripts/lib/docs/mirror-parity.md +7 -7
- package/scripts/lib/docs/rule-meta.md +12 -12
- package/scripts/lib/docs/skill-meta.md +9 -9
- package/scripts/lib/docs/worktree-notice.md +10 -8
- package/scripts/lib/rule-meta.mjs +6 -6
- package/scripts/lib/skill-meta.mjs +6 -6
- package/scripts/lib/worktree-notice.mjs +2 -2
- package/scripts/utils/docs/index.md +14 -14
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
## Dockerfile — стиснення статики та envsubst шаблону
|
|
2
|
+
|
|
3
|
+
Dockerfile потребує двох кроків, пов'язаних з nginx-шаблоном.
|
|
4
|
+
|
|
5
|
+
### Стиснення статики (gzip_static)
|
|
6
|
+
|
|
7
|
+
Щоб nginx міг використовувати `gzip_static on`, файли необхідно стиснути під час збирання образу:
|
|
8
|
+
|
|
9
|
+
```dockerfile
|
|
10
|
+
RUN find /usr/share/nginx/html -type f \( \
|
|
11
|
+
-name '*.js' -o -name '*.css' -o -name '*.map' -o -name '*.xml' -o \
|
|
12
|
+
-name '*.webmanifest' -o -name '*.html' -o -name '*.wasm' -o -name '*.ttf' \
|
|
13
|
+
\) -exec gzip -k {} +
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Прапорець `-k` зберігає оригінальний файл поруч зі стиснутим `.gz`.
|
|
17
|
+
|
|
18
|
+
### envsubst для default.conf.template
|
|
19
|
+
|
|
20
|
+
Для підстановки змінних середовища у шаблон:
|
|
21
|
+
|
|
22
|
+
```dockerfile
|
|
23
|
+
# 1) Витягнути імена змінних з ini (ігноруємо коментарі/порожні)
|
|
24
|
+
# 2) Зробити список для envsubst: $NAMESPACE $NAMESPACE2 ...
|
|
25
|
+
# 3) Підвантажити значення з ini і підставити лише їх
|
|
26
|
+
RUN NAMES=$(sed -nE '/^\s*[#;]/d; /^\s*$/d; s/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=.*/\1/p' /tpl/values-$BRANCH.ini) && \
|
|
27
|
+
VARS=$(printf '%s\n' $NAMES | awk '{printf "$%s ", $0}') && \
|
|
28
|
+
export $(grep -v '^#' /tpl/values-$BRANCH.ini | xargs) && \
|
|
29
|
+
envsubst "$VARS" < /tpl/default.conf.template > /app/default.conf
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Перевірки (автоматичні):
|
|
33
|
+
|
|
34
|
+
- Dockerfile містить `find … /usr/share/nginx/html … gzip -k` — крок стиснення статики
|
|
35
|
+
- Dockerfile містить `envsubst` і посилання на `default.conf.template`
|
|
36
|
+
- Якщо немає жодного Dockerfile / Containerfile поруч з `default.conf.template` — це помилка
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
## HTTPRoute в k8s — редирект і backendRefs
|
|
2
|
+
|
|
3
|
+
Якщо в `default.conf.template` були `proxy_pass`-секції — їхню логіку потрібно перенести
|
|
4
|
+
до HTTPRoute в k8s. `default.conf.template` **не повинен** містити жодного proxy.
|
|
5
|
+
|
|
6
|
+
HTTPRoute має містити два правила:
|
|
7
|
+
|
|
8
|
+
1. **Exact → RequestRedirect 301 (https)** — редирект з `/$PUBLIC_PATH` на `/$PUBLIC_PATH/`
|
|
9
|
+
2. **PathPrefix → backendRefs:8080** — проксі трафіку на сервіс
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
spec:
|
|
13
|
+
rules:
|
|
14
|
+
- matches:
|
|
15
|
+
- path:
|
|
16
|
+
type: Exact
|
|
17
|
+
value: /$PUBLIC_PATH
|
|
18
|
+
filters:
|
|
19
|
+
- type: RequestRedirect
|
|
20
|
+
requestRedirect:
|
|
21
|
+
scheme: https
|
|
22
|
+
path:
|
|
23
|
+
type: ReplaceFullPath
|
|
24
|
+
replaceFullPath: /$PUBLIC_PATH/
|
|
25
|
+
statusCode: 301
|
|
26
|
+
- matches:
|
|
27
|
+
- path:
|
|
28
|
+
type: PathPrefix
|
|
29
|
+
value: /$PUBLIC_PATH/
|
|
30
|
+
backendRefs:
|
|
31
|
+
- name: $SERVICE_NAME
|
|
32
|
+
port: 8080
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
де `$PUBLIC_PATH` підставляється з ini-файлу dev-середовища, а для інших середовищ — через `kustomization.yaml`.
|
|
36
|
+
`$SERVICE_NAME` — ім'я k8s-сервісу, що приймає трафік на порту 8080.
|
|
37
|
+
|
|
38
|
+
Перевірки (автоматичні):
|
|
39
|
+
|
|
40
|
+
- перше правило має `path.type: Exact` і фільтр `RequestRedirect` з `scheme: https`, `path.type: ReplaceFullPath`, `statusCode: 301`
|
|
41
|
+
- друге правило має `path.type: PathPrefix` і `backendRefs` з `port: 8080`
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## Конфігураційні *.ini файли і envsubst
|
|
2
|
+
|
|
3
|
+
Поруч з `default.conf.template` мають бути конфігураційні файли `*.ini` для кожного
|
|
4
|
+
середовища (наприклад, `values-dev.ini`, `values-prod.ini`).
|
|
5
|
+
|
|
6
|
+
Формат ini-файлу:
|
|
7
|
+
|
|
8
|
+
```ini
|
|
9
|
+
PUBLIC_PATH=/app
|
|
10
|
+
SERVICE_NAME=my-frontend
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Кожна змінна з `*.ini` **повинна використовуватись** у `default.conf.template` як `$KEY`
|
|
14
|
+
(через envsubst). Якщо у `*.ini` є ключ, що відсутній у шаблоні — його треба вилучити з ini
|
|
15
|
+
або додати в шаблон.
|
|
16
|
+
|
|
17
|
+
Перевірки (автоматичні):
|
|
18
|
+
|
|
19
|
+
- Поруч з кожним `default.conf.template` є щонайменше один `*.ini` файл
|
|
20
|
+
- Кожен ключ з `*.ini` (рядки виду `KEY=value`, без коментарів `#`/`;` і порожніх рядків)
|
|
21
|
+
присутній у шаблоні як `$KEY`
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
## Канонічна структура default.conf.template
|
|
2
|
+
|
|
3
|
+
`default.conf.template` — єдиний nginx-конфіг для фронтенду зі статичними файлами.
|
|
4
|
+
Він **не повинен** містити жодних `proxy_pass`, `proxy_redirect`, `proxy_set_header`,
|
|
5
|
+
`fastcgi_pass`, `grpc_pass`, `uwsgi_pass`. Усю проксі-логіку потрібно винести в HTTPRoute (k8s).
|
|
6
|
+
|
|
7
|
+
Канонічний вигляд файлу:
|
|
8
|
+
|
|
9
|
+
```nginx
|
|
10
|
+
server_tokens off;
|
|
11
|
+
port_in_redirect off;
|
|
12
|
+
client_max_body_size 0;
|
|
13
|
+
client_body_buffer_size 512M;
|
|
14
|
+
|
|
15
|
+
server {
|
|
16
|
+
listen 8080;
|
|
17
|
+
server_name _;
|
|
18
|
+
|
|
19
|
+
# disable all log
|
|
20
|
+
access_log off;
|
|
21
|
+
# `error_log off;` — НЕ валідний nginx: "off" трактується як ім'я файлу (/etc/nginx/off)
|
|
22
|
+
# і падає під readOnlyRootFilesystem. /dev/null — writable device.
|
|
23
|
+
error_log /dev/null crit;
|
|
24
|
+
|
|
25
|
+
# This would be the directory where your Vite app's static files are stored at
|
|
26
|
+
root /usr/share/nginx/html;
|
|
27
|
+
|
|
28
|
+
location /healthz {
|
|
29
|
+
add_header Content-Type text/plain;
|
|
30
|
+
access_log off;
|
|
31
|
+
return 200 "healthy";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# Без gz стиснених файлів, 1 year is 31536000 seconds
|
|
35
|
+
location ~ ^$PUBLIC_PATH/(.+\.(?:gif|jpe?g|png|ico|woff2|xlsx))$ {
|
|
36
|
+
alias /usr/share/nginx/html/$1;
|
|
37
|
+
add_header 'Cache-Control' "public,max-age=31536000,immutable";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# С gz стисненими файлами, 1 year is 31536000 seconds
|
|
41
|
+
location ~ ^$PUBLIC_PATH/(.+\.(?:svg|js|css|ttf|map|xml|webmanifest|wasm))$ {
|
|
42
|
+
alias /usr/share/nginx/html/$1;
|
|
43
|
+
add_header 'Cache-Control' "public,max-age=31536000,immutable";
|
|
44
|
+
|
|
45
|
+
# дозволяє віддавати замість звичайного файлу попередньо стиснутий файл з таким же ім'ям та з розширенням ".gz"
|
|
46
|
+
gzip_static on;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
location $PUBLIC_PATH/ {
|
|
50
|
+
index index.html;
|
|
51
|
+
alias /usr/share/nginx/html/;
|
|
52
|
+
|
|
53
|
+
# eliminates the step of copying the data into the buffer and enables direct copying data from one file descriptor to another.
|
|
54
|
+
sendfile on;
|
|
55
|
+
# to prevent one fast connection from entirely occupying the worker process
|
|
56
|
+
sendfile_max_chunk 512k;
|
|
57
|
+
# to send HTTP response headers in one packet right after the chunk of data has been obtained by sendfile().
|
|
58
|
+
tcp_nopush on;
|
|
59
|
+
|
|
60
|
+
# дозволяє віддавати замість звичайного файлу попередньо стиснутий файл з таким же ім'ям та з розширенням ".gz"
|
|
61
|
+
gzip_static on;
|
|
62
|
+
|
|
63
|
+
try_files $uri $uri/ /index.html =404;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Обов'язкові вимоги до структури (перевіряються автоматично):
|
|
69
|
+
|
|
70
|
+
- `server_tokens off` — приховує версію nginx у відповідях
|
|
71
|
+
- `port_in_redirect off` — виключає порт з redirect-заголовків
|
|
72
|
+
- `client_max_body_size 0` — без ліміту тіла запиту
|
|
73
|
+
- `client_body_buffer_size 512M`
|
|
74
|
+
- `listen 8080`
|
|
75
|
+
- `server_name _` — catch-all
|
|
76
|
+
- `access_log off`
|
|
77
|
+
- `error_log /dev/null crit` (НЕ `error_log off;` — це некоректно в nginx)
|
|
78
|
+
- `root /usr/share/nginx/html`
|
|
79
|
+
- `location /healthz` з `return 200` і рядком `healthy`
|
|
80
|
+
- location для статики без gzip (`gif|jpeg|png|ico|woff2|xlsx`) з `Cache-Control: max-age=31536000,immutable`
|
|
81
|
+
- location для статики з gzip (`svg|js|css|ttf|map|xml|webmanifest|wasm`) з `gzip_static on`
|
|
82
|
+
- `gzip_static on` щонайменше двічі (два location зі стисненням)
|
|
83
|
+
- `$PUBLIC_PATH` у location — плейсхолдер підставляється через envsubst
|
|
84
|
+
- `sendfile on`, `sendfile_max_chunk 512k`, `tcp_nopush on`
|
|
85
|
+
- `try_files $uri $uri/ /index.html =404`
|
|
86
|
+
- **Відсутність** будь-якого `proxy_pass` / `fastcgi_pass` / `grpc_pass` / `uwsgi_pass`
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
## VS Code — розширення та налаштування nginx
|
|
2
|
+
|
|
3
|
+
Коли у проєкті є `default.conf.template`, очікуються відповідні VS Code конфігурації
|
|
4
|
+
для підтримки nginx-синтаксису.
|
|
5
|
+
|
|
6
|
+
### .vscode/extensions.json
|
|
7
|
+
|
|
8
|
+
`recommendations` має містити розширення `ahmadalli.vscode-nginx-conf`:
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{
|
|
12
|
+
"recommendations": [
|
|
13
|
+
"ahmadalli.vscode-nginx-conf"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### .vscode/settings.json
|
|
19
|
+
|
|
20
|
+
Має бути увімкнений `formatOnSave` і встановлений форматер nginx:
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"editor.formatOnSave": true,
|
|
25
|
+
"[nginx]": {
|
|
26
|
+
"editor.defaultFormatter": "ahmadalli.vscode-nginx-conf"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Перевірки виконуються через Rego-пакети (conftest):
|
|
32
|
+
|
|
33
|
+
- `nginx_default_tpl.vscode_extensions` — перевіряє наявність `ahmadalli.vscode-nginx-conf` у `recommendations`
|
|
34
|
+
- `nginx_default_tpl.vscode_settings` — перевіряє `editor.formatOnSave: true` і `[nginx].editor.defaultFormatter: "ahmadalli.vscode-nginx-conf"`
|
|
35
|
+
|
|
36
|
+
Ці перевірки активуються **лише** якщо в проєкті знайдено `default.conf.template`
|
|
37
|
+
(умовне правило, не auto-discoverable без JS-gate).
|
|
@@ -5,120 +5,14 @@ globs: "**/default.{conf.template,tpl.conf}"
|
|
|
5
5
|
alwaysApply: false
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
default.conf.template
|
|
8
|
+
Правило забезпечує відповідність `default.conf.template` канонічній структурі nginx для фронтенду зі статичними файлами, а також перевіряє пов'язані артефакти: HTTPRoute (k8s), Dockerfile, ini-файли середовищ і VS Code конфігурацію.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
server_tokens off;
|
|
12
|
-
port_in_redirect off;
|
|
13
|
-
client_max_body_size 0;
|
|
14
|
-
client_body_buffer_size 512M;
|
|
10
|
+
[nginx-default-tpl-template-structure](./js/template-structure.mdc)
|
|
15
11
|
|
|
16
|
-
|
|
17
|
-
listen 8080;
|
|
18
|
-
server_name _;
|
|
12
|
+
[nginx-default-tpl-http-route](./js/http-route.mdc)
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
access_log off;
|
|
22
|
-
# `error_log off;` — НЕ валідний nginx: "off" трактується як ім'я файлу (/etc/nginx/off)
|
|
23
|
-
# і падає під readOnlyRootFilesystem. /dev/null — writable device.
|
|
24
|
-
error_log /dev/null crit;
|
|
14
|
+
[nginx-default-tpl-dockerfile](./js/dockerfile.mdc)
|
|
25
15
|
|
|
26
|
-
|
|
27
|
-
root /usr/share/nginx/html;
|
|
16
|
+
[nginx-default-tpl-ini-keys](./js/ini-keys.mdc)
|
|
28
17
|
|
|
29
|
-
|
|
30
|
-
add_header Content-Type text/plain;
|
|
31
|
-
access_log off;
|
|
32
|
-
return 200 "healthy";
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
# Без gz стиснених файлів, 1 year is 31536000 seconds
|
|
36
|
-
location ~ ^$PUBLIC_PATH/(.+\.(?:gif|jpe?g|png|ico|woff2|xlsx))$ {
|
|
37
|
-
alias /usr/share/nginx/html/$1;
|
|
38
|
-
add_header 'Cache-Control' "public,max-age=31536000,immutable";
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
# С gz стисненими файлами, 1 year is 31536000 seconds
|
|
42
|
-
location ~ ^$PUBLIC_PATH/(.+\.(?:svg|js|css|ttf|map|xml|webmanifest|wasm))$ {
|
|
43
|
-
alias /usr/share/nginx/html/$1;
|
|
44
|
-
add_header 'Cache-Control' "public,max-age=31536000,immutable";
|
|
45
|
-
|
|
46
|
-
# дозволяє віддавати замість звичайного файлу попередньо стиснутий файл з таким же ім'ям та з розширенням ".gz"
|
|
47
|
-
gzip_static on;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
location $PUBLIC_PATH/ {
|
|
51
|
-
index index.html;
|
|
52
|
-
alias /usr/share/nginx/html/;
|
|
53
|
-
|
|
54
|
-
# eliminates the step of copying the data into the buffer and enables direct copying data from one file descriptor to another.
|
|
55
|
-
sendfile on;
|
|
56
|
-
# to prevent one fast connection from entirely occupying the worker process
|
|
57
|
-
sendfile_max_chunk 512k;
|
|
58
|
-
# to send HTTP response headers in one packet right after the chunk of data has been obtained by sendfile().
|
|
59
|
-
tcp_nopush on;
|
|
60
|
-
|
|
61
|
-
# дозволяє віддавати замість звичайного файлу попередньо стиснутий файл з таким же ім'ям та з розширенням ".gz"
|
|
62
|
-
gzip_static on;
|
|
63
|
-
|
|
64
|
-
try_files $uri $uri/ /index.html =404;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
Тобто в ньому не потрібно щоб було жодного proxy_pass секціі і інших опцій для proxy.
|
|
70
|
-
|
|
71
|
-
Якщо в файлі вже були proxy_pass секції, то їх логіку потрібно перенести до HTTPRoute в k8s.
|
|
72
|
-
|
|
73
|
-
В HTTPRoute повинна бути секція Exact редиректу на версію з /
|
|
74
|
-
|
|
75
|
-
```yaml
|
|
76
|
-
spec:
|
|
77
|
-
rules:
|
|
78
|
-
- matches:
|
|
79
|
-
- path:
|
|
80
|
-
type: Exact
|
|
81
|
-
value: /$PUBLIC_PATH
|
|
82
|
-
filters:
|
|
83
|
-
- type: RequestRedirect
|
|
84
|
-
requestRedirect:
|
|
85
|
-
scheme: https
|
|
86
|
-
path:
|
|
87
|
-
type: ReplaceFullPath
|
|
88
|
-
replaceFullPath: /$PUBLIC_PATH/
|
|
89
|
-
statusCode: 301
|
|
90
|
-
- matches:
|
|
91
|
-
- path:
|
|
92
|
-
type: PathPrefix
|
|
93
|
-
value: /$PUBLIC_PATH/
|
|
94
|
-
backendRefs:
|
|
95
|
-
- name: $SERVICE_NAME
|
|
96
|
-
port: 8080
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
де $PUBLIC_PATH підставляється з ini файлу з dev середовища, а якщо для інших середовищ відрізняється то підставляється в kustomization.yaml відповідні значення з ini середовища.
|
|
100
|
-
|
|
101
|
-
В $SERVICE_NAME повинно бути вказано ім'я сервісу, яке буде використовуватися в k8s.
|
|
102
|
-
|
|
103
|
-
В Dockerfile потрібно додати команду для стиснення файлів, які потім використовуватимуться з `gzip_static on`:
|
|
104
|
-
|
|
105
|
-
```dockerfile
|
|
106
|
-
RUN find /usr/share/nginx/html -type f \( \
|
|
107
|
-
-name '*.js' -o -name '*.css' -o -name '*.map' -o -name '*.xml' -o \
|
|
108
|
-
-name '*.webmanifest' -o -name '*.html' -o -name '*.wasm' -o -name '*.ttf' \
|
|
109
|
-
\) -exec gzip -k {} +
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Поруч з файлом default.conf.template повинні бути конфігураційні файли *.ini для різних середовищ. В Dockerfile повинна бути команда, для заміни плейсхолдерів в цих файлах на значення з середовища:
|
|
113
|
-
|
|
114
|
-
```dockerfile
|
|
115
|
-
# 1) Витягнути імена змінних з ini (ігноруємо коментарі/порожні)
|
|
116
|
-
# 2) Зробити список для envsubst: $NAMESPACE $NAMESPACE2 ...
|
|
117
|
-
# 3) Підвантажити значення з ini і підставити лише їх
|
|
118
|
-
RUN NAMES=$(sed -nE '/^\s*[#;]/d; /^\s*$/d; s/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=.*/\1/p' /tpl/values-$BRANCH.ini) && \
|
|
119
|
-
VARS=$(printf '%s\n' $NAMES | awk '{printf "$%s ", $0}') && \
|
|
120
|
-
export $(grep -v '^#' /tpl/values-$BRANCH.ini | xargs) && \
|
|
121
|
-
envsubst "$VARS" < /tpl/default.conf.template > /app/default.conf
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Якщо у конфігураційних файлах *.ini є змінні які відсутні в default.conf.template, то їх потрібно вилучити.
|
|
18
|
+
[nginx-default-tpl-vscode](./js/vscode.mdc)
|
|
@@ -6,9 +6,9 @@ resource: npm/rules/npm-module/js/
|
|
|
6
6
|
|
|
7
7
|
# npm/rules/npm-module/js
|
|
8
8
|
|
|
9
|
-
| Файл
|
|
10
|
-
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------- | --------- |
|
|
11
11
|
| [header_doc_pointer.mjs](header_doc_pointer.md) | JS Module |
|
|
12
|
-
| [package_structure.mjs](package_structure.md)
|
|
13
|
-
| [rule_meta.mjs](rule_meta.md)
|
|
14
|
-
| [skill_meta.mjs](skill_meta.md)
|
|
12
|
+
| [package_structure.mjs](package_structure.md) | JS Module |
|
|
13
|
+
| [rule_meta.mjs](rule_meta.md) | JS Module |
|
|
14
|
+
| [skill_meta.mjs](skill_meta.md) | JS Module |
|
|
@@ -17,12 +17,12 @@ docgen:
|
|
|
17
17
|
1. Перевіряє наявність каталогу `npm/rules` у корені репозиторію. Якщо каталог відсутній, завершує роботу, повідомляючи про відсутність правил для валідації.
|
|
18
18
|
2. Ітерує по всім підкаталогах у `npm/rules`, ігноруючи приховані каталоги.
|
|
19
19
|
3. Для кожного каталогу виконує перевірку правила:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
а. Перевіряє відсутність файлу `auto.md`. Якщо знайдено, повідомляє про залишковий файл.
|
|
21
|
+
б. Перевіряє наявність файлу `main.mdc`. Якщо відсутній, повідомляє про відсутність обов'язкового файлу (scripts.mdc).
|
|
22
|
+
в. Зчитує вміст `main.json` каталогу правила. Якщо файл відсутній або невалідний, повідомляє про це та пропускає подальшу валідацію цього правила.
|
|
23
|
+
г. Перевіряє поле `auto` у `main.json`. Якщо поле присутнє, валідує його структуру та перевіряє, чи всі використані предикати визначені.
|
|
24
|
+
ґ. Перевіряє поле `lint` у `main.json`. Якщо поле присутнє, валідує його структуру та перевіряє, чи експортує файл `main.mjs` відповідну функцію `lint`.
|
|
25
|
+
і. Якщо всі перевірки для правила пройдені успішно, повідомляє про валідність `main.json`.
|
|
26
26
|
4. Після обробки всіх правил повертає код виходу, що відображає загальний статус валідації.
|
|
27
27
|
|
|
28
28
|
## Публічний API
|
|
@@ -17,14 +17,14 @@ docgen:
|
|
|
17
17
|
1. Перевіряє наявність каталогу `npm/skills` у поточному робочому каталозі. Якщо каталог відсутній, операція завершується успішно.
|
|
18
18
|
2. Ітерує по всіх підкаталогах у `npm/skills`.
|
|
19
19
|
3. Для кожного підкаталогу виконується перевірка метаданих скіла:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
а. Перевіряється наявність файлу `auto.md` у каталозі скіла. Якщо він присутній, це вважається порушенням.
|
|
21
|
+
б. Зчитується вміст `main.json` скіла. Якщо файл відсутній або невалідний, перевірка для цього скіла припиняється.
|
|
22
|
+
в. Виконується перевірка полів `main.json` скіла:
|
|
23
|
+
i. `worktree` має бути булевим значенням.
|
|
24
|
+
ii. Якщо поле `auto` визначене, його вміст має бути розпізнаним як "завжди" або непорожній масив правил.
|
|
25
|
+
iii. `requireRoot` має бути булевим значенням, якщо визначений.
|
|
26
|
+
iv. Якщо `worktree` встановлено як `true`, а `requireRoot` як `false`, це вважається порушенням.
|
|
27
|
+
г. Якщо всі поля `main.json` валідні, це вважається успішним результатом для скіла.
|
|
28
28
|
4. Після перевірки всіх скілів повертається код виходу, що відображає загальний статус (0 — успіх, 1 — порушення).
|
|
29
29
|
|
|
30
30
|
## Публічний API
|
|
@@ -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,62 @@
|
|
|
1
|
+
## Структура монорепо та компактний пакет
|
|
2
|
+
|
|
3
|
+
Bun monorepo: workspace **`npm/`**, кореневий **`package.json`**, **`.github/workflows/`**; опційно **`demo/`**.
|
|
4
|
+
|
|
5
|
+
Мета — **максимально компактний** опублікований пакет: у npm потрапляє тільки те, що потрібно під час `require`/`import` користувачем.
|
|
6
|
+
|
|
7
|
+
- **`"files"` обовʼязковий** у `npm/package.json` як **whitelist** того, що публікується (без `"files"` npm пакує майже все — це антипатерн для цього правила).
|
|
8
|
+
- **Тести й фікстури не публікуються — через негативні 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`).
|
|
9
|
+
- **Лише runtime-залежності у `npm/package.json`.** `devDependencies` тримай у **кореневому** `package.json` монорепо — тоді `npm install @nitra/<pkg>` не тягне інструментарій, потрібний лише для розробки самого пакета.
|
|
10
|
+
|
|
11
|
+
Перевірки JS (`package_structure.mjs`):
|
|
12
|
+
- Наявність `package.json`, `npm/`, `npm/package.json`.
|
|
13
|
+
- Walk шляхів з `"files"` з застосуванням негативних patterns і скан залишку на тест-патерни (walking + AST). Якщо після застосування негативних patterns у tarball лишається test-style файл — `check` падає з вказівкою, який саме негативний glob треба додати у `"files"`.
|
|
14
|
+
|
|
15
|
+
## TypeScript declaration (`npm/types`)
|
|
16
|
+
|
|
17
|
+
Файл **`npm/package.json`** має містити **`"types"`** (шлях до головного `.d.ts` або `.d.mts` під **`./types/…`**) і запис **`"types"`** у **`files`**, щоб npm публікував декларації.
|
|
18
|
+
|
|
19
|
+
Генерація — через **`tsc`** і **`bunx -p typescript`** (окремий пакет **`typescript`** у `devDependencies` не потрібен).
|
|
20
|
+
|
|
21
|
+
### Варіант A: є вихідний **`.js`** під **`npm/src/`**
|
|
22
|
+
|
|
23
|
+
Якщо під **`npm/src`** (рекурсивно) є хоча б один файл **`.js`**:
|
|
24
|
+
|
|
25
|
+
- **`"types": "./types/index.d.ts"`**;
|
|
26
|
+
- у **hk** на **`pre-commit`** з каталогу **`npm/`** викликай:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bunx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types --skipLibCheck
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Якщо glob не розгортається — **`bash -O globstar`** або **`include`** у **`tsconfig`** з тими самими **`compilerOptions`**.
|
|
33
|
+
|
|
34
|
+
### Варіант B: немає **`npm/src/**/*.js`** (наприклад лише **`bin/`**, **`scripts/**/*.mjs`**)
|
|
35
|
+
|
|
36
|
+
Не створюй штучний **`src/index.js`**. Замість цього:
|
|
37
|
+
|
|
38
|
+
1. Додай **`npm/tsconfig.emit-types.json`** з **`include`** на реальні шляхи (`.js` / `.mjs`), **`compilerOptions`**: **`allowJs`**, **`declaration`**, **`emitDeclarationOnly`**, **`outDir`: `"types"`**, **`skipLibCheck`**: **`true`** (за потреби **`rootDir`**, **`module`**, **`moduleResolution`**).
|
|
39
|
+
2. Після першого **`tsc`** подивись, який **`.d.ts`** / **`.d.mts`** відповідає публічному API, і вкажи його в **`types`** (наприклад **`./types/bin/cli.d.ts`**).
|
|
40
|
+
3. У **hk** на **`pre-commit`** з **`npm/`** викликай **`tsc -p tsconfig.emit-types.json`**. Якщо через імпорти **TypeScript** все одно згенерує зайві **`.d.mts`** у **`types/`**, після **`tsc`** обрізай дерево до потрібного entrypoint (наприклад залиш лише **`types/bin/n-cursor.d.ts`** через **`find`**), щоб у пакеті не збирались декларації внутрішніх модулів.
|
|
41
|
+
|
|
42
|
+
Файл **`tsconfig.emit-types.json`** тримай у репозиторії для **hk** / локальної генерації; у **`files`** його не додавай, якщо не хочеш публікувати його на **npm**.
|
|
43
|
+
|
|
44
|
+
## Git hooks: hk + pre-commit
|
|
45
|
+
|
|
46
|
+
У корені репозиторію — **`hk.pkl`** (або **`.config/hk.pkl`**) з **`["pre-commit"]`** і командою з відповідного варіанту (A або B) вище.
|
|
47
|
+
|
|
48
|
+
Після додавання **`hk.pkl`**: **`hk install`**.
|
|
49
|
+
|
|
50
|
+
## npm publish
|
|
51
|
+
|
|
52
|
+
**`npm-publish.yml`:** push у **`main`**, **`on.push.paths`** з **`npm/**`**, **`JS-DevTools/npm-publish@v4.1.5`**, **`with.package: npm/package.json`**, **`permissions.id-token: write`** (OIDC на npm).
|
|
53
|
+
|
|
54
|
+
Workflow робить **release + publish** одним job (`release-publish`): крок **`Release (bump + CHANGELOG + tag)`** (`bunx n-cursor release` — агрегує change-файли, bump `version`, генерує секцію `CHANGELOG.md`, ставить git-тег) виконується **перед** публікацією. Тому потрібні **`permissions.contents: write`** і **`persist-credentials: true`** з **`fetch-depth: 0`** на `checkout` (release пушить commit-back версії та тег), а також локальний composite **`./.github/actions/setup-bun-deps`** і крок `Configure git identity`. Це узгоджено з **`n-changelog`**: `version`/`CHANGELOG.md` змінює лише `n-cursor release` у CI на `main`. Програмна перевірка (`npm_module.npm_publish_yml`) звіряє **весь канонічний сніпет** напряму (`target.json:"check":"template"`, generic deep-subset): усі поля й кроки сніпета (`on.push.paths`/`branches`, `concurrency`, `permissions.contents/id-token`, `checkout` з `persist-credentials/fetch-depth`, `setup-bun-deps`, `Configure git identity`, `Release`, publish-крок) **обовʼязкові**; зайві кроки/поля дозволені (subset-of), масиви матчаться за наявністю (порядок кроків не важить). Сніпет — єдине джерело істини: його редагування одразу змінює enforce, без правок rego й без міграторів.
|
|
55
|
+
|
|
56
|
+
- Канон: [npm-publish.yml.snippet.yml](./policy/npm_publish_yml/template/npm-publish.yml.snippet.yml)
|
|
57
|
+
|
|
58
|
+
## Канонічні конфіги
|
|
59
|
+
|
|
60
|
+
- Кореневий `package.json` (workspaces): [package.json.snippet.json](./policy/root_package_json/template/package.json.snippet.json)
|
|
61
|
+
- `npm/package.json` (whitelist `files` обовʼязково має містити `types`): [package.json.snippet.json](./policy/npm_package_json/template/package.json.snippet.json)
|
|
62
|
+
- `npm/tsconfig.emit-types.json` (canonical `compilerOptions` для emit-types): [tsconfig.emit-types.json.snippet.json](./policy/emit_types_config/template/tsconfig.emit-types.json.snippet.json)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Валідація `main.json` правил
|
|
2
|
+
|
|
3
|
+
Кожне правило у `npm/rules/<id>/` повинно мати коректний `main.json` (метадані правила).
|
|
4
|
+
|
|
5
|
+
Перевірки (`rule_meta.mjs`):
|
|
6
|
+
|
|
7
|
+
- **`main.mdc` обовʼязковий** у кожному `npm/rules/<id>/` — без нього `check` падає.
|
|
8
|
+
- **`auto.md` є пережитком** — якщо такий файл залишився, `check` вимагає його видалити (метадані тепер у `main.json`).
|
|
9
|
+
- **`main.json` має бути валідним JSON** із коректними полями:
|
|
10
|
+
- **`auto`** (опційне): `"завжди"` / масив glob-рядків / `{ glob }` / `{ predicate }`. Якщо `predicate` вказано — він має бути зареєстрований у `RULE_PREDICATES`.
|
|
11
|
+
- **`lint`** (опційне): `"per-file"` або `"full"`. Якщо вказано — `main.mjs` повинен експортувати функцію `lint` (або `export { lint } from …`).
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Валідація `main.json` скілів
|
|
2
|
+
|
|
3
|
+
Кожен скіл у `npm/skills/<id>/` повинен мати коректний `main.json` (метадані скіла).
|
|
4
|
+
|
|
5
|
+
Перевірки (`skill_meta.mjs`):
|
|
6
|
+
|
|
7
|
+
- **`auto.md` є пережитком** — якщо такий файл залишився, `check` вимагає його видалити (метадані тепер у `main.json`).
|
|
8
|
+
- **`main.json` має бути валідним JSON** із коректними полями:
|
|
9
|
+
- **`worktree`** (обовʼязкове): `boolean`. Якщо `true` — скіл запускається виключно в окремому git-worktree.
|
|
10
|
+
- **`auto`** (опційне): `"завжди"` або непорожній масив ідентифікаторів правил-тригерів.
|
|
11
|
+
- **`requireRoot`** (опційне): `boolean`. Значення `false` несумісне з `worktree: true` — таку комбінацію `check` відхиляє.
|
|
@@ -7,53 +7,13 @@ version: '1.14'
|
|
|
7
7
|
|
|
8
8
|
Bun monorepo: workspace **`npm/`**, кореневий **`package.json`**, **`.github/workflows/`**; опційно **`demo/`**.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
[npm-module-package_structure](./js/package_structure.mdc)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
[npm-module-rule_meta](./js/rule_meta.mdc)
|
|
13
13
|
|
|
14
|
-
-
|
|
15
|
-
- **Тести й фікстури не публікуються — через негативні 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`).
|
|
16
|
-
- **Лише runtime-залежності у `npm/package.json`.** `devDependencies` тримай у **кореневому** `package.json` монорепо — тоді `npm install @nitra/<pkg>` не тягне інструментарій, потрібний лише для розробки самого пакета.
|
|
14
|
+
[npm-module-skill_meta](./js/skill_meta.mdc)
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- Пер-документні правила для `npm/package.json` (whitelist `files`, заборона `devDependencies`, форма `types`) — у rego-пакеті `npm_module.npm_package_json` (`npm/policy/npm_module/npm_package_json/`).
|
|
21
|
-
- Walk шляхів з `"files"` з застосуванням негативних patterns і скан залишку на тест-патерни (walking + AST JS/TS) — у `check.mjs::checkNoTestsInPublishedFiles` (FS / AST не лягають у rego). Якщо після застосування негативних patterns у tarball лишається test-style файл — `check` падає з вказівкою, який саме негативний glob треба додати у `"files"`.
|
|
22
|
-
|
|
23
|
-
## TypeScript declaration (`npm/types`)
|
|
24
|
-
|
|
25
|
-
Файл **`npm/package.json`** має містити **`"types"`** (шлях до головного `.d.ts` або `.d.mts` під **`./types/…`**) і запис **`"types"`** у **`files`**, щоб npm публікував декларації.
|
|
26
|
-
|
|
27
|
-
Генерація — через **`tsc`** і **`bunx -p typescript`** (окремий пакет **`typescript`** у `devDependencies` не потрібен).
|
|
28
|
-
|
|
29
|
-
### Варіант A: є вихідний **`.js`** під **`npm/src/`**
|
|
30
|
-
|
|
31
|
-
Якщо під **`npm/src`** (рекурсивно) є хоча б один файл **`.js`**:
|
|
32
|
-
|
|
33
|
-
- **`"types": "./types/index.d.ts"`**;
|
|
34
|
-
- у **hk** на **`pre-commit`** з каталогу **`npm/`** викликай:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
bunx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types --skipLibCheck
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Якщо glob не розгортається — **`bash -O globstar`** або **`include`** у **`tsconfig`** з тими самими **`compilerOptions`**.
|
|
41
|
-
|
|
42
|
-
### Варіант B: немає **`npm/src/**/*.js`** (наприклад лише **`bin/`**, **`scripts/**/*.mjs`**)
|
|
43
|
-
|
|
44
|
-
Не створюй штучний **`src/index.js`**. Замість цього:
|
|
45
|
-
|
|
46
|
-
1. Додай **`npm/tsconfig.emit-types.json`** з **`include`** на реальні шляхи (`.js` / `.mjs`), **`compilerOptions`**: **`allowJs`**, **`declaration`**, **`emitDeclarationOnly`**, **`outDir`: `"types"`**, **`skipLibCheck`**: **`true`** (за потреби **`rootDir`**, **`module`**, **`moduleResolution`**).
|
|
47
|
-
2. Після першого **`tsc`** подивись, який **`.d.ts`** / **`.d.mts`** відповідає публічному API, і вкажи його в **`types`** (наприклад **`./types/bin/cli.d.ts`**).
|
|
48
|
-
3. У **hk** на **`pre-commit`** з **`npm/`** викликай **`tsc -p tsconfig.emit-types.json`**. Якщо через імпорти **TypeScript** все одно згенерує зайві **`.d.mts`** у **`types/`**, після **`tsc`** обрізай дерево до потрібного entrypoint (наприклад залиш лише **`types/bin/n-cursor.d.ts`** через **`find`**), щоб у пакеті не збирались декларації внутрішніх модулів.
|
|
49
|
-
|
|
50
|
-
Файл **`tsconfig.emit-types.json`** тримай у репозиторії для **hk** / локальної генерації; у **`files`** його не додавай, якщо не хочеш публікувати його на **npm**.
|
|
51
|
-
|
|
52
|
-
## Git hooks: hk + pre-commit
|
|
53
|
-
|
|
54
|
-
У корені репозиторію — **`hk.pkl`** (або **`.config/hk.pkl`**) з **`["pre-commit"]`** і командою з відповідного варіанту (A або B) вище.
|
|
55
|
-
|
|
56
|
-
Після додавання **`hk.pkl`**: **`hk install`**.
|
|
16
|
+
[npm-module-header_doc_pointer](./js/header_doc_pointer.mdc)
|
|
57
17
|
|
|
58
18
|
## Версія та CHANGELOG
|
|
59
19
|
|
|
@@ -61,16 +21,11 @@ bunx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly
|
|
|
61
21
|
|
|
62
22
|
Повна модель (база порівняння, інверсія шляхів, формат CHANGELOG, post-release-інваріант «верхня секція CHANGELOG == `version`») — у **`n-changelog.mdc`** (джерело істини). Це правило їй підпорядковане й власних інструкцій bump/CHANGELOG не дублює.
|
|
63
23
|
|
|
64
|
-
##
|
|
65
|
-
|
|
66
|
-
**`npm-publish.yml`:** push у **`main`**, **`on.push.paths`** з **`npm/**`**, **`JS-DevTools/npm-publish@v4.1.5`**, **`with.package: npm/package.json`**, **`permissions.id-token: write`** (OIDC на npm).
|
|
67
|
-
|
|
68
|
-
Workflow робить **release + publish** одним job (`release-publish`): крок **`Release (bump + CHANGELOG + tag)`** (`bunx n-cursor release` — агрегує change-файли, bump `version`, генерує секцію `CHANGELOG.md`, ставить git-тег) виконується **перед** публікацією. Тому потрібні **`permissions.contents: write`** і **`persist-credentials: true`** з **`fetch-depth: 0`** на `checkout` (release пушить commit-back версії та тег), а також локальний composite **`./.github/actions/setup-bun-deps`** і крок `Configure git identity`. Це узгоджено з **`n-changelog`**: `version`/`CHANGELOG.md` змінює лише `n-cursor release` у CI на `main`. Програмна перевірка (`npm_module.npm_publish_yml`) звіряє **весь канонічний сніпет** напряму (`target.json:"check":"template"`, generic deep-subset): усі поля й кроки сніпета (`on.push.paths`/`branches`, `concurrency`, `permissions.contents/id-token`, `checkout` з `persist-credentials/fetch-depth`, `setup-bun-deps`, `Configure git identity`, `Release`, publish-крок) **обовʼязкові**; зайві кроки/поля дозволені (subset-of), масиви матчаться за наявністю (порядок кроків не важить). Сніпет — єдине джерело істини: його редагування одразу змінює enforce, без правок rego й без міграторів.
|
|
69
|
-
|
|
70
|
-
- Канон: [npm-publish.yml.snippet.yml](./policy/npm_publish_yml/template/npm-publish.yml.snippet.yml)
|
|
24
|
+
## Швидкий gate через conftest
|
|
71
25
|
|
|
72
|
-
|
|
26
|
+
Rego-пакети (запускаються через `npx @nitra/cursor fix`):
|
|
73
27
|
|
|
74
|
-
-
|
|
75
|
-
- `
|
|
76
|
-
- `npm/tsconfig.emit-types.json
|
|
28
|
+
- `npm_module.npm_package_json` — валідує `npm/package.json`: поле `types`, наявність і непорожність `files`, subset-of з template (зокрема `"types"` у `files`), заборона `devDependencies`.
|
|
29
|
+
- `npm_module.root_package_json` — валідує кореневий `package.json`: поле `workspaces` має містити `"npm"`.
|
|
30
|
+
- `npm_module.emit_types_config` — валідує `npm/tsconfig.emit-types.json`: `compilerOptions` відповідає канонічному сніпету (allowJs, declaration, emitDeclarationOnly, outDir, skipLibCheck).
|
|
31
|
+
- `npm_module.npm_publish_yml` — template-driven перевірка `.github/workflows/npm-publish.yml` (deep-subset: усі обовʼязкові поля й кроки з канонічного сніпету).
|