@nielspeter/eess 0.1.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/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/ansi.d.ts +7 -0
- package/dist/ansi.d.ts.map +1 -0
- package/dist/ansi.js +16 -0
- package/dist/ansi.js.map +1 -0
- package/dist/apply-fixes.d.ts +25 -0
- package/dist/apply-fixes.d.ts.map +1 -0
- package/dist/apply-fixes.js +52 -0
- package/dist/apply-fixes.js.map +1 -0
- package/dist/baseline-generator.d.ts +18 -0
- package/dist/baseline-generator.d.ts.map +1 -0
- package/dist/baseline-generator.js +29 -0
- package/dist/baseline-generator.js.map +1 -0
- package/dist/baseline.d.ts +83 -0
- package/dist/baseline.d.ts.map +1 -0
- package/dist/baseline.js +115 -0
- package/dist/baseline.js.map +1 -0
- package/dist/check-options.d.ts +47 -0
- package/dist/check-options.d.ts.map +1 -0
- package/dist/check-options.js +2 -0
- package/dist/check-options.js.map +1 -0
- package/dist/code-frame.d.ts +17 -0
- package/dist/code-frame.d.ts.map +1 -0
- package/dist/code-frame.js +32 -0
- package/dist/code-frame.js.map +1 -0
- package/dist/combinators.d.ts +55 -0
- package/dist/combinators.d.ts.map +1 -0
- package/dist/combinators.js +43 -0
- package/dist/combinators.js.map +1 -0
- package/dist/condition.d.ts +56 -0
- package/dist/condition.d.ts.map +1 -0
- package/dist/condition.js +2 -0
- package/dist/condition.js.map +1 -0
- package/dist/correspondence.d.ts +78 -0
- package/dist/correspondence.d.ts.map +1 -0
- package/dist/correspondence.js +127 -0
- package/dist/correspondence.js.map +1 -0
- package/dist/define.d.ts +41 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +42 -0
- package/dist/define.js.map +1 -0
- package/dist/diff-aware.d.ts +37 -0
- package/dist/diff-aware.d.ts.map +1 -0
- package/dist/diff-aware.js +69 -0
- package/dist/diff-aware.js.map +1 -0
- package/dist/environment.d.ts +14 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +20 -0
- package/dist/environment.js.map +1 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +21 -0
- package/dist/errors.js.map +1 -0
- package/dist/exclusion-comments.d.ts +52 -0
- package/dist/exclusion-comments.d.ts.map +1 -0
- package/dist/exclusion-comments.js +183 -0
- package/dist/exclusion-comments.js.map +1 -0
- package/dist/execute-rule.d.ts +31 -0
- package/dist/execute-rule.d.ts.map +1 -0
- package/dist/execute-rule.js +119 -0
- package/dist/execute-rule.js.map +1 -0
- package/dist/format-github.d.ts +25 -0
- package/dist/format-github.d.ts.map +1 -0
- package/dist/format-github.js +44 -0
- package/dist/format-github.js.map +1 -0
- package/dist/format-json.d.ts +12 -0
- package/dist/format-json.d.ts.map +1 -0
- package/dist/format-json.js +30 -0
- package/dist/format-json.js.map +1 -0
- package/dist/format.d.ts +25 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +66 -0
- package/dist/format.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/matching.d.ts +31 -0
- package/dist/matching.d.ts.map +1 -0
- package/dist/matching.js +64 -0
- package/dist/matching.js.map +1 -0
- package/dist/predicate.d.ts +11 -0
- package/dist/predicate.d.ts.map +1 -0
- package/dist/predicate.js +2 -0
- package/dist/predicate.js.map +1 -0
- package/dist/preset-dispatch.d.ts +46 -0
- package/dist/preset-dispatch.d.ts.map +1 -0
- package/dist/preset-dispatch.js +48 -0
- package/dist/preset-dispatch.js.map +1 -0
- package/dist/report.d.ts +38 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +45 -0
- package/dist/report.js.map +1 -0
- package/dist/rule-builder.d.ts +188 -0
- package/dist/rule-builder.d.ts.map +1 -0
- package/dist/rule-builder.js +323 -0
- package/dist/rule-builder.js.map +1 -0
- package/dist/rule-description.d.ts +12 -0
- package/dist/rule-description.d.ts.map +1 -0
- package/dist/rule-description.js +2 -0
- package/dist/rule-description.js.map +1 -0
- package/dist/rule-metadata.d.ts +17 -0
- package/dist/rule-metadata.d.ts.map +1 -0
- package/dist/rule-metadata.js +2 -0
- package/dist/rule-metadata.js.map +1 -0
- package/dist/silent-exclusion.d.ts +38 -0
- package/dist/silent-exclusion.d.ts.map +1 -0
- package/dist/silent-exclusion.js +30 -0
- package/dist/silent-exclusion.js.map +1 -0
- package/dist/terminal-builder.d.ts +83 -0
- package/dist/terminal-builder.d.ts.map +1 -0
- package/dist/terminal-builder.js +134 -0
- package/dist/terminal-builder.js.map +1 -0
- package/dist/violation.d.ts +51 -0
- package/dist/violation.d.ts.map +1 -0
- package/dist/violation.js +2 -0
- package/dist/violation.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { isSilent } from './silent-exclusion.js';
|
|
2
|
+
import { executeCheck, executeWarn, applyFilters } from './execute-rule.js';
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for builders that share the terminal method pattern
|
|
5
|
+
* (because, rule, excluding, check, warn, severity) but have different
|
|
6
|
+
* element collection and evaluation models.
|
|
7
|
+
*
|
|
8
|
+
* Used by SliceRuleBuilder, SchemaRuleBuilder, ResolverRuleBuilder,
|
|
9
|
+
* PairFinalBuilder, and SmellBuilder — all of which implement the same
|
|
10
|
+
* terminal methods but differ in how they collect and evaluate elements.
|
|
11
|
+
*
|
|
12
|
+
* RuleBuilder<T> does NOT extend this because it predates it and has
|
|
13
|
+
* additional concerns (predicate/condition pipeline, fork semantics).
|
|
14
|
+
*/
|
|
15
|
+
export class TerminalBuilder {
|
|
16
|
+
_reason;
|
|
17
|
+
_metadata;
|
|
18
|
+
_exclusions = [];
|
|
19
|
+
_silentIndices = new Set();
|
|
20
|
+
/**
|
|
21
|
+
* Attach a human-readable rationale to the rule.
|
|
22
|
+
* Included in violation messages when `.check()` throws.
|
|
23
|
+
*/
|
|
24
|
+
because(reason) {
|
|
25
|
+
this._reason = reason;
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Attach rich metadata to the rule.
|
|
30
|
+
* Provides educational context in violation output: why, how to fix, docs link.
|
|
31
|
+
*
|
|
32
|
+
* If `metadata.because` is set, it also sets the reason (same as `.because()`).
|
|
33
|
+
*/
|
|
34
|
+
rule(metadata) {
|
|
35
|
+
this._metadata = metadata;
|
|
36
|
+
if (metadata.because) {
|
|
37
|
+
this._reason = metadata.because;
|
|
38
|
+
}
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Exclude specific elements from violation reporting.
|
|
43
|
+
*
|
|
44
|
+
* Matched violations are silently suppressed. Use for permanent,
|
|
45
|
+
* intentional exceptions — not for temporary violations (use baseline for those).
|
|
46
|
+
*
|
|
47
|
+
* Matches against the violation's `element` field.
|
|
48
|
+
* Supports exact strings and regex patterns.
|
|
49
|
+
*
|
|
50
|
+
* Emits a warning if an exclusion matches zero violations (stale exclusion).
|
|
51
|
+
*/
|
|
52
|
+
excluding(...patterns) {
|
|
53
|
+
for (const p of patterns) {
|
|
54
|
+
if (isSilent(p)) {
|
|
55
|
+
this._exclusions.push(p.pattern);
|
|
56
|
+
this._silentIndices.add(this._exclusions.length - 1);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
this._exclusions.push(p);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Return a structured description of this rule without executing it.
|
|
66
|
+
* Used by the `explain` CLI subcommand.
|
|
67
|
+
*/
|
|
68
|
+
describeRule() {
|
|
69
|
+
return {
|
|
70
|
+
rule: this._metadata?.id ?? 'unnamed',
|
|
71
|
+
id: this._metadata?.id,
|
|
72
|
+
because: this._reason,
|
|
73
|
+
suggestion: this._metadata?.suggestion,
|
|
74
|
+
docs: this._metadata?.docs,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Execute the rule and return violations after exclusion filtering.
|
|
79
|
+
* Does not throw — use for programmatic access (presets, aggregation).
|
|
80
|
+
*/
|
|
81
|
+
violations() {
|
|
82
|
+
const raw = this.collectViolations();
|
|
83
|
+
return applyFilters(raw, {
|
|
84
|
+
reason: this._reason,
|
|
85
|
+
metadata: this._metadata,
|
|
86
|
+
exclusions: this._exclusions,
|
|
87
|
+
silentIndices: this._silentIndices,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Execute the rule and throw `ArchRuleError` if any violations are found.
|
|
92
|
+
* This is the primary terminal method — use in test assertions.
|
|
93
|
+
*
|
|
94
|
+
* @param options - Optional baseline, diff filtering, and output format
|
|
95
|
+
*/
|
|
96
|
+
check(options) {
|
|
97
|
+
const violations = this.collectViolations();
|
|
98
|
+
executeCheck(violations, {
|
|
99
|
+
reason: this._reason,
|
|
100
|
+
metadata: this._metadata,
|
|
101
|
+
exclusions: this._exclusions,
|
|
102
|
+
silentIndices: this._silentIndices,
|
|
103
|
+
}, options);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Execute the rule and log violations to stderr. Does not throw.
|
|
107
|
+
* Use for rules that should warn but not fail CI.
|
|
108
|
+
*
|
|
109
|
+
* @param options - Optional baseline, diff filtering, and output format
|
|
110
|
+
*/
|
|
111
|
+
warn(options) {
|
|
112
|
+
const violations = this.collectViolations();
|
|
113
|
+
executeWarn(violations, {
|
|
114
|
+
reason: this._reason,
|
|
115
|
+
metadata: this._metadata,
|
|
116
|
+
exclusions: this._exclusions,
|
|
117
|
+
silentIndices: this._silentIndices,
|
|
118
|
+
}, options);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Execute the rule with the given severity.
|
|
122
|
+
* `.severity('error')` is equivalent to `.check()`.
|
|
123
|
+
* `.severity('warn')` is equivalent to `.warn()`.
|
|
124
|
+
*/
|
|
125
|
+
severity(level) {
|
|
126
|
+
if (level === 'error') {
|
|
127
|
+
this.check();
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
this.warn();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=terminal-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-builder.js","sourceRoot":"","sources":["../src/terminal-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single architecture rule violation.
|
|
3
|
+
*
|
|
4
|
+
* Represents one element that failed to satisfy a condition. This is the
|
|
5
|
+
* kernel's central data type — dialect-independent. Each dialect provides its
|
|
6
|
+
* own adapter that builds an `ArchViolation` from that dialect's element type
|
|
7
|
+
* (e.g. the TS dialect builds one from a ts-morph `Node`).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* A deterministic, unique text edit that repairs a violation (plan 0066). Emitted
|
|
11
|
+
* by a condition ONLY when the fix is provably unambiguous (e.g. a broken link
|
|
12
|
+
* whose target resolves to exactly one file); ambiguous or judgment cases carry
|
|
13
|
+
* no fix and are reported instead. `applyFixes` writes these.
|
|
14
|
+
*/
|
|
15
|
+
export interface ArchFix {
|
|
16
|
+
/** Absolute path of the file to edit. */
|
|
17
|
+
file: string;
|
|
18
|
+
/** 0-based character offset of the start of the span to replace. */
|
|
19
|
+
start: number;
|
|
20
|
+
/** 0-based character offset of the end of the span (exclusive). */
|
|
21
|
+
end: number;
|
|
22
|
+
/** Replacement text for `[start, end)`. */
|
|
23
|
+
replacement: string;
|
|
24
|
+
/** One-line human description, e.g. 'rewrite link → work/plans/completed/0009.md'. */
|
|
25
|
+
describe: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ArchViolation {
|
|
28
|
+
/** Human-readable rule description (from the fluent chain) */
|
|
29
|
+
rule: string;
|
|
30
|
+
/** Unique rule identifier from .rule({ id }) */
|
|
31
|
+
ruleId?: string;
|
|
32
|
+
/** Element identifier, e.g. "OrderService.getTotal()" or "parseConfig" */
|
|
33
|
+
element: string;
|
|
34
|
+
/** Absolute file path where the violation occurs */
|
|
35
|
+
file: string;
|
|
36
|
+
/** Line number where the violating element starts */
|
|
37
|
+
line: number;
|
|
38
|
+
/** Human-readable description of what went wrong */
|
|
39
|
+
message: string;
|
|
40
|
+
/** Optional rationale provided via .because() */
|
|
41
|
+
because?: string;
|
|
42
|
+
/** Source code snippet around the violation line */
|
|
43
|
+
codeFrame?: string;
|
|
44
|
+
/** Actionable suggestion for fixing the violation (e.g. "Replace parseInt() with this.extractCount()") */
|
|
45
|
+
suggestion?: string;
|
|
46
|
+
/** Link to documentation — ADR, wiki, style guide */
|
|
47
|
+
docs?: string;
|
|
48
|
+
/** A deterministic, unique text edit that repairs this violation (plan 0066). */
|
|
49
|
+
fix?: ArchFix;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=violation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"violation.d.ts","sourceRoot":"","sources":["../src/violation.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAA;IACb,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAA;IACX,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAA;IACnB,sFAAsF;IACtF,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAA;IACf,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAA;IACZ,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAA;IACZ,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAA;IACf,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0GAA0G;IAC1G,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iFAAiF;IACjF,GAAG,CAAC,EAAE,OAAO,CAAA;CACd"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"violation.js","sourceRoot":"","sources":["../src/violation.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nielspeter/eess",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "eess kernel — the dialect-independent rule engine (RuleBuilder, Predicate, Condition, baseline, formatters). Specifications you can run.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=24.0.0"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/nielspeter/eess.git",
|
|
23
|
+
"directory": "packages/core"
|
|
24
|
+
},
|
|
25
|
+
"author": "Niels Peter",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"scripts": {
|
|
28
|
+
"prepublishOnly": "npm run build",
|
|
29
|
+
"build": "tsc -p tsconfig.build.json",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"test:watch": "vitest"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"eess",
|
|
36
|
+
"architecture-testing",
|
|
37
|
+
"rule-engine",
|
|
38
|
+
"specification"
|
|
39
|
+
]
|
|
40
|
+
}
|