@comity-dev/validate 0.1.2 → 0.2.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/dist/run.js ADDED
@@ -0,0 +1,144 @@
1
+ import { dirname, resolve } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { discoverRepository } from "./discover.js";
4
+ import { runAdapterPeers } from "./engines/adapter-peers.js";
5
+ import { runDepcruise } from "./engines/depcruise.js";
6
+ import { runEslint } from "./engines/eslint.js";
7
+ import { runSchema } from "./engines/schema.js";
8
+ import { runSemgrep } from "./engines/semgrep.js";
9
+ function categoryOf(result) {
10
+ return {
11
+ status: result.status,
12
+ executed: result.executed,
13
+ exitCode: result.exitCode,
14
+ passed: result.passed,
15
+ findings: result.findings.length,
16
+ tool: result.tool,
17
+ reason: result.reason,
18
+ };
19
+ }
20
+ function emptyCategory(reason) {
21
+ return {
22
+ status: "NOT-RUN",
23
+ executed: false,
24
+ exitCode: null,
25
+ passed: false,
26
+ findings: 0,
27
+ reason,
28
+ };
29
+ }
30
+ function findBinDir() {
31
+ const __dirname = dirname(fileURLToPath(import.meta.url));
32
+ // `__dirname` is the directory of the running module. Both the source
33
+ // `src/` and the built `dist/` are direct children of the package root,
34
+ // so the package's own `node_modules/.bin` is always exactly one level
35
+ // up from the running module.
36
+ return resolve(__dirname, "..", "node_modules", ".bin");
37
+ }
38
+ /**
39
+ * Run validation against a repository. Returns a normalized result.
40
+ *
41
+ * Every category reports either an executed engine with its real exit
42
+ * code, or an explicit NOT-RUN / TOOL-UNAVAILABLE / CONFIGURATION-ERROR
43
+ * state. PASS without execution is impossible.
44
+ */
45
+ export async function runValidation(options) {
46
+ const only = options.only ?? null;
47
+ const repo = await discoverRepository({ root: options.root });
48
+ const binDir = findBinDir();
49
+ let schemaResult;
50
+ let metaResult;
51
+ let configResult;
52
+ if (!only || only === "metadata" || only === "config" || only === "schema") {
53
+ schemaResult = runSchema(repo);
54
+ const metaFindings = schemaResult.findings.filter((f) => f.rule === "package-metadata");
55
+ const configFindings = schemaResult.findings.filter((f) => f.rule === "comity-config");
56
+ metaResult = {
57
+ ...schemaResult,
58
+ findings: metaFindings,
59
+ passed: metaFindings.length === 0,
60
+ status: metaFindings.length === 0 ? "PASS" : "FAIL",
61
+ };
62
+ configResult = {
63
+ ...schemaResult,
64
+ findings: configFindings,
65
+ passed: configFindings.length === 0,
66
+ status: configFindings.length === 0 ? "PASS" : "FAIL",
67
+ };
68
+ }
69
+ else {
70
+ schemaResult = emptyEngineResult("schema engine skipped");
71
+ metaResult = emptyEngineResult("schema engine skipped");
72
+ configResult = emptyEngineResult("schema engine skipped");
73
+ }
74
+ let depResult;
75
+ if (!only || only === "dependencies" || only === "depcruise") {
76
+ depResult = runDepcruise(repo, binDir);
77
+ }
78
+ else {
79
+ depResult = emptyEngineResult("dependencies engine skipped");
80
+ }
81
+ let eslintResult;
82
+ if (!only || only === "eslint") {
83
+ eslintResult = runEslint(repo, binDir);
84
+ }
85
+ else {
86
+ eslintResult = emptyEngineResult("eslint engine skipped");
87
+ }
88
+ let semgrepResult;
89
+ if (!only || only === "semgrep") {
90
+ semgrepResult = await runSemgrep(repo);
91
+ }
92
+ else {
93
+ semgrepResult = emptyEngineResult("semgrep engine skipped");
94
+ }
95
+ let adapterResult;
96
+ if (!only || only === "adapter-peers") {
97
+ adapterResult = runAdapterPeers(repo);
98
+ }
99
+ else {
100
+ adapterResult = emptyEngineResult("adapter-peers engine skipped");
101
+ }
102
+ const violations = [];
103
+ for (const r of [
104
+ schemaResult,
105
+ depResult,
106
+ eslintResult,
107
+ semgrepResult,
108
+ adapterResult,
109
+ ]) {
110
+ if (Array.isArray(r.findings)) {
111
+ violations.push(...r.findings);
112
+ }
113
+ }
114
+ const allExecuted = [depResult, eslintResult, semgrepResult, adapterResult];
115
+ const allPassed = allExecuted.every((r) => (r.executed ? r.passed : r.status !== "FAIL")) &&
116
+ (metaResult.executed ? metaResult.passed : metaResult.status !== "FAIL") &&
117
+ (configResult.executed
118
+ ? configResult.passed
119
+ : configResult.status !== "FAIL");
120
+ return {
121
+ passed: allPassed,
122
+ violations,
123
+ categories: {
124
+ schema: categoryOf(schemaResult),
125
+ metadata: categoryOf(metaResult),
126
+ config: categoryOf(configResult),
127
+ dependencies: categoryOf(depResult),
128
+ eslint: categoryOf(eslintResult),
129
+ semgrep: categoryOf(semgrepResult),
130
+ adapterPeers: categoryOf(adapterResult),
131
+ },
132
+ };
133
+ }
134
+ function emptyEngineResult(reason) {
135
+ return {
136
+ executed: false,
137
+ exitCode: null,
138
+ passed: false,
139
+ findings: [],
140
+ duration: 0,
141
+ status: "NOT-RUN",
142
+ reason,
143
+ };
144
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comity-dev/validate",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Thin orchestrator over Comity shared validation tooling. Development tooling.",
5
5
  "type": "module",
6
6
  "private": false,
@@ -34,10 +34,10 @@
34
34
  "@typescript-eslint/parser": "^8.69.0",
35
35
  "dependency-cruiser": "^16.10.4",
36
36
  "eslint": "^9.39.5",
37
- "@comity-dev/schemas": "0.1.1",
38
- "@comity-dev/dependency-rules": "0.1.1",
39
- "@comity-dev/eslint-plugin": "0.1.2",
40
- "@comity-dev/semgrep-rules": "0.1.2"
37
+ "@comity-dev/schemas": "0.2.0",
38
+ "@comity-dev/dependency-rules": "0.2.0",
39
+ "@comity-dev/eslint-plugin": "0.2.0",
40
+ "@comity-dev/semgrep-rules": "0.2.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^24.13.3",