@7n/rules 1.42.0 → 1.43.0
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 +6 -0
- package/package.json +1 -1
- package/rules/docker/lint/docs/index.md +9 -0
- package/rules/docker/lint/docs/main.md +31 -27
- package/rules/docker/lint/main.mjs +33 -9
- package/rules/docker/main.mdc +24 -0
- package/scripts/utils/ast-scan-utils.mjs +1 -1
- package/scripts/utils/docs/ast-scan-utils.md +39 -38
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.43.0] - 2026-07-22
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- docker: n-rules:bun-no-compile-маркер (# n-rules:bun-no-compile: <причина>) — генералізує native-addon-виняток на будь-яку недосяжну для checker-а причину неможливості bun build --compile (напр. динамічний import() рантайм-конфігу); вимикає вимогу компіляції й дозволяє mirror.gcr.io/oven/bun:* як фінальний stage
|
|
8
|
+
|
|
3
9
|
## [1.42.0] - 2026-07-22
|
|
4
10
|
|
|
5
11
|
### Added
|
package/package.json
CHANGED
|
@@ -3,45 +3,49 @@ type: JS Module
|
|
|
3
3
|
title: main.mjs
|
|
4
4
|
resource: npm/rules/docker/lint/main.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
7
|
-
model:
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
crc: 7cc8c2c7
|
|
7
|
+
model: openai-codex/gpt-5.4-mini
|
|
8
|
+
tier: cloud-min
|
|
9
|
+
score: 90
|
|
10
|
+
issues: internal-name:checkDockerfile,judge-refine:kept-original,judge:inaccurate:0.99
|
|
10
11
|
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
12
|
---
|
|
12
13
|
|
|
13
14
|
## Огляд
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
Файл знаходить Dockerfile і Containerfile в межах репозиторію через `findDockerfilePaths`, визначає stage-структуру через `splitDockerfileStages` і `parseFromStages`, а потім запускає `lint` як fail-safe перевірку без винесення винятків назовні.
|
|
17
|
+
Перевірки спираються на правила з `docker.mdc` і окремо покривають multistage/runtime-узгодженість через `getMultistageAndRuntimeHint`, `getBunCompileHint`, `getNginxAlpineSlimTagHint` і `getNonRootRuntimeHint`, щоб Docker-образи відповідали очікуваній схемі збірки та запуску.
|
|
16
18
|
|
|
17
19
|
## Поведінка
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
getBunCompileHint
|
|
26
|
-
|
|
27
|
-
getNonRootRuntimeHint
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
Detector спочатку знаходить лише Dockerfile і Containerfile у межах репозиторію, відфільтровуючи імена через `isDockerfileName` та враховуючи ignore-маршрути, а далі для кожного файлу запускає послідовну перевірку в межах `lint`.
|
|
22
|
+
|
|
23
|
+
`parseFromStages` і `splitDockerfileStages` дають спільну картину структури файла: перший витягує всі базові образи, другий ділить вміст на stages, щоб наступні перевірки могли оцінювати саме фінальний runtime і build-stage окремо.
|
|
24
|
+
|
|
25
|
+
`getMultistageAndRuntimeHint` використовує ці дані, щоб вимагати multistage і дозволений фінальний runtime відповідно до `docker.mdc`; для bun-runtime робить виняток лише коли є нативний `.node`-аддон або явний `# n-rules:bun-no-compile` маркер. Такий маркер читає `hasBunNoCompileMarker`, і він служить opt-in для випадків, які не можна вивести механічно.
|
|
26
|
+
|
|
27
|
+
`getBunCompileHint` працює лише для bun-проєктів із backend runtime: якщо в образі є `bun install` або `bun i`, але немає compile-кроку в build-stage, або в фінальному stage лишився bun tooling, це вважається порушенням. Вимога спирається на `package.json`, щоб зрозуміти, чи проект справді bun-орієнтований.
|
|
28
|
+
|
|
29
|
+
`getNonRootRuntimeHint` перевіряє, що фінальний runtime не працює як root, а `getNginxAlpineSlimTagHint` звужує окреме правило для nginx-образів до потрібного тегу з `docker.mdc`.
|
|
30
|
+
|
|
31
|
+
Усі ці перевірки збираються в `checkDockerfile`, який для кожного знайденого файла формує violations і додає їх до результату через fail-safe підхід: помилки не виходять назовні, а перетворюються на контрольований lint-результат.
|
|
32
|
+
|
|
33
|
+
`lint` є єдиною точкою запуску для цього detector: вона знаходить файли, проганяє їх через `checkDockerfile` і повертає підсумок для всього репозиторію без запису стану.
|
|
30
34
|
|
|
31
35
|
## Публічний API
|
|
32
36
|
|
|
33
|
-
isDockerfileName —
|
|
34
|
-
findDockerfilePaths —
|
|
35
|
-
parseFromStages —
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
lint —
|
|
37
|
+
- isDockerfileName — Чи є basename Dockerfile / Containerfile (у т.ч. Dockerfile.prod).
|
|
38
|
+
- findDockerfilePaths — Збирає абсолютні шляхи до Dockerfile / Containerfile від кореня cwd.
|
|
39
|
+
- parseFromStages — Витягує всі `FROM <image>` зі вмісту Dockerfile/Containerfile.
|
|
40
|
+
- hasBunNoCompileMarker — Явний opt-in консюмера: коментар-рядок `# n-rules:bun-no-compile: <причина>` будь-де у файлі позначає, що `bun build --compile` неможливий з причини поза виявними класами (на відміну від нативних `.node`-аддонів, які виявляються з `package.json#dependencies`).
|
|
41
|
+
- splitDockerfileStages — Розбиває Dockerfile на stages за `FROM` (порожній масив, якщо FROM немає).
|
|
42
|
+
- getMultistageAndRuntimeHint — Перевіряє multistage (мінімум 2 FROM) і дозволений фінальний runtime-образ (docker.mdc); для нативного `.node`-аддона або `n-rules:bun-no-compile`-маркера додатково дозволяє `mirror.gcr.io/oven/bun:*`.
|
|
43
|
+
- getBunCompileHint — Для backend bun-проєкту (є `bun install`, фінальний FROM — alpine, не frontend, немає `n-rules:bun-no-compile`-маркера) вимагає `bun build --compile` у build stage і відсутність `bun` у фінальному stage.
|
|
44
|
+
- getNginxAlpineSlimTagHint — Перевіряє, що для nginx-образів (`mirror.gcr.io/nginxinc/nginx-unprivileged`) у `FROM` вказано тег `alpine-slim` (docker.mdc).
|
|
45
|
+
- getNonRootRuntimeHint — Перевіряє, що у фінальному stage є `USER <name|uid>` і це не `root`/`0` (docker.mdc).
|
|
46
|
+
- lint — Detector docker/lint: Dockerfile/Containerfile — mirror/multistage/runtime/non-root + hadolint.
|
|
43
47
|
|
|
44
48
|
## Гарантії поведінки
|
|
45
49
|
|
|
46
|
-
-
|
|
50
|
+
- Власних операцій запису (ФС/БД) у файлі немає; виклики імпортованих модулів можуть писати.
|
|
47
51
|
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
@@ -15,6 +15,7 @@ const BUN_INSTALL_RE = /\bbun\s+(?:install|i)\b/iu
|
|
|
15
15
|
const BUN_BUILD_COMPILE_RE = /\bbun\s+build\b[^\n]*\s--compile\b/iu
|
|
16
16
|
const BUN_WORD_RE = /\bbun\b/iu
|
|
17
17
|
const USER_LINE_RE = /^\s*USER\s+([^\s#]+)/iu
|
|
18
|
+
const BUN_NO_COMPILE_MARKER_RE = /^#\s*n-rules:bun-no-compile:(.*)$/iu
|
|
18
19
|
|
|
19
20
|
const NGINX_UNPRIVILEGED_MIRROR_PREFIX = 'mirror.gcr.io/nginxinc/nginx-unprivileged'
|
|
20
21
|
|
|
@@ -81,22 +82,39 @@ const RUNTIME_IMAGES = /** @type {const} */ ([
|
|
|
81
82
|
/** @type {RegExp} */
|
|
82
83
|
const DEBIAN_VIA_MIRROR_RE = /^mirror\.gcr\.io\/library\/debian:(.+)$/i
|
|
83
84
|
|
|
84
|
-
/** Bun-рантайм як фінальний stage — легітимний лише за наявності нативного .node-аддона (див. docker.mdc). */
|
|
85
|
+
/** Bun-рантайм як фінальний stage — легітимний лише за наявності нативного .node-аддона або `n-rules:bun-no-compile`-маркера (див. docker.mdc). */
|
|
85
86
|
const BUN_RUNTIME_IMAGE = 'mirror.gcr.io/oven/bun'
|
|
86
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Явний opt-in консюмера: сервіс не можна пакувати через `bun build --compile` з причини, яку
|
|
90
|
+
* checker не може вивести механічно (динамічний `import()` рантайм-конфігу тощо — на відміну
|
|
91
|
+
* від нативних `.node`-аддонів, які виявляються з `package.json#dependencies`). Маркер —
|
|
92
|
+
* коментар-рядок `# n-rules:bun-no-compile: <причина>` будь-де у файлі; той самий канон, що й для
|
|
93
|
+
* native-addon: ship `node_modules` + `bun <entry>` на `mirror.gcr.io/oven/bun:*`.
|
|
94
|
+
* @param {string} fileContent вміст Dockerfile/Containerfile
|
|
95
|
+
* @returns {boolean} true, якщо маркер присутній із непорожньою причиною
|
|
96
|
+
*/
|
|
97
|
+
export function hasBunNoCompileMarker(fileContent) {
|
|
98
|
+
return fileContent.split(NEWLINE_RE).some(line => {
|
|
99
|
+
const m = line.trim().match(BUN_NO_COMPILE_MARKER_RE)
|
|
100
|
+
return Boolean(m && m[1].trim().length > 0)
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
87
104
|
/**
|
|
88
105
|
* Чи ref фінального `FROM` відповідає дозволеним у docker.mdc (multistage / runtime).
|
|
89
106
|
* @param {string} lastLower ref без digest, lower case
|
|
90
|
-
* @param {boolean} [
|
|
107
|
+
* @param {boolean} [allowBunRuntime] чи легітимний bun-рантайм як фінальний stage (нативний аддон або `n-rules:bun-no-compile`-маркер)
|
|
91
108
|
* @returns {boolean} true, якщо образ дозволений як фінальний runtime
|
|
92
109
|
*/
|
|
93
|
-
function isAllowedFinalRuntimeImage(lastLower,
|
|
110
|
+
function isAllowedFinalRuntimeImage(lastLower, allowBunRuntime = false) {
|
|
94
111
|
if (lastLower === 'scratch' || lastLower.startsWith('scratch:')) {
|
|
95
112
|
return true
|
|
96
113
|
}
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
|
|
114
|
+
// Канон — ship node_modules + `bun <entry>`, тож фінальний stage на mirror.gcr.io/oven/bun:*
|
|
115
|
+
// легітимний, коли compile неможливий (native-addon: docker-native-addon.mjs, або явний
|
|
116
|
+
// n-rules:bun-no-compile-маркер: hasBunNoCompileMarker).
|
|
117
|
+
if (allowBunRuntime && (lastLower === BUN_RUNTIME_IMAGE || lastLower.startsWith(`${BUN_RUNTIME_IMAGE}:`))) {
|
|
100
118
|
return true
|
|
101
119
|
}
|
|
102
120
|
const deb = lastLower.match(DEBIAN_VIA_MIRROR_RE)
|
|
@@ -132,7 +150,8 @@ export function splitDockerfileStages(fileContent) {
|
|
|
132
150
|
* Перевіряє базові вимоги до структури Dockerfile:
|
|
133
151
|
* - multistage: мінімум 2 FROM
|
|
134
152
|
* - фінальний FROM: дозволені образи в docker.mdc (alpine, scratch, debian slim, php, python, nginx, openresty, …);
|
|
135
|
-
* для проєктів із нативним .node-аддоном додатково дозволено
|
|
153
|
+
* для проєктів із нативним .node-аддоном або `n-rules:bun-no-compile`-маркером додатково дозволено
|
|
154
|
+
* mirror.gcr.io/oven/bun:* (bun-рантайм)
|
|
136
155
|
* @param {string} fileContent вміст Dockerfile/Containerfile
|
|
137
156
|
* @param {{ hasNativeAddon?: boolean }} [opts] опції: hasNativeAddon — є нативний .node-аддон (sharp/@img/argon2)
|
|
138
157
|
* @returns {string | null} повідомлення помилки або null
|
|
@@ -148,8 +167,9 @@ export function getMultistageAndRuntimeHint(fileContent, { hasNativeAddon = fals
|
|
|
148
167
|
const last = stages.at(-1)
|
|
149
168
|
const lastImage = (last?.image || '').split('@', 1)[0] || ''
|
|
150
169
|
const lastLower = lastImage.toLowerCase()
|
|
170
|
+
const allowBunRuntime = hasNativeAddon || hasBunNoCompileMarker(fileContent)
|
|
151
171
|
|
|
152
|
-
if (!isAllowedFinalRuntimeImage(lastLower,
|
|
172
|
+
if (!isAllowedFinalRuntimeImage(lastLower, allowBunRuntime)) {
|
|
153
173
|
return `фінальний FROM має бути дозволеним runtime-образом (див. docker.mdc: multistage), зараз: ${last?.image} (рядок ${last?.line})`
|
|
154
174
|
}
|
|
155
175
|
|
|
@@ -161,7 +181,9 @@ export function getMultistageAndRuntimeHint(fileContent, { hasNativeAddon = fals
|
|
|
161
181
|
*
|
|
162
182
|
* Тригер:
|
|
163
183
|
* - у Dockerfile є крок `bun install` (або `bun i`);
|
|
164
|
-
* - фінальний FROM — `mirror.gcr.io/library/alpine:*` (тобто не nginx/openresty frontend)
|
|
184
|
+
* - фінальний FROM — `mirror.gcr.io/library/alpine:*` (тобто не nginx/openresty frontend);
|
|
185
|
+
* - немає `n-rules:bun-no-compile`-маркера (явний opt-in консюмера — compile неможливий з причини поза
|
|
186
|
+
* виявними класами на кшталт нативних аддонів, напр. динамічний `import()` рантайм-конфігу).
|
|
165
187
|
*
|
|
166
188
|
* Очікування:
|
|
167
189
|
* - у build stage є `bun build --compile`;
|
|
@@ -170,6 +192,8 @@ export function getMultistageAndRuntimeHint(fileContent, { hasNativeAddon = fals
|
|
|
170
192
|
* @returns {string | null} повідомлення помилки або null
|
|
171
193
|
*/
|
|
172
194
|
export function getBunCompileHint(fileContent) {
|
|
195
|
+
if (hasBunNoCompileMarker(fileContent)) return null
|
|
196
|
+
|
|
173
197
|
const stages = splitDockerfileStages(fileContent)
|
|
174
198
|
if (stages.length === 0) return null
|
|
175
199
|
|
package/rules/docker/main.mdc
CHANGED
|
@@ -132,6 +132,30 @@ CMD ["bun", "src/index.js"]
|
|
|
132
132
|
|
|
133
133
|
Для проєктів **без** нативних аддонів standalone-бінарник на alpine лишається каноном (див. розділ вище про компіляцію).
|
|
134
134
|
|
|
135
|
+
## Виняток: явний `n-rules:bun-no-compile`-маркер (причина поза виявними класами)
|
|
136
|
+
|
|
137
|
+
Нативний `.node`-аддон — механічно виявна причина (є в `package.json#dependencies`). Але бувають причини, які checker вивести не може: наприклад, сервіс завантажує конфіг через динамічний `import()` шляху, невідомого на момент компіляції, — `bun build --compile` такий шлях не трейсить, тож бінарник падає в рантаймі так само, як із нативним аддоном.
|
|
138
|
+
|
|
139
|
+
Для цих випадків — явний opt-in консюмера: коментар-рядок `# n-rules:bun-no-compile: <причина>` будь-де у Dockerfile/Containerfile (причина обов'язкова, непорожня). Маркер вимикає і вимогу `bun build --compile` (розділ «Компіляція bun-проєкту в бінарник»), і заборону `mirror.gcr.io/oven/bun:*` як фінального stage (розділ «Multistage build») — той самий канон, що й для нативних аддонів: ship `node_modules` + `bun <entry>` на `mirror.gcr.io/oven/bun:alpine`.
|
|
140
|
+
|
|
141
|
+
```dockerfile
|
|
142
|
+
# n-rules:bun-no-compile: gateway.config.js вантажиться через динамічний import(), compile не трейсить його
|
|
143
|
+
FROM mirror.gcr.io/oven/bun:alpine AS build-env
|
|
144
|
+
WORKDIR /app
|
|
145
|
+
COPY package.json .
|
|
146
|
+
RUN bun install --production
|
|
147
|
+
COPY ./src ./src
|
|
148
|
+
|
|
149
|
+
FROM mirror.gcr.io/oven/bun:alpine
|
|
150
|
+
WORKDIR /app
|
|
151
|
+
COPY --from=build-env --chown=bun:bun /app/node_modules ./node_modules
|
|
152
|
+
COPY --from=build-env --chown=bun:bun /app/src ./src
|
|
153
|
+
USER bun
|
|
154
|
+
CMD ["bun", "src/index.js"]
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Маркер — **не** заміна нативно-аддонного винятку (той визначається автоматично з `package.json`) і **не** привід уникати компіляції там, де вона можлива — це escape hatch для нового, не закодованого в checker класу причин; використовуй лише коли `bun build --compile` доведено не працює. Перевіряють `hasBunNoCompileMarker` / `getBunCompileHint` / `getMultistageAndRuntimeHint` у **`npm/rules/docker/lint/main.mjs`**.
|
|
158
|
+
|
|
135
159
|
## Non-root принцип у фінальному stage
|
|
136
160
|
|
|
137
161
|
Для всіх образів потрібно щоб використовувся non-root принцип. **Спосіб** досягнення non-root залежить від **бази**, а не від зміни ОС — змінювати дистрибутив (Alpine→Debian) заради лише non-root **не треба**. Два шляхи:
|
|
@@ -115,7 +115,7 @@ export function parseProgramOrNull(content, virtualPath) {
|
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
117
|
* Парсить файл і повертає `{ program, comments }` або null. Окремий вхід для перевірок,
|
|
118
|
-
* яким потрібні коментарі (наприклад, маркер `// allow-unsafe: ...` біля виклику) —
|
|
118
|
+
* яким потрібні коментарі (наприклад, маркер `// n-rules:allow-unsafe: ...` біля виклику) —
|
|
119
119
|
* базовий `parseProgramOrNull` свідомо лишається без коментарів, щоб не змінювати API.
|
|
120
120
|
* @param {string} content вихідний код
|
|
121
121
|
* @param {string} virtualPath шлях для вибору `lang` (також для діагностики)
|
|
@@ -3,52 +3,53 @@ type: JS Module
|
|
|
3
3
|
title: ast-scan-utils.mjs
|
|
4
4
|
resource: npm/scripts/utils/ast-scan-utils.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 0a015cfc
|
|
7
|
+
model: openai-codex/gpt-5.4-mini
|
|
8
|
+
tier: cloud-min
|
|
9
|
+
score: 100
|
|
10
|
+
issues: judge:error
|
|
11
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
7
12
|
---
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
## Огляд
|
|
15
|
+
|
|
16
|
+
Утиліти для AST-сканерів JS/TS на `oxc-parser`: `langFromPath` вибирає мову за шляхом файлу, `offsetToLine` переводить зміщення в номер рядка, `normalizeSnippet` стискає фрагмент коду, а `parseProgramOrNull` і `parseProgramAndCommentsOrNull` безпечно повертають `null` замість винятку, коли розбір не вдався.
|
|
17
|
+
|
|
18
|
+
Файл також надає спільні засоби для аналізу дерева й контексту: `walkAstWithAncestors` обходить AST разом із предками, `isFunctionNode` і `isJoinCall` розпізнають типові вузли, `templateQuasisText` та `isSqlListContextTemplate` допомагають працювати з `TemplateLiteral`, а `requireCallModule` і `dynamicImportModule` виділяють модуль із викликів імпорту.
|
|
10
19
|
|
|
11
20
|
## Поведінка
|
|
12
21
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
isSqlListContextTemplate: Визначає, чи є TemplateLiteral контекстом SQL-списку (IN/VALUES).
|
|
23
|
-
requireCallModule: Витягує ім'я модуля з аргументу виклику `require`.
|
|
24
|
-
dynamicImportModule: Витягує ім'я модуля з аргументу виклику `import`.
|
|
22
|
+
Утиліти працюють як спільний шар для AST-сканерів: спочатку за шляхом файлу визначається мова парсингу, далі текст розбирається в `program`, а для перевірок, яким потрібні коментарі поруч із кодом, — у пару `program` + `comments`. Якщо розбір не вдається, зовнішнім споживачам повертається `null`, щоб сканування не падало на синтаксично проблемних файлах.
|
|
23
|
+
|
|
24
|
+
Обхід дерева будується з урахуванням предків, щоб правила могли відрізняти контекст верхнього рівня від вкладеного всередині функцій. Під час такого обходу вузли-функції та виклики спискових операцій розпізнаються як типові шаблони для аналізу, а текстові фрагменти нормалізуються до компактного вигляду для повідомлень про порушення.
|
|
25
|
+
|
|
26
|
+
Окремий набір хелперів працює з `TemplateLiteral`: один збирає видимий текст усіх частин без вставок, інший за цим текстом визначає, чи схоже місце на SQL-контекст зі списком значень. Це дає змогу знаходити небезпечні або підозрілі шаблони без дублювання однакової логіки в різних правилах.
|
|
27
|
+
|
|
28
|
+
Для аналізу імпортів спільно використовуються перевірки на звичайний `require` і динамічний `import` з рядковим модулем. Обидва хелпери повертають лише назву модуля або порожній результат, щоб сканери могли однаково працювати з різними формами завантаження без прив’язки до конкретного правила.
|
|
29
|
+
|
|
30
|
+
Усі операції побудовані fail-safe: помилки парсингу або несподівані вузли не пробиваються назовні, а переводяться в безпечний результат. Це дозволяє сканерам пропускати проблемні фрагменти й продовжувати перевірку решти коду.
|
|
25
31
|
|
|
26
32
|
## Публічний API
|
|
27
33
|
|
|
28
|
-
- langFromPath —
|
|
29
|
-
- offsetToLine —
|
|
30
|
-
- normalizeSnippet —
|
|
31
|
-
- isFunctionNode —
|
|
32
|
-
- walkAstWithAncestors —
|
|
33
|
-
- parseProgramOrNull — Парсить файл
|
|
34
|
-
- parseProgramAndCommentsOrNull — Парсить файл
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
34
|
+
- langFromPath — Мова для Oxc за шляхом файлу (розширення).
|
|
35
|
+
- offsetToLine — Номер рядка (1-based) за зміщенням у буфері.
|
|
36
|
+
- normalizeSnippet — Стискає пробіли для повідомлення про порушення.
|
|
37
|
+
- isFunctionNode — Чи є вузол функцією.
|
|
38
|
+
- walkAstWithAncestors — Рекурсивний обхід AST з предками, щоб визначати контекст (всередині функції чи ні).
|
|
39
|
+
- parseProgramOrNull — Парсить файл і повертає `program` або null, якщо є синтаксичні помилки чи виняток.
|
|
40
|
+
- parseProgramAndCommentsOrNull — Парсить файл і повертає `{ program, comments }` або null. Окремий вхід для перевірок,
|
|
41
|
+
яким потрібні коментарі (наприклад, маркер `// n-rules:allow-unsafe: ...` біля виклику) —
|
|
42
|
+
базовий `parseProgramOrNull` свідомо лишається без коментарів, щоб не змінювати API.
|
|
43
|
+
- isJoinCall — Чи це `.join(...)` виклик (типово для динамічних списків у SQL).
|
|
44
|
+
- templateQuasisText — Текст quasis у TemplateLiteral (без expressions).
|
|
45
|
+
- isSqlListContextTemplate — Чи виглядає TemplateLiteral як SQL-контекст зі списком (IN/VALUES (...)).
|
|
46
|
+
- requireCallModule — Перевіряє, чи це виклик `require('<module>')` з рядковим аргументом.
|
|
47
|
+
Спільне для сканерів імпортів (`bunyan-imports`, `redis-imports`, ...).
|
|
48
|
+
- dynamicImportModule — Перевіряє, чи це динамічний `import('<module>')` з рядковим аргументом.
|
|
49
|
+
Спільне для сканерів імпортів.
|
|
39
50
|
|
|
40
51
|
## Гарантії поведінки
|
|
41
52
|
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
- `offsetToLine` повертає `null`, якщо зміщення недійсне.
|
|
46
|
-
- `normalizeSnippet` стискає текст сніпета.
|
|
47
|
-
- `normalizeSnippet` повертає `null`, якщо не вдалося стиснути сніпет.
|
|
48
|
-
- `isFunctionNode` визначає, чи є вузол AST функцією.
|
|
49
|
-
- `isFunctionNode` повертає `true` якщо вузол є функцією, інакше `false`.
|
|
50
|
-
- `walkAstWithAncestors` обходить AST, враховуючи предки вузлів.
|
|
51
|
-
- `walkAstWithAncestors` не повертає значень.
|
|
52
|
-
- `parseProgramOrNull` парсує програму та повертає її як AST або `null`, якщо парсинг не вдається.
|
|
53
|
-
- `parseProgramOrNull` повертає `null`, якщо програма не може бути успішно розпарсена.
|
|
54
|
-
- `parseProgramAndCommentsOrNull` парсує програму
|
|
53
|
+
- Власних операцій запису (ФС/БД) у файлі немає; виклики імпортованих модулів можуть писати.
|
|
54
|
+
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
55
|
+
- За певних помилок повертає порожнє значення (напр. `null`) замість винятку.
|