@thymian/plugin-spectral 0.2.0-canary.20260810-95e9b0c
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/convert.d.ts +19 -0
- package/dist/convert.d.ts.map +1 -0
- package/dist/convert.js +67 -0
- package/dist/convert.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/load-spectral-report.d.ts +15 -0
- package/dist/load-spectral-report.d.ts.map +1 -0
- package/dist/load-spectral-report.js +75 -0
- package/dist/load-spectral-report.js.map +1 -0
- package/dist/map-location.d.ts +18 -0
- package/dist/map-location.d.ts.map +1 -0
- package/dist/map-location.js +74 -0
- package/dist/map-location.js.map +1 -0
- package/dist/spectral-types.d.ts +40 -0
- package/dist/spectral-types.d.ts.map +1 -0
- package/dist/spectral-types.js +2 -0
- package/dist/spectral-types.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { LintExecution, Logger, RuleDescriptor, ThymianFormat } from '@thymian/core';
|
|
2
|
+
import type { SpectralResult } from './spectral-types.js';
|
|
3
|
+
export interface ConvertedResults {
|
|
4
|
+
executions: LintExecution[];
|
|
5
|
+
rules: RuleDescriptor[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Maps Spectral results to failed lint executions plus one RuleDescriptor per
|
|
9
|
+
* distinct code. Every Spectral result is a problem, so every execution is
|
|
10
|
+
* `failed` with the finding's own severity on the status (per-finding
|
|
11
|
+
* fidelity regardless of rule-level severity resolution); the descriptor
|
|
12
|
+
* carries the highest severity seen for its code and links back to Spectral's
|
|
13
|
+
* docs via `documentationUrl` when present.
|
|
14
|
+
*/
|
|
15
|
+
export declare function convertResults(results: SpectralResult[], options: {
|
|
16
|
+
logger: Logger;
|
|
17
|
+
format?: ThymianFormat;
|
|
18
|
+
}): ConvertedResults;
|
|
19
|
+
//# sourceMappingURL=convert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,MAAM,EACN,cAAc,EAEd,aAAa,EACd,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA+B1D,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EAAE,EACzB,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,aAAa,CAAA;CAAE,GAClD,gBAAgB,CAqClB"}
|
package/dist/convert.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { mapLocation } from './map-location.js';
|
|
2
|
+
/** DiagnosticSeverity → Thymian severity; exact 1:1 for 0/1/2/3. */
|
|
3
|
+
const SEVERITY_BY_NUMBER = {
|
|
4
|
+
0: 'error',
|
|
5
|
+
1: 'warn',
|
|
6
|
+
2: 'info',
|
|
7
|
+
3: 'hint',
|
|
8
|
+
};
|
|
9
|
+
/** Higher number = more severe, for RuleDescriptor severity aggregation. */
|
|
10
|
+
const SEVERITY_RANK = {
|
|
11
|
+
hint: 0,
|
|
12
|
+
info: 1,
|
|
13
|
+
warn: 2,
|
|
14
|
+
error: 3,
|
|
15
|
+
};
|
|
16
|
+
function mapSeverity(severity, logger) {
|
|
17
|
+
const mapped = SEVERITY_BY_NUMBER[severity];
|
|
18
|
+
if (mapped === undefined) {
|
|
19
|
+
logger.warn(`Unknown Spectral severity ${severity.toString()} — converting conservatively as 'error'.`);
|
|
20
|
+
return 'error';
|
|
21
|
+
}
|
|
22
|
+
return mapped;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Maps Spectral results to failed lint executions plus one RuleDescriptor per
|
|
26
|
+
* distinct code. Every Spectral result is a problem, so every execution is
|
|
27
|
+
* `failed` with the finding's own severity on the status (per-finding
|
|
28
|
+
* fidelity regardless of rule-level severity resolution); the descriptor
|
|
29
|
+
* carries the highest severity seen for its code and links back to Spectral's
|
|
30
|
+
* docs via `documentationUrl` when present.
|
|
31
|
+
*/
|
|
32
|
+
export function convertResults(results, options) {
|
|
33
|
+
const executions = [];
|
|
34
|
+
const rulesById = new Map();
|
|
35
|
+
for (const result of results) {
|
|
36
|
+
const ruleId = `spectral/${String(result.code)}`;
|
|
37
|
+
const severity = mapSeverity(result.severity, options.logger);
|
|
38
|
+
executions.push({
|
|
39
|
+
kind: 'lint',
|
|
40
|
+
ruleId,
|
|
41
|
+
status: { kind: 'failed', reason: result.message, severity },
|
|
42
|
+
location: mapLocation(result, options.format),
|
|
43
|
+
findings: [],
|
|
44
|
+
});
|
|
45
|
+
const existing = rulesById.get(ruleId);
|
|
46
|
+
if (!existing) {
|
|
47
|
+
rulesById.set(ruleId, {
|
|
48
|
+
id: ruleId,
|
|
49
|
+
severity,
|
|
50
|
+
summary: { text: result.message },
|
|
51
|
+
...(result.documentationUrl
|
|
52
|
+
? { helpUri: result.documentationUrl }
|
|
53
|
+
: {}),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
if (SEVERITY_RANK[severity] > SEVERITY_RANK[existing.severity]) {
|
|
58
|
+
existing.severity = severity;
|
|
59
|
+
}
|
|
60
|
+
if (!existing.helpUri && result.documentationUrl) {
|
|
61
|
+
existing.helpUri = result.documentationUrl;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { executions, rules: [...rulesById.values()] };
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,oEAAoE;AACpE,MAAM,kBAAkB,GAA6B;IACnD,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,MAAM;IACT,CAAC,EAAE,MAAM;IACT,CAAC,EAAE,MAAM;CACV,CAAC;AAEF,4EAA4E;AAC5E,MAAM,aAAa,GAA6B;IAC9C,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,SAAS,WAAW,CAAC,QAAgB,EAAE,MAAc;IACnD,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAE5C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CACT,6BAA6B,QAAQ,CAAC,QAAQ,EAAE,0CAA0C,CAC3F,CAAC;QACF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAOD;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAyB,EACzB,OAAmD;IAEnD,MAAM,UAAU,GAAoB,EAAE,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEpD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,YAAY,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACjD,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAE9D,UAAU,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,MAAM;YACZ,MAAM;YACN,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE;YAC5D,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC;YAC7C,QAAQ,EAAE,EAAE;SACb,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE;gBACpB,EAAE,EAAE,MAAM;gBACV,QAAQ;gBACR,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE;gBACjC,GAAG,CAAC,MAAM,CAAC,gBAAgB;oBACzB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,gBAAgB,EAAE;oBACtC,CAAC,CAAC,EAAE,CAAC;aACR,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,IAAI,aAAa,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC/D,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAC/B,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBACjD,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC,gBAAgB,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ThymianPlugin } from '@thymian/core';
|
|
2
|
+
export type { SpectralResult } from './spectral-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* `@thymian/plugin-spectral` converts pre-generated Spectral JSON output
|
|
5
|
+
* (`spectral lint -f json`) into canonical Thymian lint runs. It never
|
|
6
|
+
* executes Spectral — the input is the report file. See
|
|
7
|
+
* {@link SpectralResult} for the supported input format.
|
|
8
|
+
*
|
|
9
|
+
* The plugin extends `thymian report convert` purely by listening on the
|
|
10
|
+
* core-owned `core.report.convert` collect action (ADR-0016/0017): it claims
|
|
11
|
+
* `spectral`-typed report inputs and replies one lint `ToolRun` per claimed
|
|
12
|
+
* input, tagged with that input's identity. The converted report kind is
|
|
13
|
+
* always `lint`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createSpectralPlugin(pluginName?: string): ThymianPlugin;
|
|
16
|
+
export declare const spectralPlugin: ThymianPlugin;
|
|
17
|
+
export default spectralPlugin;
|
|
18
|
+
//# 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,EAAwB,aAAa,EAAE,MAAM,eAAe,CAAC;AAMzE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,SAA6B,GACtC,aAAa,CAgEf;AAED,eAAO,MAAM,cAAc,eAAyB,CAAC;AAErD,eAAe,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { createToolRun, ThymianFormat } from '@thymian/core';
|
|
2
|
+
import { convertResults } from './convert.js';
|
|
3
|
+
import { loadSpectralReport } from './load-spectral-report.js';
|
|
4
|
+
/**
|
|
5
|
+
* `@thymian/plugin-spectral` converts pre-generated Spectral JSON output
|
|
6
|
+
* (`spectral lint -f json`) into canonical Thymian lint runs. It never
|
|
7
|
+
* executes Spectral — the input is the report file. See
|
|
8
|
+
* {@link SpectralResult} for the supported input format.
|
|
9
|
+
*
|
|
10
|
+
* The plugin extends `thymian report convert` purely by listening on the
|
|
11
|
+
* core-owned `core.report.convert` collect action (ADR-0016/0017): it claims
|
|
12
|
+
* `spectral`-typed report inputs and replies one lint `ToolRun` per claimed
|
|
13
|
+
* input, tagged with that input's identity. The converted report kind is
|
|
14
|
+
* always `lint`.
|
|
15
|
+
*/
|
|
16
|
+
export function createSpectralPlugin(pluginName = '@thymian/plugin-spectral') {
|
|
17
|
+
return {
|
|
18
|
+
name: pluginName,
|
|
19
|
+
version: '0.x',
|
|
20
|
+
actions: {
|
|
21
|
+
listensOn: ['core.report.convert'],
|
|
22
|
+
},
|
|
23
|
+
async plugin(emitter, logger, options) {
|
|
24
|
+
emitter.onAction('core.report.convert', async (input, ctx) => {
|
|
25
|
+
const spectralInputs = input.inputs.filter((reportInput) => reportInput.type === 'spectral');
|
|
26
|
+
// Always reply, even with nothing claimed — the collect strategy
|
|
27
|
+
// waits for every registered listener (14.1 listener contract).
|
|
28
|
+
if (spectralInputs.length === 0) {
|
|
29
|
+
logger.info('No spectral report inputs found, nothing to convert.');
|
|
30
|
+
ctx.reply([]);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const format = input.format
|
|
34
|
+
? ThymianFormat.import(input.format)
|
|
35
|
+
: undefined;
|
|
36
|
+
const fragments = [];
|
|
37
|
+
for (const reportInput of spectralInputs) {
|
|
38
|
+
const location = String(reportInput.location);
|
|
39
|
+
const inputLabel = `${reportInput.type}:${location}`;
|
|
40
|
+
logger.info(`Converting Spectral report: ${location}`);
|
|
41
|
+
// Failures propagate as thrown ThymianBaseErrors — the intended
|
|
42
|
+
// tool/runtime error semantics; never a silently dropped input.
|
|
43
|
+
const results = await loadSpectralReport(location, inputLabel, options.cwd);
|
|
44
|
+
const { executions, rules } = convertResults(results, {
|
|
45
|
+
logger,
|
|
46
|
+
format,
|
|
47
|
+
});
|
|
48
|
+
fragments.push({
|
|
49
|
+
// Tag with the stringified input identity — core derives claim
|
|
50
|
+
// coverage by exact type + String(location) match.
|
|
51
|
+
input: { type: reportInput.type, location },
|
|
52
|
+
run: createToolRun({
|
|
53
|
+
tool: { name: pluginName },
|
|
54
|
+
runType: 'lint',
|
|
55
|
+
executions,
|
|
56
|
+
rules: rules.length > 0 ? rules : undefined,
|
|
57
|
+
thymianFormatVersion: input.format?.attributes.hash,
|
|
58
|
+
}),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
ctx.reply(fragments);
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export const spectralPlugin = createSpectralPlugin();
|
|
67
|
+
export default spectralPlugin;
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAI/D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAClC,UAAU,GAAG,0BAA0B;IAEvC,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,KAAK;QACd,OAAO,EAAE;YACP,SAAS,EAAE,CAAC,qBAAqB,CAAC;SACnC;QACD,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO;YACnC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;gBAC3D,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CACxC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,KAAK,UAAU,CACjD,CAAC;gBAEF,iEAAiE;gBACjE,gEAAgE;gBAChE,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAChC,MAAM,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;oBACpE,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBACd,OAAO;gBACT,CAAC;gBAED,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;oBACzB,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;oBACpC,CAAC,CAAC,SAAS,CAAC;gBAEd,MAAM,SAAS,GAA2B,EAAE,CAAC;gBAE7C,KAAK,MAAM,WAAW,IAAI,cAAc,EAAE,CAAC;oBACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;oBAC9C,MAAM,UAAU,GAAG,GAAG,WAAW,CAAC,IAAI,IAAI,QAAQ,EAAE,CAAC;oBAErD,MAAM,CAAC,IAAI,CAAC,+BAA+B,QAAQ,EAAE,CAAC,CAAC;oBAEvD,gEAAgE;oBAChE,gEAAgE;oBAChE,MAAM,OAAO,GAAG,MAAM,kBAAkB,CACtC,QAAQ,EACR,UAAU,EACV,OAAO,CAAC,GAAG,CACZ,CAAC;oBAEF,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC,OAAO,EAAE;wBACpD,MAAM;wBACN,MAAM;qBACP,CAAC,CAAC;oBAEH,SAAS,CAAC,IAAI,CAAC;wBACb,+DAA+D;wBAC/D,mDAAmD;wBACnD,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE;wBAC3C,GAAG,EAAE,aAAa,CAAC;4BACjB,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;4BAC1B,OAAO,EAAE,MAAM;4BACf,UAAU;4BACV,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;4BAC3C,oBAAoB,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,IAAI;yBACpD,CAAC;qBACH,CAAC,CAAC;gBACL,CAAC;gBAED,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,oBAAoB,EAAE,CAAC;AAErD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SpectralResult } from './spectral-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Reads a single Spectral JSON report (`spectral lint -f json` output),
|
|
4
|
+
* validates its structure, and returns the parsed results.
|
|
5
|
+
*
|
|
6
|
+
* Unknown extra fields on entries are tolerated (forward-compatible).
|
|
7
|
+
*
|
|
8
|
+
* @param inputLabel the offending input's identity (`type:location`), used in
|
|
9
|
+
* every error message so failures trace back to the CLI input (AC 5).
|
|
10
|
+
* @throws {ThymianBaseError} if the file is unreadable, not valid JSON, not a
|
|
11
|
+
* result array, or an entry misses the required
|
|
12
|
+
* `code`/`message`/`severity`/`path`/`range` shape.
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadSpectralReport(location: string, inputLabel: string, cwd: string): Promise<SpectralResult[]>;
|
|
15
|
+
//# sourceMappingURL=load-spectral-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-spectral-report.d.ts","sourceRoot":"","sources":["../src/load-spectral-report.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA8C1D;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,EAAE,CAAC,CAsC3B"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { isAbsolute, join } from 'node:path';
|
|
3
|
+
import { ThymianBaseError } from '@thymian/core';
|
|
4
|
+
function isRecord(value) {
|
|
5
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
function isNonNegativeInteger(value) {
|
|
8
|
+
return typeof value === 'number' && Number.isInteger(value) && value >= 0;
|
|
9
|
+
}
|
|
10
|
+
function isPosition(value) {
|
|
11
|
+
return (isRecord(value) &&
|
|
12
|
+
isNonNegativeInteger(value['line']) &&
|
|
13
|
+
isNonNegativeInteger(value['character']));
|
|
14
|
+
}
|
|
15
|
+
function isStringWhenPresent(value) {
|
|
16
|
+
return value === undefined || typeof value === 'string';
|
|
17
|
+
}
|
|
18
|
+
// Validates the full declared SpectralResult contract — the `as
|
|
19
|
+
// SpectralResult[]` cast below vouches for exactly what is checked here, so
|
|
20
|
+
// every required field the mapping code dereferences must be covered.
|
|
21
|
+
function isSpectralResult(value) {
|
|
22
|
+
if (!isRecord(value)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const range = value['range'];
|
|
26
|
+
const code = value['code'];
|
|
27
|
+
return ((typeof code === 'string' || typeof code === 'number') &&
|
|
28
|
+
typeof value['message'] === 'string' &&
|
|
29
|
+
typeof value['severity'] === 'number' &&
|
|
30
|
+
Array.isArray(value['path']) &&
|
|
31
|
+
isRecord(range) &&
|
|
32
|
+
isPosition(range['start']) &&
|
|
33
|
+
isPosition(range['end']) &&
|
|
34
|
+
isStringWhenPresent(value['source']) &&
|
|
35
|
+
isStringWhenPresent(value['documentationUrl']));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Reads a single Spectral JSON report (`spectral lint -f json` output),
|
|
39
|
+
* validates its structure, and returns the parsed results.
|
|
40
|
+
*
|
|
41
|
+
* Unknown extra fields on entries are tolerated (forward-compatible).
|
|
42
|
+
*
|
|
43
|
+
* @param inputLabel the offending input's identity (`type:location`), used in
|
|
44
|
+
* every error message so failures trace back to the CLI input (AC 5).
|
|
45
|
+
* @throws {ThymianBaseError} if the file is unreadable, not valid JSON, not a
|
|
46
|
+
* result array, or an entry misses the required
|
|
47
|
+
* `code`/`message`/`severity`/`path`/`range` shape.
|
|
48
|
+
*/
|
|
49
|
+
export async function loadSpectralReport(location, inputLabel, cwd) {
|
|
50
|
+
const filePath = isAbsolute(location) ? location : join(cwd, location);
|
|
51
|
+
let content;
|
|
52
|
+
try {
|
|
53
|
+
content = await readFile(filePath, 'utf-8');
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
throw new ThymianBaseError(`Failed to read Spectral report "${inputLabel}" (resolved to ${filePath}).`, { cause: err instanceof Error ? err : undefined });
|
|
57
|
+
}
|
|
58
|
+
let parsed;
|
|
59
|
+
try {
|
|
60
|
+
parsed = JSON.parse(content);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
throw new ThymianBaseError(`Failed to parse Spectral report "${inputLabel}" as JSON.`, { cause: err instanceof Error ? err : undefined });
|
|
64
|
+
}
|
|
65
|
+
if (!Array.isArray(parsed)) {
|
|
66
|
+
throw new ThymianBaseError(`Unsupported Spectral report "${inputLabel}": expected the JSON array produced by \`spectral lint -f json\`.`);
|
|
67
|
+
}
|
|
68
|
+
for (const [index, entry] of parsed.entries()) {
|
|
69
|
+
if (!isSpectralResult(entry)) {
|
|
70
|
+
throw new ThymianBaseError(`Unsupported Spectral report "${inputLabel}": result ${index.toString()} does not match the \`spectral lint -f json\` result shape (code/message/severity/path/range).`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return parsed;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=load-spectral-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-spectral-report.js","sourceRoot":"","sources":["../src/load-spectral-report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Location, ThymianFormat } from '@thymian/core';
|
|
2
|
+
import type { SpectralResult } from './spectral-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Best-effort mapping of a Spectral finding onto the loaded format (AC 4):
|
|
5
|
+
*
|
|
6
|
+
* 1. With a format and a finding `source`: the graph node from the same source
|
|
7
|
+
* file whose `sourceLocation.position` is nearest at-or-before the finding.
|
|
8
|
+
* Positions are 1-based (openapi loc-mappers); Spectral ranges are 0-based,
|
|
9
|
+
* so the finding line/column are shifted by +1 before comparing.
|
|
10
|
+
* 2. Otherwise, a `file` location from `source` + the finding range,
|
|
11
|
+
* **1-based** line/column (0-based Spectral values shifted by +1).
|
|
12
|
+
* 3. Without a `source`, a `custom` location from the joined `path` segments.
|
|
13
|
+
*
|
|
14
|
+
* The fallback chain is the contract — full resolution is genuinely
|
|
15
|
+
* best-effort, never required.
|
|
16
|
+
*/
|
|
17
|
+
export declare function mapLocation(result: SpectralResult, format: ThymianFormat | undefined): Location;
|
|
18
|
+
//# sourceMappingURL=map-location.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-location.d.ts","sourceRoot":"","sources":["../src/map-location.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAuB1D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,aAAa,GAAG,SAAS,GAChC,QAAQ,CAuDV"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Does the finding's `source` refer to the node's source file? Spectral emits
|
|
3
|
+
* OS-native absolute paths while format nodes carry the path the spec was
|
|
4
|
+
* loaded from — backslashes are normalized so Windows sources match too, then
|
|
5
|
+
* paths match exactly or when one is a `/`-suffix of the other.
|
|
6
|
+
*/
|
|
7
|
+
function sourceMatches(source, nodePath) {
|
|
8
|
+
const normalizedSource = source.replaceAll('\\', '/');
|
|
9
|
+
const normalizedNodePath = nodePath.replaceAll('\\', '/');
|
|
10
|
+
if (!normalizedSource || !normalizedNodePath) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
return (normalizedSource === normalizedNodePath ||
|
|
14
|
+
normalizedSource.endsWith(`/${normalizedNodePath}`) ||
|
|
15
|
+
normalizedNodePath.endsWith(`/${normalizedSource}`));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Best-effort mapping of a Spectral finding onto the loaded format (AC 4):
|
|
19
|
+
*
|
|
20
|
+
* 1. With a format and a finding `source`: the graph node from the same source
|
|
21
|
+
* file whose `sourceLocation.position` is nearest at-or-before the finding.
|
|
22
|
+
* Positions are 1-based (openapi loc-mappers); Spectral ranges are 0-based,
|
|
23
|
+
* so the finding line/column are shifted by +1 before comparing.
|
|
24
|
+
* 2. Otherwise, a `file` location from `source` + the finding range,
|
|
25
|
+
* **1-based** line/column (0-based Spectral values shifted by +1).
|
|
26
|
+
* 3. Without a `source`, a `custom` location from the joined `path` segments.
|
|
27
|
+
*
|
|
28
|
+
* The fallback chain is the contract — full resolution is genuinely
|
|
29
|
+
* best-effort, never required.
|
|
30
|
+
*/
|
|
31
|
+
export function mapLocation(result, format) {
|
|
32
|
+
const line = result.range.start.line + 1;
|
|
33
|
+
const column = result.range.start.character + 1;
|
|
34
|
+
if (format && result.source) {
|
|
35
|
+
const source = result.source;
|
|
36
|
+
let bestId;
|
|
37
|
+
let bestLine = 0;
|
|
38
|
+
let bestColumn = 0;
|
|
39
|
+
format.graph.forEachNode((id, node) => {
|
|
40
|
+
const { sourceLocation } = node;
|
|
41
|
+
// URI-sourced nodes cannot match a Spectral file source — skip them.
|
|
42
|
+
if (!sourceLocation?.position ||
|
|
43
|
+
!('path' in sourceLocation) ||
|
|
44
|
+
!sourceMatches(source, sourceLocation.path)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const { line: nodeLine, column: nodeColumn } = sourceLocation.position;
|
|
48
|
+
const atOrBefore = nodeLine < line || (nodeLine === line && nodeColumn <= column);
|
|
49
|
+
const nearerThanBest = nodeLine > bestLine ||
|
|
50
|
+
(nodeLine === bestLine && nodeColumn > bestColumn);
|
|
51
|
+
if (atOrBefore && (bestId === undefined || nearerThanBest)) {
|
|
52
|
+
bestId = id;
|
|
53
|
+
bestLine = nodeLine;
|
|
54
|
+
bestColumn = nodeColumn;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
if (bestId !== undefined) {
|
|
58
|
+
return {
|
|
59
|
+
type: 'thymianFormat',
|
|
60
|
+
elementType: 'node',
|
|
61
|
+
elementId: bestId,
|
|
62
|
+
pointer: '',
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (result.source) {
|
|
67
|
+
return { type: 'file', path: result.source, line, column };
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
type: 'custom',
|
|
71
|
+
value: result.path.length > 0 ? result.path.join('.') : 'unknown',
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=map-location.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-location.js","sourceRoot":"","sources":["../src/map-location.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,SAAS,aAAa,CAAC,MAAc,EAAE,QAAgB;IACrD,MAAM,gBAAgB,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,kBAAkB,GAAG,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE1D,IAAI,CAAC,gBAAgB,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC7C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CACL,gBAAgB,KAAK,kBAAkB;QACvC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,kBAAkB,EAAE,CAAC;QACnD,kBAAkB,CAAC,QAAQ,CAAC,IAAI,gBAAgB,EAAE,CAAC,CACpD,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CACzB,MAAsB,EACtB,MAAiC;IAEjC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;IAEhD,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,IAAI,MAA0B,CAAC;QAC/B,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;YACpC,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;YAEhC,qEAAqE;YACrE,IACE,CAAC,cAAc,EAAE,QAAQ;gBACzB,CAAC,CAAC,MAAM,IAAI,cAAc,CAAC;gBAC3B,CAAC,aAAa,CAAC,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,EAC3C,CAAC;gBACD,OAAO;YACT,CAAC;YAED,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,cAAc,CAAC,QAAQ,CAAC;YAEvE,MAAM,UAAU,GACd,QAAQ,GAAG,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,UAAU,IAAI,MAAM,CAAC,CAAC;YACjE,MAAM,cAAc,GAClB,QAAQ,GAAG,QAAQ;gBACnB,CAAC,QAAQ,KAAK,QAAQ,IAAI,UAAU,GAAG,UAAU,CAAC,CAAC;YAErD,IAAI,UAAU,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,cAAc,CAAC,EAAE,CAAC;gBAC3D,MAAM,GAAG,EAAE,CAAC;gBACZ,QAAQ,GAAG,QAAQ,CAAC;gBACpB,UAAU,GAAG,UAAU,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO;gBACL,IAAI,EAAE,eAAe;gBACrB,WAAW,EAAE,MAAM;gBACnB,SAAS,EAAE,MAAM;gBACjB,OAAO,EAAE,EAAE;aACZ,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC7D,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;KAClE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The supported Spectral input: the JSON array produced by
|
|
3
|
+
* `spectral lint -f json` (`@stoplight/spectral-cli`).
|
|
4
|
+
*
|
|
5
|
+
* Field set as emitted by Spectral's `json` formatter: `code`, `path`,
|
|
6
|
+
* `message`, `severity`, `range`, `source`, plus `documentationUrl` only when
|
|
7
|
+
* the rule declares one. Verified against real Spectral 6 output.
|
|
8
|
+
*
|
|
9
|
+
* - `range` positions are **0-based** (lines and characters).
|
|
10
|
+
* - `severity` numbers are DiagnosticSeverity: 0=error, 1=warning,
|
|
11
|
+
* 2=information, 3=hint.
|
|
12
|
+
* - Unknown extra fields are tolerated (forward-compatible); unknown severity
|
|
13
|
+
* numbers convert conservatively to `error` with a warning — findings are
|
|
14
|
+
* never dropped.
|
|
15
|
+
*/
|
|
16
|
+
export interface SpectralResult {
|
|
17
|
+
/** Rule identifier; Spectral allows numeric codes — stringified on mapping. */
|
|
18
|
+
code: string | number;
|
|
19
|
+
message: string;
|
|
20
|
+
/** DiagnosticSeverity: 0=error, 1=warning, 2=information, 3=hint. */
|
|
21
|
+
severity: number;
|
|
22
|
+
/** JSON path segments of the offending document location. */
|
|
23
|
+
path: (string | number)[];
|
|
24
|
+
/** 0-based document range of the finding. */
|
|
25
|
+
range: {
|
|
26
|
+
start: {
|
|
27
|
+
line: number;
|
|
28
|
+
character: number;
|
|
29
|
+
};
|
|
30
|
+
end: {
|
|
31
|
+
line: number;
|
|
32
|
+
character: number;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
/** Source file the finding refers to, when Spectral knows it. */
|
|
36
|
+
source?: string;
|
|
37
|
+
/** Rule documentation link, present only when the rule declares one. */
|
|
38
|
+
documentationUrl?: string;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=spectral-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spectral-types.d.ts","sourceRoot":"","sources":["../src/spectral-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,cAAc;IAC7B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC1B,6CAA6C;IAC7C,KAAK,EAAE;QACL,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3C,GAAG,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;KAC1C,CAAC;IACF,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spectral-types.js","sourceRoot":"","sources":["../src/spectral-types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thymian/plugin-spectral",
|
|
3
|
+
"version": "0.2.0-canary.20260810-95e9b0c",
|
|
4
|
+
"description": "Thymian plugin that converts pre-generated Spectral JSON output into canonical Thymian lint reports",
|
|
5
|
+
"license": "AGPL-3.0-only",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/thymianofficial/thymian/issues"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://thymian.dev",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/thymianofficial/thymian.git",
|
|
13
|
+
"directory": "packages/plugin-spectral"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"thymian",
|
|
20
|
+
"spectral",
|
|
21
|
+
"report-converter",
|
|
22
|
+
"lint",
|
|
23
|
+
"api-conformance"
|
|
24
|
+
],
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"module": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"type": "module",
|
|
29
|
+
"exports": {
|
|
30
|
+
"./package.json": "./package.json",
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/index.js",
|
|
34
|
+
"default": "./dist/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"!**/*.tsbuildinfo"
|
|
40
|
+
],
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@thymian/core": "0.2.0-canary.20260810-95e9b0c",
|
|
43
|
+
"tslib": "^2.3.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@thymian/core-testing": "0.2.0-canary.20260810-95e9b0c"
|
|
47
|
+
}
|
|
48
|
+
}
|