@birdcc/linter 0.0.1-alpha.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.
Files changed (60) hide show
  1. package/.oxfmtrc.json +16 -0
  2. package/LICENSE +674 -0
  3. package/README.md +210 -0
  4. package/dist/index.d.ts +21 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +93 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/rules/bgp.d.ts +5 -0
  9. package/dist/rules/bgp.d.ts.map +1 -0
  10. package/dist/rules/bgp.js +131 -0
  11. package/dist/rules/bgp.js.map +1 -0
  12. package/dist/rules/catalog.d.ts +14 -0
  13. package/dist/rules/catalog.d.ts.map +1 -0
  14. package/dist/rules/catalog.js +61 -0
  15. package/dist/rules/catalog.js.map +1 -0
  16. package/dist/rules/cfg.d.ts +5 -0
  17. package/dist/rules/cfg.d.ts.map +1 -0
  18. package/dist/rules/cfg.js +264 -0
  19. package/dist/rules/cfg.js.map +1 -0
  20. package/dist/rules/net.d.ts +5 -0
  21. package/dist/rules/net.d.ts.map +1 -0
  22. package/dist/rules/net.js +140 -0
  23. package/dist/rules/net.js.map +1 -0
  24. package/dist/rules/normalize.d.ts +6 -0
  25. package/dist/rules/normalize.d.ts.map +1 -0
  26. package/dist/rules/normalize.js +65 -0
  27. package/dist/rules/normalize.js.map +1 -0
  28. package/dist/rules/ospf.d.ts +5 -0
  29. package/dist/rules/ospf.d.ts.map +1 -0
  30. package/dist/rules/ospf.js +136 -0
  31. package/dist/rules/ospf.js.map +1 -0
  32. package/dist/rules/shared.d.ts +46 -0
  33. package/dist/rules/shared.d.ts.map +1 -0
  34. package/dist/rules/shared.js +184 -0
  35. package/dist/rules/shared.js.map +1 -0
  36. package/dist/rules/sym.d.ts +5 -0
  37. package/dist/rules/sym.d.ts.map +1 -0
  38. package/dist/rules/sym.js +188 -0
  39. package/dist/rules/sym.js.map +1 -0
  40. package/dist/rules/type.d.ts +5 -0
  41. package/dist/rules/type.d.ts.map +1 -0
  42. package/dist/rules/type.js +130 -0
  43. package/dist/rules/type.js.map +1 -0
  44. package/package.json +41 -0
  45. package/src/index.ts +155 -0
  46. package/src/rules/bgp.ts +239 -0
  47. package/src/rules/catalog.ts +80 -0
  48. package/src/rules/cfg.ts +562 -0
  49. package/src/rules/net.ts +262 -0
  50. package/src/rules/normalize.ts +90 -0
  51. package/src/rules/ospf.ts +221 -0
  52. package/src/rules/shared.ts +354 -0
  53. package/src/rules/sym.ts +342 -0
  54. package/src/rules/type.ts +210 -0
  55. package/test/linter.bgp-ospf.test.ts +129 -0
  56. package/test/linter.migration.test.ts +66 -0
  57. package/test/linter.net-type.test.ts +132 -0
  58. package/test/linter.sym-cfg.test.ts +224 -0
  59. package/test/linter.test.ts +21 -0
  60. package/tsconfig.json +8 -0
package/README.md ADDED
@@ -0,0 +1,210 @@
1
+ <div align="center">
2
+
3
+ # 🧩 BIRD Config Linter (@birdcc/linter)
4
+
5
+ </div>
6
+
7
+ [![npm version](https://img.shields.io/badge/version-0.1.0--alpha-blue)](https://www.npmjs.com/package/@birdcc/linter) [![License: GPL-3.0](https://img.shields.io/badge/License-GPL--3.0--only-green.svg)](https://www.gnu.org/licenses/gpl-3.0) [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178c6?logo=typescript)](https://www.typescriptlang.org/)
8
+
9
+ > [Overview](#overview) · [Features](#features) · [Installation](#installation) · [Usage](#usage) · [Rules](#rules) · [API Reference](#api-reference)
10
+
11
+ ## Overview
12
+
13
+ **@birdcc/linter** is the rule engine layer of the BIRD-LSP toolchain, providing a pluggable lint rule system for checking protocol compliance, security, and performance issues in BIRD2 configuration files.
14
+
15
+ ---
16
+
17
+ ## Features
18
+
19
+ - 🧩 **Pluggable Rules** — Flexible rule system based on the `BirdRule` type
20
+ - 🌐 **Protocol Rules** — BGP/OSPF configuration completeness checks
21
+ - 🔒 **Security Rules** — Configuration security best practices
22
+ - ⚡ **Performance Rules** — Performance optimization recommendations
23
+ - 🔍 **32+ Built-in Rules** — Comprehensive coverage of common issues
24
+
25
+ ---
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ # Using pnpm (recommended)
31
+ pnpm add @birdcc/linter
32
+
33
+ # Using npm
34
+ npm install @birdcc/linter
35
+
36
+ # Using yarn
37
+ yarn add @birdcc/linter
38
+ ```
39
+
40
+ ---
41
+
42
+ ## Usage
43
+
44
+ ### Basic Linting
45
+
46
+ ```typescript
47
+ import { lintBirdConfig } from "@birdcc/linter";
48
+
49
+ const config = `
50
+ protocol bgp example {
51
+ neighbor 192.168.1.1 as 65001;
52
+ }
53
+ `;
54
+
55
+ const result = lintBirdConfig(config);
56
+
57
+ console.log(result.diagnostics);
58
+ // [{ code: "bgp/missing-local-as", message: "BGP protocol missing local as configuration", severity: "warning" }]
59
+ ```
60
+
61
+ ### Custom Rules
62
+
63
+ ```typescript
64
+ import type { BirdRule, BirdDiagnostic } from "@birdcc/linter";
65
+
66
+ const namingConventionRule: BirdRule = ({ core }) => {
67
+ const diagnostics: BirdDiagnostic[] = [];
68
+
69
+ for (const symbol of core.symbols) {
70
+ if (symbol.kind === "protocol") {
71
+ if (!/^[a-z][a-z0-9-]*$/.test(symbol.name)) {
72
+ diagnostics.push({
73
+ code: "structure/invalid-protocol-name",
74
+ message: `Protocol name '${symbol.name}' should only contain lowercase letters, numbers, and hyphens`,
75
+ severity: "warning",
76
+ source: "linter",
77
+ range: { /* ... */ },
78
+ });
79
+ }
80
+ }
81
+ }
82
+
83
+ return diagnostics;
84
+ };
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Rules
90
+
91
+ ### Symbol Rules (`sym/*`)
92
+
93
+ | Rule | Description | Level |
94
+ | ---- | ----------- | ----- |
95
+ | `sym/undefined` | Reference to undefined symbol | error |
96
+ | `sym/duplicate` | Duplicate symbol definition | error |
97
+ | `sym/proto-type-mismatch` | Protocol type mismatch | error |
98
+
99
+ ### Config Rules (`cfg/*`)
100
+
101
+ | Rule | Description | Level |
102
+ | ---- | ----------- | ----- |
103
+ | `cfg/no-protocol` | No protocol defined | error |
104
+ | `cfg/missing-router-id` | Missing router id | error |
105
+ | `cfg/syntax-error` | Syntax error detected | error |
106
+ | `cfg/value-out-of-range` | Value out of valid range | error |
107
+
108
+ ### Network Rules (`net/*`)
109
+
110
+ | Rule | Description | Level |
111
+ | ---- | ----------- | ----- |
112
+ | `net/invalid-prefix-length` | Invalid prefix length | error |
113
+ | `net/invalid-ipv4-prefix` | Invalid IPv4 prefix | error |
114
+ | `net/invalid-ipv6-prefix` | Invalid IPv6 prefix | error |
115
+
116
+ ### Type Rules (`type/*`)
117
+
118
+ | Rule | Description | Level |
119
+ | ---- | ----------- | ----- |
120
+ | `type/mismatch` | Type mismatch | error |
121
+ | `type/not-iterable` | Non-iterable in loop | error |
122
+
123
+ ### BGP Rules (`bgp/*`)
124
+
125
+ | Rule | Description | Level |
126
+ | ---- | ----------- | ----- |
127
+ | `bgp/missing-local-as` | Missing local AS | warning |
128
+ | `bgp/missing-neighbor` | Missing neighbor | warning |
129
+ | `bgp/missing-remote-as` | Missing remote AS | warning |
130
+ | `bgp/as-mismatch` | AS number mismatch | warning |
131
+
132
+ ### OSPF Rules (`ospf/*`)
133
+
134
+ | Rule | Description | Level |
135
+ | ---- | ----------- | ----- |
136
+ | `ospf/missing-area` | Missing area configuration | warning |
137
+ | `ospf/backbone-stub` | Stub area on backbone | warning |
138
+
139
+ ---
140
+
141
+ ## API Reference
142
+
143
+ ### `lintBirdConfig(text: string, options?): LintResult`
144
+
145
+ Perform complete lint checks (semantic analysis + rule checks).
146
+
147
+ ```typescript
148
+ import { lintBirdConfig } from "@birdcc/linter";
149
+
150
+ const result = lintBirdConfig(birdConfigText);
151
+ // result.parsed → Parsed AST
152
+ // result.core → Semantic analysis snapshot
153
+ // result.diagnostics → All diagnostic messages
154
+ ```
155
+
156
+ ### Types
157
+
158
+ ```typescript
159
+ interface LintResult {
160
+ parsed: ParsedBirdDocument;
161
+ core: CoreSnapshot;
162
+ diagnostics: BirdDiagnostic[];
163
+ }
164
+
165
+ type BirdRule = (context: RuleContext) => BirdDiagnostic[];
166
+
167
+ interface RuleContext {
168
+ text: string;
169
+ parsed: ParsedBirdDocument;
170
+ core: CoreSnapshot;
171
+ }
172
+ ```
173
+
174
+ ---
175
+
176
+ ## Related Packages
177
+
178
+ | Package | Description |
179
+ | ------- | ----------- |
180
+ | [@birdcc/parser](../parser/) | Tree-sitter grammar and parser |
181
+ | [@birdcc/core](../core/) | Semantic analysis engine |
182
+ | [@birdcc/formatter](../formatter/) | Code formatting engine |
183
+ | [@birdcc/lsp](../lsp/) | LSP server implementation |
184
+ | [@birdcc/cli](../cli/) | Command-line interface |
185
+
186
+ ---
187
+
188
+ ### 📖 Documentation
189
+
190
+ - [BIRD Official Documentation](https://bird.network.cz/)
191
+ - [BIRD2 User Manual](https://bird.network.cz/doc/bird.html)
192
+ - [GitHub Project](https://github.com/bird-chinese-community/BIRD-LSP)
193
+
194
+ ---
195
+
196
+ ## 📝 License
197
+
198
+ This project is licensed under the [GPL-3.0 License](https://github.com/bird-chinese-community/BIRD-LSP/blob/main/LICENSE).
199
+
200
+ ---
201
+
202
+ <p align="center">
203
+ <sub>Built with ❤️ by the BIRD Chinese Community (BIRDCC)</sub>
204
+ </p>
205
+
206
+ <p align="center">
207
+ <a href="https://github.com/bird-chinese-community/BIRD-LSP">🕊 GitHub</a> ·
208
+ <a href="https://marketplace.visualstudio.com/items?itemName=birdcc.bird2-lsp">🛒 Marketplace</a> ·
209
+ <a href="https://github.com/bird-chinese-community/BIRD-LSP/issues">🐛 Report Issues</a>
210
+ </p>
@@ -0,0 +1,21 @@
1
+ import type { CrossFileResolutionResult } from "@birdcc/core";
2
+ import { type BirdDiagnostic, type CoreSnapshot } from "@birdcc/core";
3
+ import { type ParsedBirdDocument } from "@birdcc/parser";
4
+ export interface LintResult {
5
+ parsed: ParsedBirdDocument;
6
+ core: CoreSnapshot;
7
+ diagnostics: BirdDiagnostic[];
8
+ }
9
+ export interface LintBirdConfigOptions {
10
+ parsed?: ParsedBirdDocument;
11
+ core?: CoreSnapshot;
12
+ uri?: string;
13
+ }
14
+ export interface CrossFileLintResult {
15
+ diagnostics: BirdDiagnostic[];
16
+ byUri: Record<string, LintResult>;
17
+ }
18
+ /** Runs parser + core + normalized 32-rule linter pipeline and returns merged diagnostics. */
19
+ export declare const lintBirdConfig: (text: string, options?: LintBirdConfigOptions) => Promise<LintResult>;
20
+ export declare const lintResolvedCrossFileGraph: (resolution: CrossFileResolutionResult) => Promise<CrossFileLintResult>;
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAe,MAAM,cAAc,CAAC;AAC3E,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAU1E,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,IAAI,EAAE,YAAY,CAAC;IACnB,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAkDD,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACnC;AAED,8FAA8F;AAC9F,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,UAAS,qBAA0B,KAClC,OAAO,CAAC,UAAU,CAkCpB,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,YAAY,yBAAyB,KACpC,OAAO,CAAC,mBAAmB,CA+B7B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,93 @@
1
+ import { buildCoreSnapshotFromParsed, } from "@birdcc/core";
2
+ import { parseBirdConfig } from "@birdcc/parser";
3
+ import { collectBgpRuleDiagnostics } from "./rules/bgp.js";
4
+ import { collectCfgRuleDiagnostics } from "./rules/cfg.js";
5
+ import { collectNetRuleDiagnostics } from "./rules/net.js";
6
+ import { normalizeBaseDiagnostics } from "./rules/normalize.js";
7
+ import { collectOspfRuleDiagnostics } from "./rules/ospf.js";
8
+ import { collectSymRuleDiagnostics } from "./rules/sym.js";
9
+ import { collectTypeRuleDiagnostics } from "./rules/type.js";
10
+ const dedupeDiagnostics = (diagnostics) => {
11
+ const seen = new Set();
12
+ const output = [];
13
+ for (const diagnostic of diagnostics) {
14
+ const key = [
15
+ diagnostic.code,
16
+ diagnostic.message,
17
+ diagnostic.uri ?? "",
18
+ diagnostic.range.line,
19
+ diagnostic.range.column,
20
+ diagnostic.range.endLine,
21
+ diagnostic.range.endColumn,
22
+ ].join(":");
23
+ if (seen.has(key)) {
24
+ continue;
25
+ }
26
+ seen.add(key);
27
+ output.push(diagnostic);
28
+ }
29
+ return output;
30
+ };
31
+ const diagnosticsForUri = (diagnostics, uri, entryUri) => {
32
+ return diagnostics.filter((diagnostic) => (diagnostic.uri ?? entryUri) === uri);
33
+ };
34
+ const createMergedCoreSnapshot = (localCore, mergedSymbolTable, scopedDiagnostics) => ({
35
+ ...localCore,
36
+ symbols: mergedSymbolTable.definitions,
37
+ references: mergedSymbolTable.references,
38
+ symbolTable: mergedSymbolTable,
39
+ diagnostics: scopedDiagnostics,
40
+ });
41
+ /** Runs parser + core + normalized 32-rule linter pipeline and returns merged diagnostics. */
42
+ export const lintBirdConfig = async (text, options = {}) => {
43
+ const parsed = options.parsed ?? (await parseBirdConfig(text));
44
+ const core = options.core ?? buildCoreSnapshotFromParsed(parsed, { uri: options.uri });
45
+ const context = { text, parsed, core };
46
+ const normalizedBaseDiagnostics = normalizeBaseDiagnostics(parsed, core.diagnostics, {
47
+ uri: options.uri,
48
+ });
49
+ const ruleDiagnostics = [
50
+ ...collectSymRuleDiagnostics(context),
51
+ ...collectCfgRuleDiagnostics(context),
52
+ ...collectNetRuleDiagnostics(context),
53
+ ...collectTypeRuleDiagnostics(context),
54
+ ...collectBgpRuleDiagnostics(context),
55
+ ...collectOspfRuleDiagnostics(context),
56
+ ].map((diagnostic) => ({
57
+ ...diagnostic,
58
+ uri: diagnostic.uri ?? options.uri,
59
+ }));
60
+ return {
61
+ parsed,
62
+ core,
63
+ diagnostics: dedupeDiagnostics([
64
+ ...normalizedBaseDiagnostics,
65
+ ...ruleDiagnostics,
66
+ ]),
67
+ };
68
+ };
69
+ export const lintResolvedCrossFileGraph = async (resolution) => {
70
+ const byUri = {};
71
+ const diagnostics = [];
72
+ const uris = resolution.visitedUris.length > 0
73
+ ? resolution.visitedUris
74
+ : [resolution.entryUri];
75
+ for (const uri of uris) {
76
+ const text = resolution.documents[uri];
77
+ const localCore = resolution.snapshots[uri];
78
+ if (!text || !localCore) {
79
+ continue;
80
+ }
81
+ const lintResult = await lintBirdConfig(text, {
82
+ uri,
83
+ core: createMergedCoreSnapshot(localCore, resolution.symbolTable, diagnosticsForUri(resolution.diagnostics, uri, resolution.entryUri)),
84
+ });
85
+ byUri[uri] = lintResult;
86
+ diagnostics.push(...lintResult.diagnostics);
87
+ }
88
+ return {
89
+ byUri,
90
+ diagnostics: dedupeDiagnostics(diagnostics),
91
+ };
92
+ };
93
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { BirdDiagnostic } from "@birdcc/core";
2
+ import { type BirdRule } from "./shared.js";
3
+ export declare const bgpRules: BirdRule[];
4
+ export declare const collectBgpRuleDiagnostics: (context: Parameters<BirdRule>[0]) => BirdDiagnostic[];
5
+ //# sourceMappingURL=bgp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bgp.d.ts","sourceRoot":"","sources":["../../src/rules/bgp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAOL,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAyNrB,eAAO,MAAM,QAAQ,EAAE,QAAQ,EAM9B,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,SAAS,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAC/B,cAAc,EAEhB,CAAC"}
@@ -0,0 +1,131 @@
1
+ import { createProtocolDiagnostic, createRuleDiagnostic, extractFirstNumberAfterKeyword, isProtocolType, numericValue, protocolDeclarations, } from "./shared.js";
2
+ const isInternalSession = (value) => /^(internal|ibgp)$/i.test(value?.trim() ?? "");
3
+ const isExternalSession = (value) => /^(external|ebgp)$/i.test(value?.trim() ?? "");
4
+ const bgpMissingLocalAsRule = ({ parsed }) => {
5
+ const diagnostics = [];
6
+ for (const declaration of protocolDeclarations(parsed)) {
7
+ if (!isProtocolType(declaration, "bgp")) {
8
+ continue;
9
+ }
10
+ if (declaration.statements.some((statement) => statement.kind === "local-as")) {
11
+ continue;
12
+ }
13
+ diagnostics.push(createProtocolDiagnostic("bgp/missing-local-as", `BGP protocol '${declaration.name}' missing local AS number`, declaration));
14
+ }
15
+ return diagnostics;
16
+ };
17
+ const bgpMissingNeighborRule = ({ parsed }) => {
18
+ const diagnostics = [];
19
+ for (const declaration of protocolDeclarations(parsed)) {
20
+ if (!isProtocolType(declaration, "bgp")) {
21
+ continue;
22
+ }
23
+ if (declaration.statements.some((statement) => statement.kind === "neighbor")) {
24
+ continue;
25
+ }
26
+ diagnostics.push(createProtocolDiagnostic("bgp/missing-neighbor", `BGP protocol '${declaration.name}' missing neighbor configuration`, declaration));
27
+ }
28
+ return diagnostics;
29
+ };
30
+ const bgpMissingRemoteAsRule = ({ parsed }) => {
31
+ const diagnostics = [];
32
+ for (const declaration of protocolDeclarations(parsed)) {
33
+ if (!isProtocolType(declaration, "bgp")) {
34
+ continue;
35
+ }
36
+ for (const statement of declaration.statements) {
37
+ if (statement.kind !== "neighbor") {
38
+ continue;
39
+ }
40
+ if (isInternalSession(statement.asn) ||
41
+ isExternalSession(statement.asn)) {
42
+ continue;
43
+ }
44
+ if (statement.asn && numericValue(statement.asn) !== null) {
45
+ continue;
46
+ }
47
+ diagnostics.push(createRuleDiagnostic("bgp/missing-remote-as", `BGP protocol '${declaration.name}' neighbor '${statement.address}' missing remote AS`, statement.asnRange ?? statement.addressRange));
48
+ }
49
+ }
50
+ return diagnostics;
51
+ };
52
+ const bgpAsMismatchRule = ({ parsed }) => {
53
+ const diagnostics = [];
54
+ for (const declaration of protocolDeclarations(parsed)) {
55
+ if (!isProtocolType(declaration, "bgp")) {
56
+ continue;
57
+ }
58
+ const localAsStatement = declaration.statements.find((statement) => statement.kind === "local-as");
59
+ if (!localAsStatement || localAsStatement.kind !== "local-as") {
60
+ continue;
61
+ }
62
+ const localAs = numericValue(localAsStatement.asn);
63
+ if (localAs === null) {
64
+ continue;
65
+ }
66
+ const hasInternalNeighbor = declaration.statements.some((statement) => statement.kind === "neighbor" && isInternalSession(statement.asn));
67
+ if (!hasInternalNeighbor) {
68
+ continue;
69
+ }
70
+ for (const statement of declaration.statements) {
71
+ if (statement.kind !== "neighbor" || !statement.asn) {
72
+ continue;
73
+ }
74
+ if (isInternalSession(statement.asn) ||
75
+ isExternalSession(statement.asn)) {
76
+ continue;
77
+ }
78
+ const remoteAs = numericValue(statement.asn);
79
+ if (remoteAs === null || remoteAs === localAs) {
80
+ continue;
81
+ }
82
+ diagnostics.push(createRuleDiagnostic("bgp/as-mismatch", `BGP protocol '${declaration.name}' internal session requires same ASN (local ${localAs}, remote ${remoteAs})`, statement.asnRange ?? statement.addressRange));
83
+ }
84
+ }
85
+ return diagnostics;
86
+ };
87
+ const bgpTimerInvalidRule = ({ parsed }) => {
88
+ const diagnostics = [];
89
+ for (const declaration of protocolDeclarations(parsed)) {
90
+ if (!isProtocolType(declaration, "bgp")) {
91
+ continue;
92
+ }
93
+ let hold = null;
94
+ let keepalive = null;
95
+ for (const statement of declaration.statements) {
96
+ if (statement.kind !== "other") {
97
+ continue;
98
+ }
99
+ const text = statement.text.toLowerCase();
100
+ const holdValue = extractFirstNumberAfterKeyword(text, "hold");
101
+ const keepaliveValue = extractFirstNumberAfterKeyword(text, "keepalive");
102
+ if (holdValue !== null) {
103
+ hold = holdValue;
104
+ if (hold < 3 || hold > 65_535) {
105
+ diagnostics.push(createRuleDiagnostic("bgp/timer-invalid", `BGP protocol '${declaration.name}' hold time must be in range 3..65535`, statement));
106
+ }
107
+ }
108
+ if (keepaliveValue !== null) {
109
+ keepalive = keepaliveValue;
110
+ if (keepalive < 1 || keepalive > 65_535) {
111
+ diagnostics.push(createRuleDiagnostic("bgp/timer-invalid", `BGP protocol '${declaration.name}' keepalive must be in range 1..65535`, statement));
112
+ }
113
+ }
114
+ }
115
+ if (hold !== null && keepalive !== null && keepalive >= hold) {
116
+ diagnostics.push(createProtocolDiagnostic("bgp/timer-invalid", `BGP protocol '${declaration.name}' keepalive (${keepalive}) must be smaller than hold (${hold})`, declaration));
117
+ }
118
+ }
119
+ return diagnostics;
120
+ };
121
+ export const bgpRules = [
122
+ bgpMissingLocalAsRule,
123
+ bgpMissingNeighborRule,
124
+ bgpMissingRemoteAsRule,
125
+ bgpAsMismatchRule,
126
+ bgpTimerInvalidRule,
127
+ ];
128
+ export const collectBgpRuleDiagnostics = (context) => {
129
+ return bgpRules.flatMap((rule) => rule(context));
130
+ };
131
+ //# sourceMappingURL=bgp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bgp.js","sourceRoot":"","sources":["../../src/rules/bgp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { BirdDiagnosticSeverity } from "@birdcc/core";
2
+ export declare const RULE_CODES: {
3
+ readonly sym: readonly ["sym/undefined", "sym/duplicate", "sym/proto-type-mismatch", "sym/filter-required", "sym/function-required", "sym/table-required", "sym/variable-scope"];
4
+ readonly cfg: readonly ["cfg/no-protocol", "cfg/missing-router-id", "cfg/syntax-error", "cfg/value-out-of-range", "cfg/switch-value-expected", "cfg/number-expected", "cfg/incompatible-type", "cfg/ip-network-mismatch", "cfg/circular-template"];
5
+ readonly net: readonly ["net/invalid-prefix-length", "net/invalid-ipv4-prefix", "net/invalid-ipv6-prefix", "net/max-prefix-length"];
6
+ readonly type: readonly ["type/mismatch", "type/not-iterable", "type/set-incompatible"];
7
+ readonly bgp: readonly ["bgp/missing-local-as", "bgp/missing-neighbor", "bgp/missing-remote-as", "bgp/as-mismatch", "bgp/timer-invalid"];
8
+ readonly ospf: readonly ["ospf/missing-area", "ospf/backbone-stub", "ospf/vlink-in-backbone", "ospf/asbr-stub-area"];
9
+ };
10
+ export type RuleCode = (typeof RULE_CODES.sym)[number] | (typeof RULE_CODES.cfg)[number] | (typeof RULE_CODES.net)[number] | (typeof RULE_CODES.type)[number] | (typeof RULE_CODES.bgp)[number] | (typeof RULE_CODES.ospf)[number];
11
+ export declare const RULE_SEVERITY: Record<RuleCode, BirdDiagnosticSeverity>;
12
+ export declare const LEGACY_CODE_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp];
13
+ export declare const isRuleCode: (code: string) => code is RuleCode;
14
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/rules/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAE3D,eAAO,MAAM,UAAU;;;;;;;CAyCb,CAAC;AAEX,MAAM,MAAM,QAAQ,GAChB,CAAC,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAC/B,CAAC,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAC/B,CAAC,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAC/B,CAAC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,GAChC,CAAC,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAC/B,CAAC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;AAarC,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,QAAQ,EAAE,sBAAsB,CAIhE,CAAC;AAEJ,eAAO,MAAM,oBAAoB,2CAKvB,CAAC;AAEX,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,IAAI,IAAI,QAEjD,CAAC"}
@@ -0,0 +1,61 @@
1
+ export const RULE_CODES = {
2
+ sym: [
3
+ "sym/undefined",
4
+ "sym/duplicate",
5
+ "sym/proto-type-mismatch",
6
+ "sym/filter-required",
7
+ "sym/function-required",
8
+ "sym/table-required",
9
+ "sym/variable-scope",
10
+ ],
11
+ cfg: [
12
+ "cfg/no-protocol",
13
+ "cfg/missing-router-id",
14
+ "cfg/syntax-error",
15
+ "cfg/value-out-of-range",
16
+ "cfg/switch-value-expected",
17
+ "cfg/number-expected",
18
+ "cfg/incompatible-type",
19
+ "cfg/ip-network-mismatch",
20
+ "cfg/circular-template",
21
+ ],
22
+ net: [
23
+ "net/invalid-prefix-length",
24
+ "net/invalid-ipv4-prefix",
25
+ "net/invalid-ipv6-prefix",
26
+ "net/max-prefix-length",
27
+ ],
28
+ type: ["type/mismatch", "type/not-iterable", "type/set-incompatible"],
29
+ bgp: [
30
+ "bgp/missing-local-as",
31
+ "bgp/missing-neighbor",
32
+ "bgp/missing-remote-as",
33
+ "bgp/as-mismatch",
34
+ "bgp/timer-invalid",
35
+ ],
36
+ ospf: [
37
+ "ospf/missing-area",
38
+ "ospf/backbone-stub",
39
+ "ospf/vlink-in-backbone",
40
+ "ospf/asbr-stub-area",
41
+ ],
42
+ };
43
+ const ruleSeverityEntries = [
44
+ ...RULE_CODES.sym.map((code) => [code, "error"]),
45
+ ...RULE_CODES.cfg.map((code) => [code, "error"]),
46
+ ...RULE_CODES.net.map((code) => [code, "error"]),
47
+ ...RULE_CODES.type.map((code) => [code, "error"]),
48
+ ...RULE_CODES.bgp.map((code) => [code, "warning"]),
49
+ ...RULE_CODES.ospf.map((code) => [code, "warning"]),
50
+ ];
51
+ export const RULE_SEVERITY = Object.fromEntries(ruleSeverityEntries);
52
+ export const LEGACY_CODE_PATTERNS = [
53
+ /^protocol\//,
54
+ /^security\//,
55
+ /^performance\//,
56
+ /^structure\//,
57
+ ];
58
+ export const isRuleCode = (code) => {
59
+ return code in RULE_SEVERITY;
60
+ };
61
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/rules/catalog.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,GAAG,EAAE;QACH,eAAe;QACf,eAAe;QACf,yBAAyB;QACzB,qBAAqB;QACrB,uBAAuB;QACvB,oBAAoB;QACpB,oBAAoB;KACrB;IACD,GAAG,EAAE;QACH,iBAAiB;QACjB,uBAAuB;QACvB,kBAAkB;QAClB,wBAAwB;QACxB,2BAA2B;QAC3B,qBAAqB;QACrB,uBAAuB;QACvB,yBAAyB;QACzB,uBAAuB;KACxB;IACD,GAAG,EAAE;QACH,2BAA2B;QAC3B,yBAAyB;QACzB,yBAAyB;QACzB,uBAAuB;KACxB;IACD,IAAI,EAAE,CAAC,eAAe,EAAE,mBAAmB,EAAE,uBAAuB,CAAC;IACrE,GAAG,EAAE;QACH,sBAAsB;QACtB,sBAAsB;QACtB,uBAAuB;QACvB,iBAAiB;QACjB,mBAAmB;KACpB;IACD,IAAI,EAAE;QACJ,mBAAmB;QACnB,oBAAoB;QACpB,wBAAwB;QACxB,qBAAqB;KACtB;CACO,CAAC;AAUX,MAAM,mBAAmB,GAErB;IACF,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAU,CAAC;IACzD,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAU,CAAC;IACzD,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAU,CAAC;IACzD,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAU,CAAC;IAC1D,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,CAAU,CAAC;IAC3D,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,CAAU,CAAC;CAC7D,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GACxB,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAGrC,CAAC;AAEJ,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,aAAa;IACb,aAAa;IACb,gBAAgB;IAChB,cAAc;CACN,CAAC;AAEX,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAoB,EAAE;IAC3D,OAAO,IAAI,IAAI,aAAa,CAAC;AAC/B,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { BirdDiagnostic } from "@birdcc/core";
2
+ import { type BirdRule } from "./shared.js";
3
+ export declare const cfgRules: BirdRule[];
4
+ export declare const collectCfgRuleDiagnostics: (context: Parameters<BirdRule>[0]) => BirdDiagnostic[];
5
+ //# sourceMappingURL=cfg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cfg.d.ts","sourceRoot":"","sources":["../../src/rules/cfg.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAYL,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAkhBrB,eAAO,MAAM,QAAQ,EAAE,QAAQ,EAS9B,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,SAAS,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAC/B,cAAc,EAEhB,CAAC"}