heicat-core 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.
Files changed (50) hide show
  1. package/dist/contract-loader.d.ts +4 -0
  2. package/dist/contract-loader.d.ts.map +1 -0
  3. package/dist/contract-loader.js +45 -0
  4. package/dist/contract-loader.js.map +1 -0
  5. package/dist/engine.d.ts +22 -0
  6. package/dist/engine.d.ts.map +1 -0
  7. package/dist/engine.js +75 -0
  8. package/dist/engine.js.map +1 -0
  9. package/dist/index.d.ts +8 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +12 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/middleware.d.ts +13 -0
  14. package/dist/middleware.d.ts.map +1 -0
  15. package/dist/middleware.js +78 -0
  16. package/dist/middleware.js.map +1 -0
  17. package/dist/types/contract.d.ts +26 -0
  18. package/dist/types/contract.d.ts.map +1 -0
  19. package/dist/types/contract.js +3 -0
  20. package/dist/types/contract.js.map +1 -0
  21. package/dist/types/options.d.ts +7 -0
  22. package/dist/types/options.d.ts.map +1 -0
  23. package/dist/types/options.js +3 -0
  24. package/dist/types/options.js.map +1 -0
  25. package/dist/types/violation.d.ts +19 -0
  26. package/dist/types/violation.d.ts.map +1 -0
  27. package/dist/types/violation.js +3 -0
  28. package/dist/types/violation.js.map +1 -0
  29. package/dist/validation-engine.d.ts +10 -0
  30. package/dist/validation-engine.d.ts.map +1 -0
  31. package/dist/validation-engine.js +138 -0
  32. package/dist/validation-engine.js.map +1 -0
  33. package/dist/violation-store.d.ts +16 -0
  34. package/dist/violation-store.d.ts.map +1 -0
  35. package/dist/violation-store.js +41 -0
  36. package/dist/violation-store.js.map +1 -0
  37. package/jest.config.js +7 -0
  38. package/package.json +45 -0
  39. package/src/__tests__/contract-loader.test.ts +112 -0
  40. package/src/__tests__/validation-engine.test.ts +213 -0
  41. package/src/contract-loader.ts +55 -0
  42. package/src/engine.ts +95 -0
  43. package/src/index.ts +9 -0
  44. package/src/middleware.ts +97 -0
  45. package/src/types/contract.ts +28 -0
  46. package/src/types/options.ts +7 -0
  47. package/src/types/violation.ts +19 -0
  48. package/src/validation-engine.ts +157 -0
  49. package/src/violation-store.ts +46 -0
  50. package/tsconfig.json +18 -0
@@ -0,0 +1,4 @@
1
+ import { Contract } from './types/contract';
2
+ export declare function loadContracts(contractsPath: string): Promise<Contract[]>;
3
+ export declare function findContract(contracts: Contract[], method: string, path: string): Contract | undefined;
4
+ //# sourceMappingURL=contract-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-loader.d.ts","sourceRoot":"","sources":["../src/contract-loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,wBAAsB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAG9E;AAqCD,wBAAgB,YAAY,CAC1B,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,QAAQ,GAAG,SAAS,CAKtB"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadContracts = loadContracts;
4
+ exports.findContract = findContract;
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ async function loadContracts(contractsPath) {
8
+ // Use manual directory traversal (more reliable than glob)
9
+ return loadContractsManually(contractsPath);
10
+ }
11
+ function loadContractsManually(contractsPath) {
12
+ const contracts = [];
13
+ const fullPath = (0, path_1.resolve)(contractsPath);
14
+ try {
15
+ const items = (0, fs_1.readdirSync)(fullPath);
16
+ for (const item of items) {
17
+ const itemPath = (0, path_1.join)(fullPath, item);
18
+ const stat = (0, fs_1.statSync)(itemPath);
19
+ if (stat.isFile() && item.endsWith('.contract.json')) {
20
+ try {
21
+ const content = (0, fs_1.readFileSync)(itemPath, 'utf-8');
22
+ const contract = JSON.parse(content);
23
+ // Basic validation
24
+ if (!contract.method || !contract.path) {
25
+ console.warn(`Invalid contract in ${itemPath}: missing method or path`);
26
+ continue;
27
+ }
28
+ contracts.push(contract);
29
+ }
30
+ catch (error) {
31
+ console.warn(`Failed to load contract from ${itemPath}:`, error);
32
+ }
33
+ }
34
+ }
35
+ }
36
+ catch (error) {
37
+ console.warn(`Failed to read contracts directory ${fullPath}:`, error);
38
+ }
39
+ return contracts;
40
+ }
41
+ function findContract(contracts, method, path) {
42
+ return contracts.find(contract => contract.method.toUpperCase() === method.toUpperCase() &&
43
+ contract.path === path);
44
+ }
45
+ //# sourceMappingURL=contract-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-loader.js","sourceRoot":"","sources":["../src/contract-loader.ts"],"names":[],"mappings":";;AAKA,sCAGC;AAqCD,oCASC;AArDD,2BAAyD;AACzD,+BAA8C;AAGvC,KAAK,UAAU,aAAa,CAAC,aAAqB;IACvD,2DAA2D;IAC3D,OAAO,qBAAqB,CAAC,aAAa,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,qBAAqB,CAAC,aAAqB;IAClD,MAAM,SAAS,GAAe,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,IAAA,cAAO,EAAC,aAAa,CAAC,CAAC;IAExC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAA,gBAAW,EAAC,QAAQ,CAAC,CAAC;QAEpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACtC,MAAM,IAAI,GAAG,IAAA,aAAQ,EAAC,QAAQ,CAAC,CAAC;YAEhC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACrD,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,IAAA,iBAAY,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;oBAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAa,CAAC;oBAEjD,mBAAmB;oBACnB,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;wBACvC,OAAO,CAAC,IAAI,CAAC,uBAAuB,QAAQ,0BAA0B,CAAC,CAAC;wBACxE,SAAS;oBACX,CAAC;oBAED,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC3B,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,IAAI,CAAC,gCAAgC,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;gBACnE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,sCAAsC,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,YAAY,CAC1B,SAAqB,EACrB,MAAc,EACd,IAAY;IAEZ,OAAO,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAC/B,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,WAAW,EAAE;QACtD,QAAQ,CAAC,IAAI,KAAK,IAAI,CACvB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { Violation } from './types/violation';
2
+ import { ValidationMode } from './types/options';
3
+ export declare class ContractEngine {
4
+ private contracts;
5
+ private validationEngine;
6
+ private violationStore;
7
+ private mode;
8
+ constructor(mode: ValidationMode);
9
+ loadContracts(contractsPath: string): Promise<void>;
10
+ validateRequest(method: string, path: string, req: any): Violation[];
11
+ validateResponse(method: string, path: string, statusCode: number, body: any): Violation[];
12
+ validateError(method: string, path: string, statusCode: number, body: any): Violation[];
13
+ private logViolation;
14
+ getViolations(): Violation[];
15
+ getStats(): {
16
+ total: number;
17
+ byType: Record<string, number>;
18
+ bySeverity: Record<string, number>;
19
+ };
20
+ clearViolations(): void;
21
+ }
22
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAI9C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,IAAI,CAAiB;gBAEjB,IAAI,EAAE,cAAc;IAM1B,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzD,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,SAAS,EAAE;IAkBpE,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,SAAS,EAAE;IAkB1F,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,SAAS,EAAE;IAkBvF,OAAO,CAAC,YAAY;IAKpB,aAAa;IAIb,QAAQ;;;;;IAIR,eAAe,IAAI,IAAI;CAGxB"}
package/dist/engine.js ADDED
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ContractEngine = void 0;
4
+ const validation_engine_1 = require("./validation-engine");
5
+ const violation_store_1 = require("./violation-store");
6
+ const contract_loader_1 = require("./contract-loader");
7
+ class ContractEngine {
8
+ constructor(mode) {
9
+ this.contracts = [];
10
+ this.validationEngine = new validation_engine_1.ValidationEngine();
11
+ this.violationStore = new violation_store_1.ViolationStore();
12
+ this.mode = mode;
13
+ }
14
+ async loadContracts(contractsPath) {
15
+ this.contracts = await (0, contract_loader_1.loadContracts)(contractsPath);
16
+ console.log(`Loaded ${this.contracts.length} contracts`);
17
+ }
18
+ validateRequest(method, path, req) {
19
+ const contract = (0, contract_loader_1.findContract)(this.contracts, method, path);
20
+ if (!contract) {
21
+ return []; // No contract means no validation
22
+ }
23
+ const result = this.validationEngine.validateRequest(contract, req);
24
+ if (!result.isValid) {
25
+ result.violations.forEach(violation => {
26
+ this.violationStore.add(violation);
27
+ this.logViolation(violation);
28
+ });
29
+ }
30
+ return result.violations;
31
+ }
32
+ validateResponse(method, path, statusCode, body) {
33
+ const contract = (0, contract_loader_1.findContract)(this.contracts, method, path);
34
+ if (!contract) {
35
+ return [];
36
+ }
37
+ const result = this.validationEngine.validateResponse(contract, statusCode, body);
38
+ if (!result.isValid) {
39
+ result.violations.forEach(violation => {
40
+ this.violationStore.add(violation);
41
+ this.logViolation(violation);
42
+ });
43
+ }
44
+ return result.violations;
45
+ }
46
+ validateError(method, path, statusCode, body) {
47
+ const contract = (0, contract_loader_1.findContract)(this.contracts, method, path);
48
+ if (!contract) {
49
+ return [];
50
+ }
51
+ const result = this.validationEngine.validateError(contract, statusCode, body);
52
+ if (!result.isValid) {
53
+ result.violations.forEach(violation => {
54
+ this.violationStore.add(violation);
55
+ this.logViolation(violation);
56
+ });
57
+ }
58
+ return result.violations;
59
+ }
60
+ logViolation(violation) {
61
+ const prefix = violation.severity === 'error' ? '❌' : '⚠️';
62
+ console.log(`${prefix} ${violation.endpoint.method} ${violation.endpoint.path}: ${violation.message}`);
63
+ }
64
+ getViolations() {
65
+ return this.violationStore.getAll();
66
+ }
67
+ getStats() {
68
+ return this.violationStore.getStats();
69
+ }
70
+ clearViolations() {
71
+ this.violationStore.clear();
72
+ }
73
+ }
74
+ exports.ContractEngine = ContractEngine;
75
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export { contractMiddleware } from './middleware';
2
+ export { ContractEngine } from './engine';
3
+ export { ViolationStore } from './violation-store';
4
+ export { loadContracts } from './contract-loader';
5
+ export type { Contract } from './types/contract';
6
+ export type { Violation } from './types/violation';
7
+ export type { MiddlewareOptions } from './types/options';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,YAAY,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadContracts = exports.ViolationStore = exports.ContractEngine = exports.contractMiddleware = void 0;
4
+ var middleware_1 = require("./middleware");
5
+ Object.defineProperty(exports, "contractMiddleware", { enumerable: true, get: function () { return middleware_1.contractMiddleware; } });
6
+ var engine_1 = require("./engine");
7
+ Object.defineProperty(exports, "ContractEngine", { enumerable: true, get: function () { return engine_1.ContractEngine; } });
8
+ var violation_store_1 = require("./violation-store");
9
+ Object.defineProperty(exports, "ViolationStore", { enumerable: true, get: function () { return violation_store_1.ViolationStore; } });
10
+ var contract_loader_1 = require("./contract-loader");
11
+ Object.defineProperty(exports, "loadContracts", { enumerable: true, get: function () { return contract_loader_1.loadContracts; } });
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2CAAkD;AAAzC,gHAAA,kBAAkB,OAAA;AAC3B,mCAA0C;AAAjC,wGAAA,cAAc,OAAA;AACvB,qDAAmD;AAA1C,iHAAA,cAAc,OAAA;AACvB,qDAAkD;AAAzC,gHAAA,aAAa,OAAA"}
@@ -0,0 +1,13 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ import { MiddlewareOptions } from './types/options';
3
+ import { ContractEngine } from './engine';
4
+ declare global {
5
+ namespace Express {
6
+ interface Request {
7
+ _contractEngine?: ContractEngine;
8
+ }
9
+ }
10
+ }
11
+ export declare function contractMiddleware(options: MiddlewareOptions): (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
12
+ export declare function getContractEngine(req: Request): ContractEngine | undefined;
13
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,eAAe,CAAC,EAAE,cAAc,CAAC;SAClC;KACF;CACF;AAKD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,IAW7C,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,6DAkE9D;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAE1E"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.contractMiddleware = contractMiddleware;
4
+ exports.getContractEngine = getContractEngine;
5
+ const engine_1 = require("./engine");
6
+ // Shared engine instance across all requests
7
+ let sharedEngine = null;
8
+ function contractMiddleware(options) {
9
+ // Create shared engine instance only once
10
+ if (!sharedEngine) {
11
+ sharedEngine = new engine_1.ContractEngine(options.mode);
12
+ // Load contracts asynchronously
13
+ sharedEngine.loadContracts(options.contractsPath).catch(error => {
14
+ console.error('Failed to load contracts:', error);
15
+ });
16
+ }
17
+ return async (req, res, next) => {
18
+ req._contractEngine = sharedEngine;
19
+ // Validate request
20
+ const requestViolations = sharedEngine.validateRequest(req.method, req.path, req);
21
+ if (requestViolations.some((v) => v.severity === 'error')) {
22
+ // Block invalid requests in all modes
23
+ const violation = requestViolations.find((v) => v.severity === 'error');
24
+ return res.status(400).json({
25
+ error: 'Request validation failed',
26
+ message: violation.message,
27
+ contract: violation.contractPath
28
+ });
29
+ }
30
+ // Store original send method
31
+ const originalSend = res.send;
32
+ const originalJson = res.json;
33
+ const originalStatus = res.status;
34
+ let responseSent = false;
35
+ let responseStatus = 200;
36
+ let responseBody = null;
37
+ // Override status to capture status code
38
+ res.status = function (code) {
39
+ responseStatus = code;
40
+ return originalStatus.call(this, code);
41
+ };
42
+ // Override json to capture response body
43
+ res.json = function (body) {
44
+ if (!responseSent) {
45
+ responseBody = body;
46
+ responseSent = true;
47
+ // Validate response
48
+ sharedEngine.validateResponse(req.method, req.path, responseStatus, body);
49
+ }
50
+ return originalJson.call(this, body);
51
+ };
52
+ // Override send to capture response body
53
+ res.send = function (body) {
54
+ if (!responseSent) {
55
+ responseBody = body;
56
+ responseSent = true;
57
+ // Try to parse JSON, otherwise treat as raw response
58
+ let parsedBody = body;
59
+ if (typeof body === 'string') {
60
+ try {
61
+ parsedBody = JSON.parse(body);
62
+ }
63
+ catch {
64
+ // Keep as string
65
+ }
66
+ }
67
+ // Validate response
68
+ sharedEngine.validateResponse(req.method, req.path, responseStatus, parsedBody);
69
+ }
70
+ return originalSend.call(this, body);
71
+ };
72
+ next();
73
+ };
74
+ }
75
+ function getContractEngine(req) {
76
+ return req._contractEngine;
77
+ }
78
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export interface Contract {
2
+ method: string;
3
+ path: string;
4
+ auth?: string;
5
+ request?: {
6
+ body?: Record<string, any>;
7
+ query?: Record<string, any>;
8
+ params?: Record<string, any>;
9
+ headers?: Record<string, any>;
10
+ };
11
+ response?: Record<string, any>;
12
+ errors?: Record<string, any>;
13
+ }
14
+ export interface RequestContract {
15
+ body?: Record<string, any>;
16
+ query?: Record<string, any>;
17
+ params?: Record<string, any>;
18
+ headers?: Record<string, any>;
19
+ }
20
+ export interface ResponseContract {
21
+ [statusCode: string]: Record<string, any>;
22
+ }
23
+ export interface ErrorContract {
24
+ [statusCode: string]: Record<string, any>;
25
+ }
26
+ //# sourceMappingURL=contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/types/contract.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC3B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC5B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAC/B,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3C"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/types/contract.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ export interface MiddlewareOptions {
2
+ contractsPath: string;
3
+ mode: 'dev' | 'strict' | 'ci';
4
+ port?: number;
5
+ }
6
+ export type ValidationMode = 'dev' | 'strict' | 'ci';
7
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/types/options.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,QAAQ,GAAG,IAAI,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/types/options.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ export interface Violation {
2
+ id: string;
3
+ timestamp: Date;
4
+ type: 'request' | 'response' | 'error';
5
+ contractPath: string;
6
+ endpoint: {
7
+ method: string;
8
+ path: string;
9
+ };
10
+ expected: any;
11
+ actual: any;
12
+ message: string;
13
+ severity: 'error' | 'warning';
14
+ }
15
+ export interface ValidationResult {
16
+ isValid: boolean;
17
+ violations: Violation[];
18
+ }
19
+ //# sourceMappingURL=violation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"violation.d.ts","sourceRoot":"","sources":["../../src/types/violation.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,QAAQ,EAAE,GAAG,CAAC;IACd,MAAM,EAAE,GAAG,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=violation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"violation.js","sourceRoot":"","sources":["../../src/types/violation.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import { Contract } from './types/contract';
2
+ import { ValidationResult } from './types/violation';
3
+ export declare class ValidationEngine {
4
+ private createSchema;
5
+ private createTypeSchema;
6
+ validateRequest(contract: Contract, req: any): ValidationResult;
7
+ validateResponse(contract: Contract, statusCode: number, body: any): ValidationResult;
8
+ validateError(contract: Contract, statusCode: number, body: any): ValidationResult;
9
+ }
10
+ //# sourceMappingURL=validation-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-engine.d.ts","sourceRoot":"","sources":["../src/validation-engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAqC,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAa,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEhE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,YAAY;IA2BpB,OAAO,CAAC,gBAAgB;IA+BxB,eAAe,CACb,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,GACP,gBAAgB;IA6BnB,gBAAgB,CACd,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,GAAG,GACR,gBAAgB;IA2BnB,aAAa,CACX,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,GAAG,GACR,gBAAgB;CA0BpB"}
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidationEngine = void 0;
4
+ const zod_1 = require("zod");
5
+ class ValidationEngine {
6
+ createSchema(obj) {
7
+ if (!obj || typeof obj !== 'object') {
8
+ return zod_1.z.any();
9
+ }
10
+ const shape = {};
11
+ for (const [key, value] of Object.entries(obj)) {
12
+ if (typeof value === 'object' && value !== null) {
13
+ if (value.type) {
14
+ // Handle type-based schema
15
+ shape[key] = this.createTypeSchema(value);
16
+ }
17
+ else {
18
+ // Handle nested object
19
+ shape[key] = this.createSchema(value);
20
+ }
21
+ }
22
+ else if (typeof value === 'string') {
23
+ // Simple string type
24
+ shape[key] = zod_1.z.string();
25
+ }
26
+ else {
27
+ shape[key] = zod_1.z.any();
28
+ }
29
+ }
30
+ return zod_1.z.object(shape);
31
+ }
32
+ createTypeSchema(config) {
33
+ let schema;
34
+ switch (config.type) {
35
+ case 'string':
36
+ schema = zod_1.z.string();
37
+ if (config.minLength)
38
+ schema = schema.min(config.minLength);
39
+ if (config.maxLength)
40
+ schema = schema.max(config.maxLength);
41
+ break;
42
+ case 'number':
43
+ schema = zod_1.z.number();
44
+ if (config.minimum)
45
+ schema = schema.min(config.minimum);
46
+ if (config.maximum)
47
+ schema = schema.max(config.maximum);
48
+ break;
49
+ case 'boolean':
50
+ schema = zod_1.z.boolean();
51
+ break;
52
+ case 'array':
53
+ schema = zod_1.z.array(this.createTypeSchema(config.items || {}));
54
+ break;
55
+ default:
56
+ schema = zod_1.z.any();
57
+ }
58
+ if (config.required === false) {
59
+ schema = schema.optional();
60
+ }
61
+ return schema;
62
+ }
63
+ validateRequest(contract, req) {
64
+ const violations = [];
65
+ if (contract.request?.body) {
66
+ const bodySchema = this.createSchema(contract.request.body);
67
+ const result = bodySchema.safeParse(req.body);
68
+ if (!result.success) {
69
+ violations.push({
70
+ id: `req-${Date.now()}-${Math.random()}`,
71
+ timestamp: new Date(),
72
+ type: 'request',
73
+ contractPath: contract.path,
74
+ endpoint: { method: contract.method, path: contract.path },
75
+ expected: contract.request.body,
76
+ actual: req.body,
77
+ message: `Request body validation failed: ${result.error.message}`,
78
+ severity: 'error'
79
+ });
80
+ }
81
+ }
82
+ // TODO: Add query, params, headers validation
83
+ return {
84
+ isValid: violations.length === 0,
85
+ violations
86
+ };
87
+ }
88
+ validateResponse(contract, statusCode, body) {
89
+ const violations = [];
90
+ if (contract.response && contract.response[statusCode]) {
91
+ const responseSchema = this.createSchema(contract.response[statusCode]);
92
+ const result = responseSchema.safeParse(body);
93
+ if (!result.success) {
94
+ violations.push({
95
+ id: `res-${Date.now()}-${Math.random()}`,
96
+ timestamp: new Date(),
97
+ type: 'response',
98
+ contractPath: contract.path,
99
+ endpoint: { method: contract.method, path: contract.path },
100
+ expected: contract.response[statusCode],
101
+ actual: body,
102
+ message: `Response validation failed for status ${statusCode}: ${result.error.message}`,
103
+ severity: 'warning' // In dev mode, responses are warnings
104
+ });
105
+ }
106
+ }
107
+ return {
108
+ isValid: violations.length === 0,
109
+ violations
110
+ };
111
+ }
112
+ validateError(contract, statusCode, body) {
113
+ const violations = [];
114
+ if (contract.errors && contract.errors[statusCode]) {
115
+ const errorSchema = this.createSchema(contract.errors[statusCode]);
116
+ const result = errorSchema.safeParse(body);
117
+ if (!result.success) {
118
+ violations.push({
119
+ id: `err-${Date.now()}-${Math.random()}`,
120
+ timestamp: new Date(),
121
+ type: 'error',
122
+ contractPath: contract.path,
123
+ endpoint: { method: contract.method, path: contract.path },
124
+ expected: contract.errors[statusCode],
125
+ actual: body,
126
+ message: `Error validation failed for status ${statusCode}: ${result.error.message}`,
127
+ severity: 'warning'
128
+ });
129
+ }
130
+ }
131
+ return {
132
+ isValid: violations.length === 0,
133
+ violations
134
+ };
135
+ }
136
+ }
137
+ exports.ValidationEngine = ValidationEngine;
138
+ //# sourceMappingURL=validation-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-engine.js","sourceRoot":"","sources":["../src/validation-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { Violation } from './types/violation';
2
+ export declare class ViolationStore {
3
+ private violations;
4
+ private maxViolations;
5
+ add(violation: Violation): void;
6
+ getAll(): Violation[];
7
+ getByEndpoint(method: string, path: string): Violation[];
8
+ getByType(type: Violation['type']): Violation[];
9
+ clear(): void;
10
+ getStats(): {
11
+ total: number;
12
+ byType: Record<string, number>;
13
+ bySeverity: Record<string, number>;
14
+ };
15
+ }
16
+ //# sourceMappingURL=violation-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"violation-store.d.ts","sourceRoot":"","sources":["../src/violation-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,qBAAa,cAAc;IACzB,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,aAAa,CAAQ;IAE7B,GAAG,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAO/B,MAAM,IAAI,SAAS,EAAE;IAIrB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE;IAMxD,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,SAAS,EAAE;IAI/C,KAAK,IAAI,IAAI;IAIb,QAAQ;;;;;CAcT"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ViolationStore = void 0;
4
+ class ViolationStore {
5
+ constructor() {
6
+ this.violations = [];
7
+ this.maxViolations = 1000;
8
+ }
9
+ add(violation) {
10
+ this.violations.unshift(violation);
11
+ if (this.violations.length > this.maxViolations) {
12
+ this.violations = this.violations.slice(0, this.maxViolations);
13
+ }
14
+ }
15
+ getAll() {
16
+ return [...this.violations];
17
+ }
18
+ getByEndpoint(method, path) {
19
+ return this.violations.filter(v => v.endpoint.method === method && v.endpoint.path === path);
20
+ }
21
+ getByType(type) {
22
+ return this.violations.filter(v => v.type === type);
23
+ }
24
+ clear() {
25
+ this.violations = [];
26
+ }
27
+ getStats() {
28
+ const total = this.violations.length;
29
+ const byType = this.violations.reduce((acc, v) => {
30
+ acc[v.type] = (acc[v.type] || 0) + 1;
31
+ return acc;
32
+ }, {});
33
+ const bySeverity = this.violations.reduce((acc, v) => {
34
+ acc[v.severity] = (acc[v.severity] || 0) + 1;
35
+ return acc;
36
+ }, {});
37
+ return { total, byType, bySeverity };
38
+ }
39
+ }
40
+ exports.ViolationStore = ViolationStore;
41
+ //# sourceMappingURL=violation-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"violation-store.js","sourceRoot":"","sources":["../src/violation-store.ts"],"names":[],"mappings":";;;AAEA,MAAa,cAAc;IAA3B;QACU,eAAU,GAAgB,EAAE,CAAC;QAC7B,kBAAa,GAAG,IAAI,CAAC;IAyC/B,CAAC;IAvCC,GAAG,CAAC,SAAoB;QACtB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAChD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IAED,aAAa,CAAC,MAAc,EAAE,IAAY;QACxC,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAChC,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,IAAI,CACzD,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,IAAuB;QAC/B,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,KAAK;QACH,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;IACvB,CAAC;IAED,QAAQ;QACN,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YAC/C,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACrC,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAA4B,CAAC,CAAC;QAEjC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YACnD,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAC7C,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAA4B,CAAC,CAAC;QAEjC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACvC,CAAC;CACF;AA3CD,wCA2CC"}