@cisco_open/linting-orchestrator 1.0.0-rc.4
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 +201 -0
- package/NOTICE +5 -0
- package/README.md +43 -0
- package/build/cli/api-client.d.ts +170 -0
- package/build/cli/api-client.d.ts.map +1 -0
- package/build/cli/api-client.js +284 -0
- package/build/cli/api-client.js.map +1 -0
- package/build/cli/commands/agents.d.ts +7 -0
- package/build/cli/commands/agents.d.ts.map +1 -0
- package/build/cli/commands/agents.js +694 -0
- package/build/cli/commands/agents.js.map +1 -0
- package/build/cli/commands/completion.d.ts +9 -0
- package/build/cli/commands/completion.d.ts.map +1 -0
- package/build/cli/commands/completion.js +177 -0
- package/build/cli/commands/completion.js.map +1 -0
- package/build/cli/commands/config.d.ts +10 -0
- package/build/cli/commands/config.d.ts.map +1 -0
- package/build/cli/commands/config.js +284 -0
- package/build/cli/commands/config.js.map +1 -0
- package/build/cli/commands/health.d.ts +11 -0
- package/build/cli/commands/health.d.ts.map +1 -0
- package/build/cli/commands/health.js +38 -0
- package/build/cli/commands/health.js.map +1 -0
- package/build/cli/commands/help.d.ts +6 -0
- package/build/cli/commands/help.d.ts.map +1 -0
- package/build/cli/commands/help.js +20 -0
- package/build/cli/commands/help.js.map +1 -0
- package/build/cli/commands/history.d.ts +11 -0
- package/build/cli/commands/history.d.ts.map +1 -0
- package/build/cli/commands/history.js +50 -0
- package/build/cli/commands/history.js.map +1 -0
- package/build/cli/commands/jobs.d.ts +12 -0
- package/build/cli/commands/jobs.d.ts.map +1 -0
- package/build/cli/commands/jobs.js +84 -0
- package/build/cli/commands/jobs.js.map +1 -0
- package/build/cli/commands/lint.d.ts +15 -0
- package/build/cli/commands/lint.d.ts.map +1 -0
- package/build/cli/commands/lint.js +384 -0
- package/build/cli/commands/lint.js.map +1 -0
- package/build/cli/commands/ps.d.ts +8 -0
- package/build/cli/commands/ps.d.ts.map +1 -0
- package/build/cli/commands/ps.js +74 -0
- package/build/cli/commands/ps.js.map +1 -0
- package/build/cli/commands/reproduce.d.ts +9 -0
- package/build/cli/commands/reproduce.d.ts.map +1 -0
- package/build/cli/commands/reproduce.js +31 -0
- package/build/cli/commands/reproduce.js.map +1 -0
- package/build/cli/commands/reset.d.ts +5 -0
- package/build/cli/commands/reset.d.ts.map +1 -0
- package/build/cli/commands/reset.js +13 -0
- package/build/cli/commands/reset.js.map +1 -0
- package/build/cli/commands/results.d.ts +13 -0
- package/build/cli/commands/results.d.ts.map +1 -0
- package/build/cli/commands/results.js +129 -0
- package/build/cli/commands/results.js.map +1 -0
- package/build/cli/commands/rulesets/check.d.ts +12 -0
- package/build/cli/commands/rulesets/check.d.ts.map +1 -0
- package/build/cli/commands/rulesets/check.js +226 -0
- package/build/cli/commands/rulesets/check.js.map +1 -0
- package/build/cli/commands/rulesets/index.d.ts +5 -0
- package/build/cli/commands/rulesets/index.d.ts.map +1 -0
- package/build/cli/commands/rulesets/index.js +6 -0
- package/build/cli/commands/rulesets/index.js.map +1 -0
- package/build/cli/commands/rulesets/view.d.ts +16 -0
- package/build/cli/commands/rulesets/view.d.ts.map +1 -0
- package/build/cli/commands/rulesets/view.js +100 -0
- package/build/cli/commands/rulesets/view.js.map +1 -0
- package/build/cli/commands/start.d.ts +16 -0
- package/build/cli/commands/start.d.ts.map +1 -0
- package/build/cli/commands/start.js +167 -0
- package/build/cli/commands/start.js.map +1 -0
- package/build/cli/commands/status.d.ts +9 -0
- package/build/cli/commands/status.d.ts.map +1 -0
- package/build/cli/commands/status.js +46 -0
- package/build/cli/commands/status.js.map +1 -0
- package/build/cli/commands/stop.d.ts +11 -0
- package/build/cli/commands/stop.d.ts.map +1 -0
- package/build/cli/commands/stop.js +78 -0
- package/build/cli/commands/stop.js.map +1 -0
- package/build/cli/config-manager.d.ts +134 -0
- package/build/cli/config-manager.d.ts.map +1 -0
- package/build/cli/config-manager.js +288 -0
- package/build/cli/config-manager.js.map +1 -0
- package/build/cli/formatters.d.ts +62 -0
- package/build/cli/formatters.d.ts.map +1 -0
- package/build/cli/formatters.js +715 -0
- package/build/cli/formatters.js.map +1 -0
- package/build/cli/history-manager.d.ts +97 -0
- package/build/cli/history-manager.d.ts.map +1 -0
- package/build/cli/history-manager.js +201 -0
- package/build/cli/history-manager.js.map +1 -0
- package/build/cli/index.d.ts +16 -0
- package/build/cli/index.d.ts.map +1 -0
- package/build/cli/index.js +335 -0
- package/build/cli/index.js.map +1 -0
- package/build/cli/list-rulesets.d.ts +15 -0
- package/build/cli/list-rulesets.d.ts.map +1 -0
- package/build/cli/list-rulesets.js +193 -0
- package/build/cli/list-rulesets.js.map +1 -0
- package/build/cli/utils/connection-error.d.ts +9 -0
- package/build/cli/utils/connection-error.d.ts.map +1 -0
- package/build/cli/utils/connection-error.js +30 -0
- package/build/cli/utils/connection-error.js.map +1 -0
- package/build/cli/utils/embedded-server.d.ts +21 -0
- package/build/cli/utils/embedded-server.d.ts.map +1 -0
- package/build/cli/utils/embedded-server.js +61 -0
- package/build/cli/utils/embedded-server.js.map +1 -0
- package/build/cli/utils/mode-validator.d.ts +13 -0
- package/build/cli/utils/mode-validator.d.ts.map +1 -0
- package/build/cli/utils/mode-validator.js +31 -0
- package/build/cli/utils/mode-validator.js.map +1 -0
- package/build/cli/utils/port-checker.d.ts +20 -0
- package/build/cli/utils/port-checker.d.ts.map +1 -0
- package/build/cli/utils/port-checker.js +49 -0
- package/build/cli/utils/port-checker.js.map +1 -0
- package/build/config.d.ts +57 -0
- package/build/config.d.ts.map +1 -0
- package/build/config.js +527 -0
- package/build/config.js.map +1 -0
- package/build/document-accessor.d.ts +79 -0
- package/build/document-accessor.d.ts.map +1 -0
- package/build/document-accessor.js +148 -0
- package/build/document-accessor.js.map +1 -0
- package/build/formatters/reproduce-markdown.d.ts +14 -0
- package/build/formatters/reproduce-markdown.d.ts.map +1 -0
- package/build/formatters/reproduce-markdown.js +182 -0
- package/build/formatters/reproduce-markdown.js.map +1 -0
- package/build/formatters/sarif-builder.d.ts +86 -0
- package/build/formatters/sarif-builder.d.ts.map +1 -0
- package/build/formatters/sarif-builder.js +276 -0
- package/build/formatters/sarif-builder.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +174 -0
- package/build/index.js.map +1 -0
- package/build/logger.d.ts +38 -0
- package/build/logger.d.ts.map +1 -0
- package/build/logger.js +105 -0
- package/build/logger.js.map +1 -0
- package/build/mock-server.d.ts +2 -0
- package/build/mock-server.d.ts.map +1 -0
- package/build/mock-server.js +290 -0
- package/build/mock-server.js.map +1 -0
- package/build/orchestrator.d.ts +149 -0
- package/build/orchestrator.d.ts.map +1 -0
- package/build/orchestrator.js +874 -0
- package/build/orchestrator.js.map +1 -0
- package/build/ruleset-loader.d.ts +79 -0
- package/build/ruleset-loader.d.ts.map +1 -0
- package/build/ruleset-loader.js +514 -0
- package/build/ruleset-loader.js.map +1 -0
- package/build/schemas.d.ts +2568 -0
- package/build/schemas.d.ts.map +1 -0
- package/build/schemas.js +674 -0
- package/build/schemas.js.map +1 -0
- package/build/server.d.ts +39 -0
- package/build/server.d.ts.map +1 -0
- package/build/server.js +834 -0
- package/build/server.js.map +1 -0
- package/build/storage/memory-storage.d.ts +190 -0
- package/build/storage/memory-storage.d.ts.map +1 -0
- package/build/storage/memory-storage.js +629 -0
- package/build/storage/memory-storage.js.map +1 -0
- package/build/storage/redis-storage.d.ts +134 -0
- package/build/storage/redis-storage.d.ts.map +1 -0
- package/build/storage/redis-storage.js +236 -0
- package/build/storage/redis-storage.js.map +1 -0
- package/build/storage/storage-adapter.d.ts +189 -0
- package/build/storage/storage-adapter.d.ts.map +1 -0
- package/build/storage/storage-adapter.js +36 -0
- package/build/storage/storage-adapter.js.map +1 -0
- package/build/types.d.ts +981 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +5 -0
- package/build/types.js.map +1 -0
- package/build/utils/version.d.ts +40 -0
- package/build/utils/version.d.ts.map +1 -0
- package/build/utils/version.js +94 -0
- package/build/utils/version.js.map +1 -0
- package/build/validation.d.ts +95 -0
- package/build/validation.d.ts.map +1 -0
- package/build/validation.js +150 -0
- package/build/validation.js.map +1 -0
- package/build/worker-pool.d.ts +137 -0
- package/build/worker-pool.d.ts.map +1 -0
- package/build/worker-pool.js +549 -0
- package/build/worker-pool.js.map +1 -0
- package/build/worker.d.ts +2 -0
- package/build/worker.d.ts.map +1 -0
- package/build/worker.js +427 -0
- package/build/worker.js.map +1 -0
- package/package.json +110 -0
- package/rulesets/CHANGELOG.md +25 -0
- package/rulesets/config/rulesets.yaml +96 -0
- package/rulesets/sources/README.md +47 -0
- package/rulesets/sources/example/oas-recommended/v1.0.0/ruleset.yaml +6 -0
- package/rulesets/sources/example/oas-recommended/v2.0.0/ruleset.yaml +14 -0
package/build/worker.js
ADDED
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
// Copyright 2026 Cisco Systems, Inc. and its affiliates
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
/**
|
|
5
|
+
* Worker Thread Implementation
|
|
6
|
+
*
|
|
7
|
+
* Each worker is dedicated to a specific ruleset and maintains:
|
|
8
|
+
* - Pre-loaded Spectral ruleset for fast execution
|
|
9
|
+
* - Document cache (LRU, 1 document) for repeated linting
|
|
10
|
+
* - Health monitoring and status reporting
|
|
11
|
+
*
|
|
12
|
+
* Architecture:
|
|
13
|
+
* - Zero-copy: Receives document file paths, not content
|
|
14
|
+
* - Stateful: Pre-loaded ruleset stays in memory
|
|
15
|
+
* - Cached: Last document cached for reuse
|
|
16
|
+
*
|
|
17
|
+
* @module worker
|
|
18
|
+
*/
|
|
19
|
+
import { parentPort, workerData } from 'worker_threads';
|
|
20
|
+
import pkg from '@stoplight/spectral-core';
|
|
21
|
+
const { Spectral, Ruleset } = pkg;
|
|
22
|
+
// @ts-ignore - ESM export resolution issue with TypeScript
|
|
23
|
+
import { bundleAndLoadRuleset } from '@stoplight/spectral-ruleset-bundler/with-loader';
|
|
24
|
+
import fs from 'fs/promises';
|
|
25
|
+
import { pathToFileURL } from 'url';
|
|
26
|
+
// ============================================
|
|
27
|
+
// Worker State
|
|
28
|
+
// ============================================
|
|
29
|
+
let spectral = null; // Spectral instance (any to avoid CommonJS/ESM type issues)
|
|
30
|
+
let initData;
|
|
31
|
+
let workerStatus = 'initializing';
|
|
32
|
+
// Document cache (LRU, 1 document)
|
|
33
|
+
let cachedDocument = null;
|
|
34
|
+
let cachedDocumentId = null;
|
|
35
|
+
let cachedAt = null;
|
|
36
|
+
let cacheSize = 0;
|
|
37
|
+
// Performance tracking
|
|
38
|
+
let taskCount = 0;
|
|
39
|
+
let totalExecutionTime = 0;
|
|
40
|
+
let lastHeartbeat = new Date();
|
|
41
|
+
// ============================================
|
|
42
|
+
// Initialization
|
|
43
|
+
// ============================================
|
|
44
|
+
/**
|
|
45
|
+
* Initialize worker with pre-loaded Spectral ruleset
|
|
46
|
+
*/
|
|
47
|
+
async function initialize() {
|
|
48
|
+
try {
|
|
49
|
+
initData = workerData;
|
|
50
|
+
if (!initData || !initData.workerId || !initData.rulesetPath) {
|
|
51
|
+
throw new Error('Invalid worker initialization data');
|
|
52
|
+
}
|
|
53
|
+
// Validate ruleset file exists
|
|
54
|
+
try {
|
|
55
|
+
await fs.access(initData.rulesetPath);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
throw new Error(`Ruleset file not found: ${initData.rulesetPath}`);
|
|
59
|
+
}
|
|
60
|
+
// Load Spectral ruleset using whichever mechanism the catalogue
|
|
61
|
+
// entry's `loader` field selected. Defaults to `bundler` if absent.
|
|
62
|
+
// See ruleset-loader.ts for the same two-branch logic and rationale.
|
|
63
|
+
let ruleset;
|
|
64
|
+
const loaderKind = initData.rulesetLoader ?? 'bundler';
|
|
65
|
+
if (loaderKind === 'native') {
|
|
66
|
+
if (!/\.(js|cjs|mjs)$/i.test(initData.rulesetPath)) {
|
|
67
|
+
throw new Error(`loader: native only supports .js / .cjs / .mjs entrypoints, got: ${initData.rulesetPath}`);
|
|
68
|
+
}
|
|
69
|
+
const mod = await import(pathToFileURL(initData.rulesetPath).href);
|
|
70
|
+
const def = extractRulesetDef(mod);
|
|
71
|
+
if (!def || (!def.rules && !def.extends && !def.overrides)) {
|
|
72
|
+
throw new Error(`module at ${initData.rulesetPath} did not export a Spectral ruleset definition`);
|
|
73
|
+
}
|
|
74
|
+
ruleset = new Ruleset(def, { source: initData.rulesetPath });
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
ruleset = await bundleAndLoadRuleset(initData.rulesetPath, {
|
|
78
|
+
fs: { promises: fs },
|
|
79
|
+
fetch: fetch
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// Load custom resolver if configured
|
|
83
|
+
let resolverOpts = {};
|
|
84
|
+
if (initData.resolverPath) {
|
|
85
|
+
try {
|
|
86
|
+
const resolverModule = await import(pathToFileURL(initData.resolverPath).href);
|
|
87
|
+
const resolver = resolverModule.default ?? resolverModule;
|
|
88
|
+
resolverOpts = { resolver };
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
throw new Error(`Failed to load resolver from ${initData.resolverPath}: ${err.message}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Initialize Spectral with pre-loaded ruleset (and optional custom resolver)
|
|
95
|
+
spectral = new Spectral(resolverOpts);
|
|
96
|
+
spectral.setRuleset(ruleset);
|
|
97
|
+
workerStatus = 'ready';
|
|
98
|
+
lastHeartbeat = new Date();
|
|
99
|
+
// Notify main thread that worker is ready
|
|
100
|
+
sendMessage({
|
|
101
|
+
type: 'ready',
|
|
102
|
+
payload: {
|
|
103
|
+
workerId: initData.workerId,
|
|
104
|
+
rulesetName: initData.rulesetName,
|
|
105
|
+
rulesetVersion: initData.rulesetVersion,
|
|
106
|
+
timestamp: new Date().toISOString()
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
workerStatus = 'error';
|
|
112
|
+
sendMessage({
|
|
113
|
+
type: 'error',
|
|
114
|
+
payload: {
|
|
115
|
+
workerId: initData?.workerId || 'unknown',
|
|
116
|
+
phase: 'initialization',
|
|
117
|
+
error: error instanceof Error ? error.message : String(error),
|
|
118
|
+
stack: error instanceof Error ? error.stack : undefined
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// ============================================
|
|
125
|
+
// Task Execution
|
|
126
|
+
// ============================================
|
|
127
|
+
/**
|
|
128
|
+
* Execute Spectral rules on a document
|
|
129
|
+
*/
|
|
130
|
+
async function executeTask(msg) {
|
|
131
|
+
const { taskId, documentId, documentPath, timeout, ruleOverrides } = msg.payload;
|
|
132
|
+
const startTime = Date.now();
|
|
133
|
+
try {
|
|
134
|
+
if (!spectral) {
|
|
135
|
+
throw new Error('Spectral not initialized');
|
|
136
|
+
}
|
|
137
|
+
workerStatus = 'busy';
|
|
138
|
+
sendStatus();
|
|
139
|
+
// Check if document is in cache BEFORE loading
|
|
140
|
+
const wasCacheHit = cachedDocumentId === documentId;
|
|
141
|
+
// Load document (from cache or filesystem)
|
|
142
|
+
const document = await loadDocument(documentId, documentPath);
|
|
143
|
+
// Execute Spectral rules with timeout
|
|
144
|
+
const executionTimeout = timeout || initData.config.taskTimeout;
|
|
145
|
+
const results = await executeWithTimeout(() => spectral.run(document), executionTimeout); // Spectral returns unknown in some contexts
|
|
146
|
+
// Update performance metrics
|
|
147
|
+
const executionTime = Date.now() - startTime;
|
|
148
|
+
taskCount++;
|
|
149
|
+
totalExecutionTime += executionTime;
|
|
150
|
+
lastHeartbeat = new Date();
|
|
151
|
+
// Send results back to main thread
|
|
152
|
+
workerStatus = 'ready';
|
|
153
|
+
let formattedResults = (results || []).map(formatDiagnostic);
|
|
154
|
+
// Apply rule overrides (post-filter): exclude 'off' rules, remap severities
|
|
155
|
+
if (ruleOverrides && Object.keys(ruleOverrides).length > 0) {
|
|
156
|
+
formattedResults = applyRuleOverrides(formattedResults, ruleOverrides);
|
|
157
|
+
}
|
|
158
|
+
sendMessage({
|
|
159
|
+
type: 'result',
|
|
160
|
+
payload: {
|
|
161
|
+
taskId,
|
|
162
|
+
success: true,
|
|
163
|
+
results: formattedResults,
|
|
164
|
+
executionTime,
|
|
165
|
+
cacheHit: wasCacheHit,
|
|
166
|
+
timestamp: new Date().toISOString()
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
sendStatus();
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
const executionTime = Date.now() - startTime;
|
|
173
|
+
workerStatus = 'ready';
|
|
174
|
+
sendMessage({
|
|
175
|
+
type: 'result',
|
|
176
|
+
payload: {
|
|
177
|
+
taskId,
|
|
178
|
+
success: false,
|
|
179
|
+
error: error instanceof Error ? error.message : String(error),
|
|
180
|
+
executionTime,
|
|
181
|
+
timestamp: new Date().toISOString()
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
sendStatus();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Load document from cache or filesystem (zero-copy architecture)
|
|
189
|
+
*/
|
|
190
|
+
async function loadDocument(documentId, documentPath) {
|
|
191
|
+
// Check cache first
|
|
192
|
+
if (initData.config.documentCache.enabled && cachedDocumentId === documentId) {
|
|
193
|
+
// Check if cache is still valid
|
|
194
|
+
if (cachedAt && initData.config.documentCache.evictAfterMinutes > 0) {
|
|
195
|
+
const cacheAge = Date.now() - cachedAt.getTime();
|
|
196
|
+
const maxAge = initData.config.documentCache.evictAfterMinutes * 60 * 1000;
|
|
197
|
+
if (cacheAge > maxAge) {
|
|
198
|
+
// Cache expired, evict
|
|
199
|
+
evictCache();
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
// Cache hit! Return cached document
|
|
203
|
+
return cachedDocument;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
// Cache hit! Return cached document
|
|
208
|
+
return cachedDocument;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Cache miss - load from filesystem
|
|
212
|
+
try {
|
|
213
|
+
const content = await fs.readFile(documentPath, 'utf-8');
|
|
214
|
+
const document = JSON.parse(content);
|
|
215
|
+
// Cache document if enabled
|
|
216
|
+
if (initData.config.documentCache.enabled) {
|
|
217
|
+
cacheDocument(documentId, document);
|
|
218
|
+
}
|
|
219
|
+
return document;
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
throw new Error(`Failed to load document from ${documentPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Cache document in memory (LRU with 1 slot)
|
|
227
|
+
*/
|
|
228
|
+
function cacheDocument(documentId, document) {
|
|
229
|
+
// Evict old cache if exists
|
|
230
|
+
if (cachedDocumentId !== null) {
|
|
231
|
+
evictCache();
|
|
232
|
+
}
|
|
233
|
+
// Calculate document size (rough estimate)
|
|
234
|
+
const docSize = JSON.stringify(document).length;
|
|
235
|
+
// Check size limit
|
|
236
|
+
if (docSize > initData.config.documentCache.maxCacheSizePerWorker) {
|
|
237
|
+
// Document too large to cache
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
// Cache document
|
|
241
|
+
cachedDocument = document;
|
|
242
|
+
cachedDocumentId = documentId;
|
|
243
|
+
cachedAt = new Date();
|
|
244
|
+
cacheSize = docSize;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Evict cached document
|
|
248
|
+
*/
|
|
249
|
+
function evictCache() {
|
|
250
|
+
cachedDocument = null;
|
|
251
|
+
cachedDocumentId = null;
|
|
252
|
+
cachedAt = null;
|
|
253
|
+
cacheSize = 0;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Execute function with timeout
|
|
257
|
+
*/
|
|
258
|
+
async function executeWithTimeout(fn, timeoutMs) {
|
|
259
|
+
return new Promise((resolve, reject) => {
|
|
260
|
+
let timedOut = false;
|
|
261
|
+
const timer = setTimeout(() => {
|
|
262
|
+
timedOut = true;
|
|
263
|
+
const error = new Error(`Execution timeout after ${timeoutMs}ms`);
|
|
264
|
+
error.code = 'TIMEOUT'; // Mark as timeout error
|
|
265
|
+
reject(error);
|
|
266
|
+
}, timeoutMs);
|
|
267
|
+
fn()
|
|
268
|
+
.then(result => {
|
|
269
|
+
if (!timedOut) {
|
|
270
|
+
clearTimeout(timer);
|
|
271
|
+
resolve(result);
|
|
272
|
+
}
|
|
273
|
+
})
|
|
274
|
+
.catch(error => {
|
|
275
|
+
if (!timedOut) {
|
|
276
|
+
clearTimeout(timer);
|
|
277
|
+
reject(error);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Format Spectral diagnostic to our result format
|
|
284
|
+
*/
|
|
285
|
+
function formatDiagnostic(diagnostic) {
|
|
286
|
+
return {
|
|
287
|
+
code: diagnostic.code,
|
|
288
|
+
message: diagnostic.message,
|
|
289
|
+
severity: diagnostic.severity,
|
|
290
|
+
path: diagnostic.path,
|
|
291
|
+
range: diagnostic.range,
|
|
292
|
+
source: diagnostic.source
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Apply rule overrides to formatted diagnostics (post-filter).
|
|
297
|
+
* - 'off': remove the diagnostic entirely
|
|
298
|
+
* - severity level: remap the diagnostic's severity
|
|
299
|
+
*
|
|
300
|
+
* Severity mapping: error=0, warn=1, info=2, hint=3
|
|
301
|
+
*/
|
|
302
|
+
const SEVERITY_MAP = { error: 0, warn: 1, info: 2, hint: 3 };
|
|
303
|
+
function applyRuleOverrides(diagnostics, overrides) {
|
|
304
|
+
return diagnostics
|
|
305
|
+
.filter(d => overrides[d.code] !== 'off')
|
|
306
|
+
.map(d => {
|
|
307
|
+
const override = overrides[d.code];
|
|
308
|
+
if (override && override !== 'off' && SEVERITY_MAP[override] !== undefined) {
|
|
309
|
+
return { ...d, severity: SEVERITY_MAP[override] };
|
|
310
|
+
}
|
|
311
|
+
return d;
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
// ============================================
|
|
315
|
+
// Message Handling
|
|
316
|
+
// ============================================
|
|
317
|
+
/**
|
|
318
|
+
* Send message to main thread
|
|
319
|
+
*/
|
|
320
|
+
function sendMessage(message) {
|
|
321
|
+
if (parentPort) {
|
|
322
|
+
parentPort.postMessage(message);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Send status update to main thread
|
|
327
|
+
*/
|
|
328
|
+
function sendStatus() {
|
|
329
|
+
sendMessage({
|
|
330
|
+
type: 'status',
|
|
331
|
+
payload: {
|
|
332
|
+
workerId: initData.workerId,
|
|
333
|
+
status: workerStatus,
|
|
334
|
+
taskCount,
|
|
335
|
+
averageExecutionTime: taskCount > 0 ? totalExecutionTime / taskCount : 0,
|
|
336
|
+
cachedDocumentId,
|
|
337
|
+
cachedAt: cachedAt?.toISOString(),
|
|
338
|
+
cacheSize,
|
|
339
|
+
lastHeartbeat: lastHeartbeat.toISOString()
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Handle incoming messages from main thread
|
|
345
|
+
*/
|
|
346
|
+
function handleMessage(msg) {
|
|
347
|
+
switch (msg.type) {
|
|
348
|
+
case 'execute':
|
|
349
|
+
executeTask(msg).catch(error => {
|
|
350
|
+
sendMessage({
|
|
351
|
+
type: 'error',
|
|
352
|
+
payload: {
|
|
353
|
+
workerId: initData.workerId,
|
|
354
|
+
phase: 'execution',
|
|
355
|
+
error: error instanceof Error ? error.message : String(error)
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
break;
|
|
360
|
+
case 'evict-cache':
|
|
361
|
+
evictCache();
|
|
362
|
+
sendStatus();
|
|
363
|
+
break;
|
|
364
|
+
case 'shutdown':
|
|
365
|
+
workerStatus = 'terminated';
|
|
366
|
+
sendStatus();
|
|
367
|
+
process.exit(0);
|
|
368
|
+
break;
|
|
369
|
+
case 'ping':
|
|
370
|
+
lastHeartbeat = new Date();
|
|
371
|
+
sendMessage({
|
|
372
|
+
type: 'pong',
|
|
373
|
+
payload: {
|
|
374
|
+
workerId: initData.workerId,
|
|
375
|
+
timestamp: lastHeartbeat.toISOString()
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
break;
|
|
379
|
+
default:
|
|
380
|
+
sendMessage({
|
|
381
|
+
type: 'error',
|
|
382
|
+
payload: {
|
|
383
|
+
workerId: initData.workerId,
|
|
384
|
+
phase: 'message-handling',
|
|
385
|
+
error: `Unknown message type: ${msg.type}`
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
// ============================================
|
|
391
|
+
// Worker Entry Point
|
|
392
|
+
// ============================================
|
|
393
|
+
if (parentPort) {
|
|
394
|
+
// Set up message listener
|
|
395
|
+
parentPort.on('message', handleMessage);
|
|
396
|
+
// Start initialization
|
|
397
|
+
initialize().catch(error => {
|
|
398
|
+
console.error('[Worker] Initialization failed:', error);
|
|
399
|
+
process.exit(1);
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
console.error('[Worker] No parent port available - must be run as worker thread');
|
|
404
|
+
process.exit(1);
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Extract a Spectral ruleset definition from a Node module namespace.
|
|
408
|
+
* Mirrors `extractRulesetDef` in ruleset-loader.ts. Handles ESM default,
|
|
409
|
+
* CJS default, and Babel CJS double-wrap shapes.
|
|
410
|
+
*/
|
|
411
|
+
function extractRulesetDef(mod) {
|
|
412
|
+
if (!mod || typeof mod !== 'object')
|
|
413
|
+
return null;
|
|
414
|
+
const ns = mod;
|
|
415
|
+
let candidate = (ns.default ?? ns);
|
|
416
|
+
if (candidate
|
|
417
|
+
&& typeof candidate === 'object'
|
|
418
|
+
&& !('rules' in candidate)
|
|
419
|
+
&& !('extends' in candidate)
|
|
420
|
+
&& !('overrides' in candidate)
|
|
421
|
+
&& candidate.default
|
|
422
|
+
&& typeof candidate.default === 'object') {
|
|
423
|
+
candidate = candidate.default;
|
|
424
|
+
}
|
|
425
|
+
return candidate;
|
|
426
|
+
}
|
|
427
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cisco_open/linting-orchestrator",
|
|
3
|
+
"version": "1.0.0-rc.4",
|
|
4
|
+
"description": "Quality assurance for API specifications. An orchestrator daemon (spectifyd) and CLI (spectify) that run Spectral and custom rule engines at scale, with worker-per-ruleset architecture, document caching, and pluggable storage.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/cisco-open/linting-orchestrator.git",
|
|
8
|
+
"directory": "packages/orchestrator"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/cisco-open/linting-orchestrator#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/cisco-open/linting-orchestrator/issues"
|
|
13
|
+
},
|
|
14
|
+
"spectify": {
|
|
15
|
+
"components": {
|
|
16
|
+
"server": "1.0.0-rc.3",
|
|
17
|
+
"cli": "1.0.0-rc.3"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"type": "module",
|
|
21
|
+
"main": "build/index.js",
|
|
22
|
+
"bin": {
|
|
23
|
+
"spectify": "build/cli/index.js",
|
|
24
|
+
"spectifyd": "build/index.js"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc && chmod 755 build/index.js build/cli/index.js",
|
|
28
|
+
"rebuild": "rm -rf build && npm run build",
|
|
29
|
+
"dev": "tsx watch src/index.ts",
|
|
30
|
+
"start": "node build/index.js",
|
|
31
|
+
"mock": "tsx src/mock-server.ts",
|
|
32
|
+
"list-rulesets": "tsx src/cli/list-rulesets.ts",
|
|
33
|
+
"add-ruleset": "bash scripts/add-ruleset.sh",
|
|
34
|
+
"install-rulesets": "bash scripts/install-rulesets-dependencies.sh",
|
|
35
|
+
"check-rulesets": "bash scripts/check-rulesets-dependencies.sh",
|
|
36
|
+
"generate-openapi": "bash scripts/generate-openapi.sh",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"test:unit": "vitest run tests/unit",
|
|
39
|
+
"test:integration": "vitest run tests/integration/deployment-modes.test.ts tests/integration/loader-accessor.test.ts",
|
|
40
|
+
"test:mcp": "vitest run tests/integration/e2e.test.ts tests/integration/performance.test.ts",
|
|
41
|
+
"test:server": "vitest run tests/unit tests/integration/loader-accessor.test.ts tests/integration/deployment-modes.test.ts",
|
|
42
|
+
"test:cli": "vitest run tests/integration/cli-config.test.ts",
|
|
43
|
+
"test:integration:e2e": "vitest run tests/integration/e2e.test.ts",
|
|
44
|
+
"test:integration:loader": "vitest run tests/integration/loader-accessor.test.ts",
|
|
45
|
+
"test:integration:perf": "vitest run tests/integration/performance.test.ts",
|
|
46
|
+
"test:watch": "vitest --watch",
|
|
47
|
+
"test:coverage": "vitest run --coverage",
|
|
48
|
+
"lint": "tsc --noEmit",
|
|
49
|
+
"api-health": "curl -s -X GET http://localhost:3003/health | jq",
|
|
50
|
+
"api-stats": "curl -s -X GET http://localhost:3003/stats | jq",
|
|
51
|
+
"api-rulesets": "curl -s -X GET http://localhost:3003/rulesets | jq"
|
|
52
|
+
},
|
|
53
|
+
"keywords": [
|
|
54
|
+
"linting",
|
|
55
|
+
"spectral",
|
|
56
|
+
"orchestrator",
|
|
57
|
+
"api-quality",
|
|
58
|
+
"openapi",
|
|
59
|
+
"asyncapi",
|
|
60
|
+
"arazzo"
|
|
61
|
+
],
|
|
62
|
+
"author": "Cisco Systems, Inc.",
|
|
63
|
+
"license": "Apache-2.0",
|
|
64
|
+
"contributors": [
|
|
65
|
+
"DevNet Team"
|
|
66
|
+
],
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"@cisco_open/linting-document-store": "*",
|
|
69
|
+
"@cisco_open/linting-reports": "*",
|
|
70
|
+
"@fastify/swagger": "^9.7.0",
|
|
71
|
+
"@stoplight/spectral-cli": "^6.11.0",
|
|
72
|
+
"@stoplight/spectral-core": "^1.18.3",
|
|
73
|
+
"@stoplight/spectral-functions": "^1.7.2",
|
|
74
|
+
"@stoplight/spectral-rulesets": "1.22.2",
|
|
75
|
+
"chalk": "^5.3.0",
|
|
76
|
+
"cli-table3": "^0.6.3",
|
|
77
|
+
"commander": "^11.1.0",
|
|
78
|
+
"dotenv": "^17.2.3",
|
|
79
|
+
"fastify": "^5.8.2",
|
|
80
|
+
"inquirer": "^9.3.8",
|
|
81
|
+
"ora": "^8.0.1",
|
|
82
|
+
"yaml": "^2.3.4"
|
|
83
|
+
},
|
|
84
|
+
"devDependencies": {
|
|
85
|
+
"@types/inquirer": "^9.0.9",
|
|
86
|
+
"@types/node": "^20.11.0",
|
|
87
|
+
"tsx": "^4.7.0",
|
|
88
|
+
"typescript": "^5.3.3",
|
|
89
|
+
"vitest": "^4.0.18"
|
|
90
|
+
},
|
|
91
|
+
"files": [
|
|
92
|
+
"build",
|
|
93
|
+
"rulesets",
|
|
94
|
+
"LICENSE",
|
|
95
|
+
"NOTICE",
|
|
96
|
+
"README.md"
|
|
97
|
+
],
|
|
98
|
+
"publishConfig": {
|
|
99
|
+
"access": "public"
|
|
100
|
+
},
|
|
101
|
+
"engines": {
|
|
102
|
+
"node": ">=20.0.0"
|
|
103
|
+
},
|
|
104
|
+
"overrides": {
|
|
105
|
+
"minimatch": "^9.0.0",
|
|
106
|
+
"@stoplight/spectral-ruleset-bundler": {
|
|
107
|
+
"rollup": "^2.80.0"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Rulesets Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to bundled rulesets are documented in this file.
|
|
4
|
+
For orchestrator changes, see [../CHANGELOG.md](../CHANGELOG.md).
|
|
5
|
+
|
|
6
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [1.0.0-rc.4] - 2026-06-18
|
|
11
|
+
|
|
12
|
+
**Initial open-source release.**
|
|
13
|
+
|
|
14
|
+
First public release of the bundled rulesets under the Apache-2.0 license.
|
|
15
|
+
|
|
16
|
+
<!-- UPDATE ME with command: `markdown-toc -i CHANGELOG.md --maxdepth 2` -->
|
|
17
|
+
|
|
18
|
+
<!-- toc -->
|
|
19
|
+
|
|
20
|
+
- [[Unreleased]](#unreleased)
|
|
21
|
+
- [[1.1.0] - 2025-12-18](#110---2025-12-18)
|
|
22
|
+
- [[1.0.0] - 2025-11-20](#100---2025-11-20)
|
|
23
|
+
- [Versioning Policy](#versioning-policy)
|
|
24
|
+
|
|
25
|
+
<!-- tocstop -->
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Spectify Built-in Ruleset Configuration
|
|
2
|
+
#
|
|
3
|
+
# This is the MINIMAL built-in ruleset shipped with the Spectify orchestrator.
|
|
4
|
+
# It serves two purposes:
|
|
5
|
+
# 1. A fresh `spectifyd` install works out of the box — no external repo needed.
|
|
6
|
+
# 2. A concrete, tested example of the rulesets.yaml format.
|
|
7
|
+
#
|
|
8
|
+
# To supply your own ruleset catalogue, point Spectify at an external rulesets
|
|
9
|
+
# directory via the SPECTIFYD_RULESETS_DIR environment variable or the
|
|
10
|
+
# --rulesets-directory CLI flag. See:
|
|
11
|
+
# docs/maintainers/ruleset-externalization.md
|
|
12
|
+
#
|
|
13
|
+
# Architecture: Source Repositories → Configuration Layer → Exposed Rulesets
|
|
14
|
+
|
|
15
|
+
rulesets:
|
|
16
|
+
# ============================================================================
|
|
17
|
+
# Built-in: OpenAPI Recommended (YAML-only, no npm dependencies)
|
|
18
|
+
# ============================================================================
|
|
19
|
+
- name: oas-recommended
|
|
20
|
+
displayName: "OpenAPI Recommended"
|
|
21
|
+
category: validation
|
|
22
|
+
origin: external
|
|
23
|
+
description: >
|
|
24
|
+
Core OpenAPI 3.x validation rules built on Spectral's built-in OAS
|
|
25
|
+
ruleset, extended with a small set of opinionated quality rules.
|
|
26
|
+
No npm dependencies required.
|
|
27
|
+
tags:
|
|
28
|
+
- oas
|
|
29
|
+
- spectral
|
|
30
|
+
metadata:
|
|
31
|
+
team: "Spectify"
|
|
32
|
+
repository: "https://github.com/cisco-open/spectify"
|
|
33
|
+
license: "Apache-2.0"
|
|
34
|
+
documentation: ""
|
|
35
|
+
versions:
|
|
36
|
+
- version: "1.0.0"
|
|
37
|
+
sourceRepo: "example/oas-recommended"
|
|
38
|
+
sourceVersion: "v1.0.0"
|
|
39
|
+
entrypoint: "ruleset.yaml"
|
|
40
|
+
releaseDate: "2026-06-01"
|
|
41
|
+
deprecated: false
|
|
42
|
+
changelog: "Initial release. Extends spectral:oas recommended profile."
|
|
43
|
+
- version: "2.0.0"
|
|
44
|
+
sourceRepo: "example/oas-recommended"
|
|
45
|
+
sourceVersion: "v2.0.0"
|
|
46
|
+
entrypoint: "ruleset.yaml"
|
|
47
|
+
releaseDate: "2026-06-01"
|
|
48
|
+
deprecated: false
|
|
49
|
+
changelog: >
|
|
50
|
+
v2: adds operation-operationId, operation-tags, and
|
|
51
|
+
info-contact-email rules on top of the v1 base.
|
|
52
|
+
|
|
53
|
+
# ============================================================================
|
|
54
|
+
# Default Configuration
|
|
55
|
+
# ============================================================================
|
|
56
|
+
# Default versions for each ruleset.
|
|
57
|
+
# Should always point to stable, non-deprecated versions.
|
|
58
|
+
# "latest" resolves to the last non-deprecated entry in the versions array.
|
|
59
|
+
|
|
60
|
+
defaults:
|
|
61
|
+
oas-recommended: "2.0.0"
|
|
62
|
+
|
|
63
|
+
# ============================================================================
|
|
64
|
+
# Configuration Notes
|
|
65
|
+
# ============================================================================
|
|
66
|
+
#
|
|
67
|
+
# Adding a new ruleset:
|
|
68
|
+
# 1. Add source to: rulesets/sources/{sourceRepo}/{sourceVersion}/
|
|
69
|
+
# 2. Add configuration entry above with unique name
|
|
70
|
+
# 3. Set appropriate category, origin, and metadata
|
|
71
|
+
# 4. Add to defaults section
|
|
72
|
+
# 5. Restart Spectify service (or call cache refresh API when available)
|
|
73
|
+
#
|
|
74
|
+
# Updating an existing ruleset:
|
|
75
|
+
# 1. Add new source version to sources directory
|
|
76
|
+
# 2. Add new version entry under existing ruleset
|
|
77
|
+
# 3. Update defaults to point to new version (optional)
|
|
78
|
+
# 4. Mark old version as deprecated if needed (optional)
|
|
79
|
+
#
|
|
80
|
+
# For team-specific rulesets, use an external rulesets directory instead
|
|
81
|
+
# of modifying this built-in configuration. See ruleset-externalization.md.
|
|
82
|
+
#
|
|
83
|
+
# Categories:
|
|
84
|
+
# - publishing: Rules for content publishing platforms
|
|
85
|
+
# - contract: API contract validation and quality
|
|
86
|
+
# - documentation: Documentation completeness and quality
|
|
87
|
+
# - validation: General validation and linting
|
|
88
|
+
# - security: Security-focused validation
|
|
89
|
+
# - other: Miscellaneous or multi-purpose rulesets
|
|
90
|
+
#
|
|
91
|
+
# Origins:
|
|
92
|
+
# - internal: Internal repositories
|
|
93
|
+
# - external: Public open-source repositories
|
|
94
|
+
# - third-party: External vendor/partner repositories
|
|
95
|
+
#
|
|
96
|
+
# ============================================================================
|