Skip to content

Commit e66f4e0

Browse files
fix: add request scope handling for tracking rules in client and api mode (#505)
Signed-off-by: Fredrik Nordlander <fredrik.nordlander@digg.se>
1 parent 7f1ef9d commit e66f4e0

25 files changed

+254
-208
lines changed

src/cli-mode.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { Issue } from './util/Issue.js';
2020
import { parseApiSpecInput,detectSpecFormatPreference, ParseResult} from './util/validateUtil.js';
2121
import { SpecParseError } from './util/RapLPSpecParseError.js';
2222
import * as path from 'node:path';
23+
import { RuleExecutionContext } from './util/RuleExecutionContext.js';
2324

2425
declare var AggregateError: {
2526
prototype: AggregateError;
@@ -47,6 +48,8 @@ export async function execCLI<T extends CliArgs>(argv: T) {
4748
const logErrorFilePath = argv.logError as string | undefined;
4849
const logDiagnosticFilePath = argv.logDiagnostic as string | undefined;
4950
const strict = argv.strict as boolean ?? false;
51+
const context = new RuleExecutionContext();
52+
5053

5154
// Schemevalidation and Spectral Document creation ----------
5255
let apiSpecDocument: SpectralDocument;
@@ -125,7 +128,7 @@ export async function execCLI<T extends CliArgs>(argv: T) {
125128

126129
try {
127130
// Import and create rule instances in RAP-LP
128-
const enabledRulesAndCategorys = await importAndCreateRuleInstances(ruleCategories);
131+
const enabledRulesAndCategorys = await importAndCreateRuleInstances(context,ruleCategories);
129132
// Load API specification into a Document object
130133
const parser: IParser<any> = (parseResult.format === 'json' ? Parsers.Json : Parsers.Yaml) as unknown as IParser<any>;
131134
apiSpecDocument = new SpectralDocument(parseResult.raw, parser, apiSpecFileName);
@@ -138,7 +141,7 @@ export async function execCLI<T extends CliArgs>(argv: T) {
138141
customSpectral.setRuleset(enabledRulesAndCategorys.rules);
139142
const result = await customSpectral.run(apiSpecDocument);
140143

141-
const customDiagnostic = new RapLPDiagnostic();
144+
const customDiagnostic = new RapLPDiagnostic(context);
142145
customDiagnostic.processRuleExecutionInformation(result, enabledRulesAndCategorys.instanceCategoryMap);
143146
const diagnosticReports: DiagnosticReport[] = customDiagnostic.processDiagnosticInformation();
144147
if (argv.dex != null) {

src/routes/urlValidation.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ import { UrlContentDto } from '../model/UrlContentDto.js';
1010
import { importAndCreateRuleInstances } from '../util/ruleUtil.js';
1111
import { ERROR_TYPE, RapLPBaseApiError } from '../util/RapLPBaseApiErrorHandling.js';
1212
import { loadUrlValidationConfiguration } from '../util/urlValidationConfig.js';
13+
import { RuleExecutionContext } from '../util/RuleExecutionContext.js';
1314

1415
export const registerUrlValidationRoutes = (app: Express, urlValidationConfigFile?: string) => {
1516
const config = loadUrlValidationConfiguration(urlValidationConfigFile);
1617

1718
// Route for validating openapi yaml from url.
1819
app.post('/api/v1/validation/url', async (req, res, next) => {
1920
try {
21+
const context = new RuleExecutionContext();
2022
const dto: UrlContentDto = req.body;
2123

2224
if (config?.urlMatchRegex && !dto.url.match(config.urlMatchRegex)) {
@@ -35,9 +37,9 @@ export const registerUrlValidationRoutes = (app: Express, urlValidationConfigFil
3537

3638
const apiSpecDocument = new Document(yamlContentString, Parsers.Yaml, '');
3739

38-
const rules = await importAndCreateRuleInstances(dto.categories);
40+
const rules = await importAndCreateRuleInstances(context, dto.categories);
3941

40-
const result = await processApiSpec(rules, apiSpecDocument);
42+
const result = await processApiSpec(context,rules, apiSpecDocument);
4143
res.send(result);
4244
} catch (e) {
4345
next(e);

src/routes/validate.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@ import { ApiInfo } from '../model/ApiInfo.js';
1212
import { validationRules } from '../model/validationRules.js';
1313
import { ExcelReportProcessor } from '../util/excelReportProcessor.js';
1414
import { DiagnosticReport, RapLPDiagnostic } from '../util/RapLPDiagnostic.js';
15-
import { Issue } from '../util/Issue.js';
1615
import * as IssueHelper from '../util/RapLPIssueHelpers.js';
1716
import { parseApiSpecInput,detectSpecFormatPreference, ParseResult} from '../util/validateUtil.js';
18-
import { SpecParseError } from '../util/RapLPSpecParseError.js';
1917
import { ProblemDetailsDTO } from '../model/ProblemDetailsDto.js';
2018
import { SpecValidationRequestDto } from '../model/SpecValidationRequestDto.js';
2119
import { ERROR_TYPE, RapLPBaseApiError } from '../util/RapLPBaseApiErrorHandling.js';
2220
import type { IParser } from '@stoplight/spectral-parsers';
2321
import { stringify } from 'node:querystring';
22+
import { RuleExecutionContext } from '../util/RuleExecutionContext.js';
2423

2524

2625

2726
export const registerValidationRoutes = (app: Express) => {
2827
// Route for raw content upload.
2928
app.post('/api/v1/validation/validate', async (req, res, next) => {
3029
try {
30+
const context = new RuleExecutionContext();
3131
const yamlContent: YamlContentDto = req.body;
3232

3333
let yamlContentString: string;
@@ -37,9 +37,9 @@ export const registerValidationRoutes = (app: Express) => {
3737

3838
const apiSpecDocument = new Document(yamlContentString, Parsers.Yaml, '');
3939

40-
const rules = await importAndCreateRuleInstances(yamlContent.categories);
40+
const rules = await importAndCreateRuleInstances(context, yamlContent.categories);
4141

42-
const result = await processApiSpec(rules, apiSpecDocument);
42+
const result = await processApiSpec(context,rules, apiSpecDocument);
4343
res.send(result);
4444
} catch (e) {
4545
next(e);
@@ -59,6 +59,7 @@ export const registerValidationRoutes = (app: Express) => {
5959
app.post('/api/v1/validation/generate-report', async (req, res, next): Promise<any> => {
6060
try {
6161
const data = req.body;
62+
const context = new RuleExecutionContext();
6263

6364
if (!data || !data.result || !Array.isArray(data.result)) {
6465
return res.status(400).json({ error: 'Invalid data format. Expected an object with a "result" array.' });
@@ -70,7 +71,7 @@ export const registerValidationRoutes = (app: Express) => {
7071
const ruleCategories = data.categories && data.categories.length > 0 ? data.categories : undefined;
7172

7273
const enabledRulesAndCategorys = await importAndCreateRuleInstances(ruleCategories);
73-
const customDiagnostic = new RapLPDiagnostic();
74+
const customDiagnostic = new RapLPDiagnostic(context);
7475
customDiagnostic.processRuleExecutionInformation(data.result, enabledRulesAndCategorys.instanceCategoryMap);
7576
const diagnosticReports: DiagnosticReport[] = customDiagnostic.processDiagnosticInformation();
7677

@@ -93,6 +94,7 @@ export const registerValidationRoutes = (app: Express) => {
9394
*/
9495
app.post('/api/v1/validation/validatespec', async (req, res, next) => {
9596
try {
97+
const context = new RuleExecutionContext();
9698
const body: SpecValidationRequestDto = req.body;
9799

98100
//0.5 Check input
@@ -146,8 +148,8 @@ export const registerValidationRoutes = (app: Express) => {
146148
// 5. No strict-errors → run raplp ruleengine
147149
const parser: IParser<any> = (parseResult.format === 'json' ? Parsers.Json : Parsers.Yaml) as unknown as IParser<any>;
148150
const apiSpecDocument = new Document(parseResult.raw, parser, '');
149-
const rules = await importAndCreateRuleInstances(categories);
150-
const result = await processApiSpec(rules, apiSpecDocument);
151+
const rules = await importAndCreateRuleInstances(context, categories);
152+
const result = await processApiSpec(context, rules, apiSpecDocument);
151153

152154
const hasRuleViolations = result.result.some(
153155
d =>d.allvarlighetsgrad === 'ERROR' || d.allvarlighetsgrad === 'WARNING'

src/rulesets/AmeRules.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { parsePropertyNames } from './rulesetUtil.js';
88
import { CustomProperties } from '../ruleinterface/CustomProperties.js';
99
import { BaseRuleset } from './BaseRuleset.js';
1010
import { isValidApplicationJson } from './util/AmeRulesUtil.js';
11+
import { RuleExecutionContext } from '../util/RuleExecutionContext.js';
1112

1213
const moduleName: string = 'AmeRules.js';
1314

@@ -55,8 +56,8 @@ export class Ame07 extends BaseRuleset {
5556
},
5657
},
5758
];
58-
constructor() {
59-
super();
59+
constructor(context: RuleExecutionContext) {
60+
super(context);
6061
super.initializeFormats(['OAS3']);
6162
}
6263
severity = DiagnosticSeverity.Warning;
@@ -91,8 +92,8 @@ export class Ame04 extends BaseRuleset {
9192
},
9293
},
9394
];
94-
constructor() {
95-
super();
95+
constructor(context: RuleExecutionContext) {
96+
super(context);
9697
super.initializeFormats(['OAS3']);
9798
}
9899
severity = DiagnosticSeverity.Warning;
@@ -137,8 +138,8 @@ export class Ame01 extends BaseRuleset {
137138
},
138139
},
139140
];
140-
constructor() {
141-
super();
141+
constructor(context: RuleExecutionContext) {
142+
super(context);
142143
super.initializeFormats(['OAS3']);
143144
}
144145
severity = DiagnosticSeverity.Warning;
@@ -185,8 +186,8 @@ export class Ame02 extends BaseRuleset {
185186
},
186187
},
187188
];
188-
constructor() {
189-
super();
189+
constructor(context: RuleExecutionContext) {
190+
super(context);
190191
super.initializeFormats(['OAS3']);
191192
}
192193
severity = DiagnosticSeverity.Warning;
@@ -315,8 +316,8 @@ export class Ame05 extends BaseRuleset {
315316
}
316317
return Array.from(invalidEntries);
317318
}
318-
constructor() {
319-
super();
319+
constructor(context: RuleExecutionContext) {
320+
super(context);
320321
super.initializeFormats(['OAS3']);
321322
}
322323
severity = DiagnosticSeverity.Error;

src/rulesets/ArqRules.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { DiagnosticSeverity } from '@stoplight/types';
88
import { CustomProperties } from '../ruleinterface/CustomProperties.js';
99
import { BaseRuleset } from './BaseRuleset.js';
1010
import { isValidApplicationJson } from './rulesetUtil.js';
11+
import { RuleExecutionContext } from '../util/RuleExecutionContext.js';
1112

1213
const moduleName: string = 'ArqRules.js';
1314

@@ -149,8 +150,8 @@ export class Arq01 extends BaseRuleset {
149150
},
150151
},
151152
];
152-
constructor() {
153-
super();
153+
constructor(context: RuleExecutionContext) {
154+
super(context);
154155
super.initializeFormats(['OAS3']);
155156
}
156157
severity = DiagnosticSeverity.Warning;
@@ -215,9 +216,9 @@ export class Arq03 extends BaseRuleset {
215216
},
216217
},
217218
];
218-
constructor() {
219-
super();
220-
super.initializeFormats(['OAS2', 'OAS3']);
219+
constructor(context: RuleExecutionContext) {
220+
super(context);
221+
super.initializeFormats(['OAS3']);
221222
}
222223
severity = DiagnosticSeverity.Warning;
223224
}

src/rulesets/BaseRuleset.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import { RulesetInterface } from '../ruleinterface/RuleInterface.js';
66
import { CustomProperties } from '../ruleinterface/CustomProperties.js';
77
import { CustomFormatType } from './util/CustomOasVersion.js';
88
import { DiagnosticSeverity } from '@stoplight/types';
9-
import { logRuleExecution } from '../util/RuleExecutionStatusModule.js';
109
import Format from '@stoplight/spectral-formats';
10+
import { RuleExecutionContext } from '../util/RuleExecutionContext.js';
1111

12-
export class BaseRuleset implements RulesetInterface {
12+
export abstract class BaseRuleset implements RulesetInterface {
1313
static customProperties: CustomProperties = { område: undefined!, id: '' };
1414
static getCustomProperties(): CustomProperties {
1515
return BaseRuleset.customProperties;
@@ -22,7 +22,14 @@ export class BaseRuleset implements RulesetInterface {
2222

2323
formats: any = [];
2424

25-
trackRuleExecutionHandler(
25+
constructor(context: RuleExecutionContext) {
26+
this.#context = context;
27+
28+
}
29+
#context: RuleExecutionContext;
30+
31+
32+
protected trackRuleExecutionHandler(
2633
targetVal: string,
2734
_opts: string,
2835
paths: string[],
@@ -31,7 +38,7 @@ export class BaseRuleset implements RulesetInterface {
3138
moduleName: any,
3239
subclassProperties: CustomProperties,
3340
) {
34-
logRuleExecution(moduleName, subclassInfo, subclassProperties, this.severity.toString(), true, targetVal);
41+
this.#context.logRuleExecution(moduleName, subclassInfo, subclassProperties, this.severity.toString(), true, targetVal);
3542
return [];
3643
}
3744
async initializeFormats(formats: CustomFormatType[] = []) {

0 commit comments

Comments
 (0)