json-function-engine 0.8.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 (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +509 -0
  3. package/dist/constants.d.ts +13 -0
  4. package/dist/constants.d.ts.map +1 -0
  5. package/dist/constants.js +18 -0
  6. package/dist/constants.js.map +1 -0
  7. package/dist/engine/Executor.d.ts +92 -0
  8. package/dist/engine/Executor.d.ts.map +1 -0
  9. package/dist/engine/Executor.js +260 -0
  10. package/dist/engine/Executor.js.map +1 -0
  11. package/dist/engine/FileLoader.d.ts +51 -0
  12. package/dist/engine/FileLoader.d.ts.map +1 -0
  13. package/dist/engine/FileLoader.js +195 -0
  14. package/dist/engine/FileLoader.js.map +1 -0
  15. package/dist/engine/Pipeline.d.ts +54 -0
  16. package/dist/engine/Pipeline.d.ts.map +1 -0
  17. package/dist/engine/Pipeline.js +91 -0
  18. package/dist/engine/Pipeline.js.map +1 -0
  19. package/dist/engine/actions/BlockAction.d.ts +3 -0
  20. package/dist/engine/actions/BlockAction.d.ts.map +1 -0
  21. package/dist/engine/actions/BlockAction.js +13 -0
  22. package/dist/engine/actions/BlockAction.js.map +1 -0
  23. package/dist/engine/actions/FlagAction.d.ts +3 -0
  24. package/dist/engine/actions/FlagAction.d.ts.map +1 -0
  25. package/dist/engine/actions/FlagAction.js +29 -0
  26. package/dist/engine/actions/FlagAction.js.map +1 -0
  27. package/dist/engine/actions/NotifyAction.d.ts +3 -0
  28. package/dist/engine/actions/NotifyAction.d.ts.map +1 -0
  29. package/dist/engine/actions/NotifyAction.js +13 -0
  30. package/dist/engine/actions/NotifyAction.js.map +1 -0
  31. package/dist/engine/actions/TransformAction.d.ts +3 -0
  32. package/dist/engine/actions/TransformAction.d.ts.map +1 -0
  33. package/dist/engine/actions/TransformAction.js +13 -0
  34. package/dist/engine/actions/TransformAction.js.map +1 -0
  35. package/dist/engine/actions/index.d.ts +5 -0
  36. package/dist/engine/actions/index.d.ts.map +1 -0
  37. package/dist/engine/actions/index.js +5 -0
  38. package/dist/engine/actions/index.js.map +1 -0
  39. package/dist/engine/conditions/ArrayCondition.d.ts +3 -0
  40. package/dist/engine/conditions/ArrayCondition.d.ts.map +1 -0
  41. package/dist/engine/conditions/ArrayCondition.js +47 -0
  42. package/dist/engine/conditions/ArrayCondition.js.map +1 -0
  43. package/dist/engine/conditions/ComparisonCondition.d.ts +3 -0
  44. package/dist/engine/conditions/ComparisonCondition.d.ts.map +1 -0
  45. package/dist/engine/conditions/ComparisonCondition.js +42 -0
  46. package/dist/engine/conditions/ComparisonCondition.js.map +1 -0
  47. package/dist/engine/conditions/CompositeCondition.d.ts +3 -0
  48. package/dist/engine/conditions/CompositeCondition.d.ts.map +1 -0
  49. package/dist/engine/conditions/CompositeCondition.js +50 -0
  50. package/dist/engine/conditions/CompositeCondition.js.map +1 -0
  51. package/dist/engine/conditions/ExistsCondition.d.ts +3 -0
  52. package/dist/engine/conditions/ExistsCondition.d.ts.map +1 -0
  53. package/dist/engine/conditions/ExistsCondition.js +14 -0
  54. package/dist/engine/conditions/ExistsCondition.js.map +1 -0
  55. package/dist/engine/conditions/MathCondition.d.ts +3 -0
  56. package/dist/engine/conditions/MathCondition.d.ts.map +1 -0
  57. package/dist/engine/conditions/MathCondition.js +30 -0
  58. package/dist/engine/conditions/MathCondition.js.map +1 -0
  59. package/dist/engine/conditions/RegexCondition.d.ts +3 -0
  60. package/dist/engine/conditions/RegexCondition.d.ts.map +1 -0
  61. package/dist/engine/conditions/RegexCondition.js +10 -0
  62. package/dist/engine/conditions/RegexCondition.js.map +1 -0
  63. package/dist/engine/conditions/helpers.d.ts +3 -0
  64. package/dist/engine/conditions/helpers.d.ts.map +1 -0
  65. package/dist/engine/conditions/helpers.js +14 -0
  66. package/dist/engine/conditions/helpers.js.map +1 -0
  67. package/dist/engine/conditions/index.d.ts +7 -0
  68. package/dist/engine/conditions/index.d.ts.map +1 -0
  69. package/dist/engine/conditions/index.js +7 -0
  70. package/dist/engine/conditions/index.js.map +1 -0
  71. package/dist/engine/engine.d.ts +151 -0
  72. package/dist/engine/engine.d.ts.map +1 -0
  73. package/dist/engine/engine.js +246 -0
  74. package/dist/engine/engine.js.map +1 -0
  75. package/dist/engine/guards.d.ts +22 -0
  76. package/dist/engine/guards.d.ts.map +1 -0
  77. package/dist/engine/guards.js +84 -0
  78. package/dist/engine/guards.js.map +1 -0
  79. package/dist/engine/registry.d.ts +23 -0
  80. package/dist/engine/registry.d.ts.map +1 -0
  81. package/dist/engine/registry.js +93 -0
  82. package/dist/engine/registry.js.map +1 -0
  83. package/dist/engine/reporters/index.d.ts +12 -0
  84. package/dist/engine/reporters/index.d.ts.map +1 -0
  85. package/dist/engine/reporters/index.js +146 -0
  86. package/dist/engine/reporters/index.js.map +1 -0
  87. package/dist/index.d.ts +21 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +20 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/types/index.d.ts +204 -0
  92. package/dist/types/index.d.ts.map +1 -0
  93. package/dist/types/index.js +27 -0
  94. package/dist/types/index.js.map +1 -0
  95. package/dist/utils/cache.d.ts +17 -0
  96. package/dist/utils/cache.d.ts.map +1 -0
  97. package/dist/utils/cache.js +52 -0
  98. package/dist/utils/cache.js.map +1 -0
  99. package/dist/utils/errors.d.ts +45 -0
  100. package/dist/utils/errors.d.ts.map +1 -0
  101. package/dist/utils/errors.js +84 -0
  102. package/dist/utils/errors.js.map +1 -0
  103. package/dist/utils/factories.d.ts +23 -0
  104. package/dist/utils/factories.d.ts.map +1 -0
  105. package/dist/utils/factories.js +63 -0
  106. package/dist/utils/factories.js.map +1 -0
  107. package/dist/utils/metrics.d.ts +75 -0
  108. package/dist/utils/metrics.d.ts.map +1 -0
  109. package/dist/utils/metrics.js +99 -0
  110. package/dist/utils/metrics.js.map +1 -0
  111. package/dist/utils/regex.d.ts +33 -0
  112. package/dist/utils/regex.d.ts.map +1 -0
  113. package/dist/utils/regex.js +226 -0
  114. package/dist/utils/regex.js.map +1 -0
  115. package/dist/utils/schema.d.ts +7 -0
  116. package/dist/utils/schema.d.ts.map +1 -0
  117. package/dist/utils/schema.js +226 -0
  118. package/dist/utils/schema.js.map +1 -0
  119. package/package.json +50 -0
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Custom error types for json-function-engine
3
+ * Provides granular error handling for consumers
4
+ */
5
+ // Base error class
6
+ export class EngineError extends Error {
7
+ code;
8
+ cause;
9
+ constructor(message, code, cause) {
10
+ super(message);
11
+ this.code = code;
12
+ this.cause = cause;
13
+ this.name = 'EngineError';
14
+ Error.captureStackTrace(this, this.constructor);
15
+ }
16
+ }
17
+ // Validation errors
18
+ export class ValidationError extends EngineError {
19
+ field;
20
+ constructor(message, field, cause) {
21
+ super(message, 'VALIDATION_ERROR', cause);
22
+ this.field = field;
23
+ this.name = 'ValidationError';
24
+ }
25
+ }
26
+ // Function loading errors
27
+ export class FunctionLoadError extends EngineError {
28
+ path;
29
+ constructor(message, path, cause) {
30
+ super(message, 'FUNCTION_LOAD_ERROR', cause);
31
+ this.path = path;
32
+ this.name = 'FunctionLoadError';
33
+ }
34
+ }
35
+ // Function execution errors
36
+ export class FunctionExecutionError extends EngineError {
37
+ functionId;
38
+ file;
39
+ constructor(message, functionId, file, cause) {
40
+ super(message, 'FUNCTION_EXECUTION_ERROR', cause);
41
+ this.functionId = functionId;
42
+ this.file = file;
43
+ this.name = 'FunctionExecutionError';
44
+ }
45
+ }
46
+ // Timeout errors
47
+ export class TimeoutError extends EngineError {
48
+ functionId;
49
+ timeoutMs;
50
+ constructor(message, functionId, timeoutMs) {
51
+ super(message, 'TIMEOUT_ERROR');
52
+ this.functionId = functionId;
53
+ this.timeoutMs = timeoutMs;
54
+ this.name = 'TimeoutError';
55
+ }
56
+ }
57
+ // File errors
58
+ export class FileError extends EngineError {
59
+ path;
60
+ constructor(message, path, cause) {
61
+ super(message, 'FILE_ERROR', cause);
62
+ this.path = path;
63
+ this.name = 'FileError';
64
+ }
65
+ }
66
+ // Configuration errors
67
+ export class ConfigurationError extends EngineError {
68
+ constructor(message, cause) {
69
+ super(message, 'CONFIGURATION_ERROR', cause);
70
+ this.name = 'ConfigurationError';
71
+ }
72
+ }
73
+ // Registry errors (unknown condition/action types)
74
+ export class RegistryError extends EngineError {
75
+ type;
76
+ availableTypes;
77
+ constructor(message, type, availableTypes) {
78
+ super(message, 'REGISTRY_ERROR');
79
+ this.type = type;
80
+ this.availableTypes = availableTypes;
81
+ this.name = 'RegistryError';
82
+ }
83
+ }
84
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mBAAmB;AACnB,MAAM,OAAO,WAAY,SAAQ,KAAK;IAGlB;IACA;IAHlB,YACE,OAAe,EACC,IAAY,EACZ,KAAa;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAQ;QACZ,UAAK,GAAL,KAAK,CAAQ;QAG7B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;CACF;AAED,oBAAoB;AACpB,MAAM,OAAO,eAAgB,SAAQ,WAAW;IACD;IAA7C,YAAY,OAAe,EAAkB,KAAc,EAAE,KAAa;QACxE,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,KAAK,CAAC,CAAC;QADC,UAAK,GAAL,KAAK,CAAS;QAEzD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,0BAA0B;AAC1B,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IAG9B;IAFlB,YACE,OAAe,EACC,IAAa,EAC7B,KAAa;QAEb,KAAK,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,CAAC,CAAC;QAH7B,SAAI,GAAJ,IAAI,CAAS;QAI7B,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,4BAA4B;AAC5B,MAAM,OAAO,sBAAuB,SAAQ,WAAW;IAGnC;IACA;IAHlB,YACE,OAAe,EACC,UAAmB,EACnB,IAAa,EAC7B,KAAa;QAEb,KAAK,CAAC,OAAO,EAAE,0BAA0B,EAAE,KAAK,CAAC,CAAC;QAJlC,eAAU,GAAV,UAAU,CAAS;QACnB,SAAI,GAAJ,IAAI,CAAS;QAI7B,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,iBAAiB;AACjB,MAAM,OAAO,YAAa,SAAQ,WAAW;IAGzB;IACA;IAHlB,YACE,OAAe,EACC,UAAmB,EACnB,SAAkB;QAElC,KAAK,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAHhB,eAAU,GAAV,UAAU,CAAS;QACnB,cAAS,GAAT,SAAS,CAAS;QAGlC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,cAAc;AACd,MAAM,OAAO,SAAU,SAAQ,WAAW;IAGtB;IAFlB,YACE,OAAe,EACC,IAAa,EAC7B,KAAa;QAEb,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;QAHpB,SAAI,GAAJ,IAAI,CAAS;QAI7B,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,uBAAuB;AACvB,MAAM,OAAO,kBAAmB,SAAQ,WAAW;IACjD,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,mDAAmD;AACnD,MAAM,OAAO,aAAc,SAAQ,WAAW;IAG1B;IACA;IAHlB,YACE,OAAe,EACC,IAAa,EACb,cAAyB;QAEzC,KAAK,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;QAHjB,SAAI,GAAJ,IAAI,CAAS;QACb,mBAAc,GAAd,cAAc,CAAW;QAGzC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ import type { FileSystem, Logger } from '../types/index.js';
2
+ /**
3
+ * Create a default FileSystem implementation using Node.js fs
4
+ */
5
+ export declare function createDefaultFileSystem(): FileSystem;
6
+ /**
7
+ * Create a default console-based logger
8
+ */
9
+ export declare function createDefaultLogger(): Logger;
10
+ /**
11
+ * Create a structured logger with timestamps and levels
12
+ */
13
+ export interface StructuredLoggerOptions {
14
+ prefix?: string;
15
+ includeTimestamp?: boolean;
16
+ includeLevel?: boolean;
17
+ }
18
+ export declare function createStructuredLogger(options?: StructuredLoggerOptions): Logger;
19
+ /**
20
+ * Create a no-op logger for testing or silent mode
21
+ */
22
+ export declare function createSilentLogger(): Logger;
23
+ //# sourceMappingURL=factories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factories.d.ts","sourceRoot":"","sources":["../../src/utils/factories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE5D;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,UAAU,CAgBpD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAM5C;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,uBAA4B,GAAG,MAAM,CAuBpF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAM3C"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Create a default FileSystem implementation using Node.js fs
3
+ */
4
+ export function createDefaultFileSystem() {
5
+ return {
6
+ readFile: async (path, encoding) => {
7
+ const { readFile } = await import('fs/promises');
8
+ return readFile(path, encoding);
9
+ },
10
+ readdir: async (path) => {
11
+ const { readdir } = await import('fs/promises');
12
+ return readdir(path);
13
+ },
14
+ stat: async (path) => {
15
+ const { stat } = await import('fs/promises');
16
+ const stats = await stat(path);
17
+ return { isDirectory: () => stats.isDirectory() };
18
+ }
19
+ };
20
+ }
21
+ /**
22
+ * Create a default console-based logger
23
+ */
24
+ export function createDefaultLogger() {
25
+ return {
26
+ warn: (message, ...args) => console.warn(message, ...args),
27
+ info: (message, ...args) => console.info(message, ...args),
28
+ error: (message, ...args) => console.error(message, ...args)
29
+ };
30
+ }
31
+ export function createStructuredLogger(options = {}) {
32
+ const { prefix = '', includeTimestamp = true, includeLevel = true } = options;
33
+ const formatMessage = (level, message) => {
34
+ const parts = [];
35
+ if (includeTimestamp) {
36
+ parts.push(new Date().toISOString());
37
+ }
38
+ if (includeLevel) {
39
+ parts.push(level.toUpperCase());
40
+ }
41
+ if (prefix) {
42
+ parts.push(prefix);
43
+ }
44
+ parts.push(message);
45
+ return parts.join(' | ');
46
+ };
47
+ return {
48
+ warn: (message, ...args) => console.warn(formatMessage('warn', message), ...args),
49
+ info: (message, ...args) => console.info(formatMessage('info', message), ...args),
50
+ error: (message, ...args) => console.error(formatMessage('error', message), ...args)
51
+ };
52
+ }
53
+ /**
54
+ * Create a no-op logger for testing or silent mode
55
+ */
56
+ export function createSilentLogger() {
57
+ return {
58
+ warn: () => { },
59
+ info: () => { },
60
+ error: () => { }
61
+ };
62
+ }
63
+ //# sourceMappingURL=factories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factories.js","sourceRoot":"","sources":["../../src/utils/factories.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Metrics collected during engine execution
3
+ */
4
+ export interface EngineMetrics {
5
+ totalDurationMs: number;
6
+ loadDurationMs: number;
7
+ executeDurationMs: number;
8
+ filesProcessed: number;
9
+ functionsExecuted: number;
10
+ functionsEnabled: number;
11
+ findingsCount: number;
12
+ findingsBySeverity: Record<string, number>;
13
+ cacheHits: number;
14
+ cacheMisses: number;
15
+ errorsCount: number;
16
+ blockedCount: number;
17
+ }
18
+ /**
19
+ * Metrics collector interface
20
+ */
21
+ export interface MetricsCollector {
22
+ /**
23
+ * Record the start of an operation
24
+ */
25
+ startTimer(operation: string): () => void;
26
+ /**
27
+ * Increment a counter
28
+ */
29
+ increment(counter: string, value?: number): void;
30
+ /**
31
+ * Set a gauge value
32
+ */
33
+ gauge(gauge: string, value: number): void;
34
+ /**
35
+ * Record a histogram value
36
+ */
37
+ histogram(histogram: string, value: number): void;
38
+ /**
39
+ * Get all collected metrics
40
+ */
41
+ getMetrics(): EngineMetrics;
42
+ /**
43
+ * Reset all metrics
44
+ */
45
+ reset(): void;
46
+ }
47
+ /**
48
+ * Default in-memory metrics collector
49
+ */
50
+ export declare class DefaultMetricsCollector implements MetricsCollector {
51
+ private counters;
52
+ private gauges;
53
+ private histograms;
54
+ private timers;
55
+ constructor();
56
+ startTimer(operation: string): () => void;
57
+ increment(counter: string, value?: number): void;
58
+ gauge(gauge: string, value: number): void;
59
+ histogram(histogram: string, value: number): void;
60
+ getMetrics(): EngineMetrics;
61
+ reset(): void;
62
+ _setTimer(name: string, value: number): void;
63
+ }
64
+ /**
65
+ * No-op metrics collector for when metrics are not needed
66
+ */
67
+ export declare class NoOpMetricsCollector implements MetricsCollector {
68
+ startTimer(): () => void;
69
+ increment(): void;
70
+ gauge(): void;
71
+ histogram(): void;
72
+ getMetrics(): EngineMetrics;
73
+ reset(): void;
74
+ }
75
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/utils/metrics.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,aAAa;IAE5B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAG1B,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IAGtB,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAG3C,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IAGpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAE1C;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjD;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1C;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAElD;;OAEG;IACH,UAAU,IAAI,aAAa,CAAC;IAE5B;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;GAEG;AACH,qBAAa,uBAAwB,YAAW,gBAAgB;IAC9D,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,MAAM,CAAkC;;IAMhD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,IAAI;IAQzC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,IAAI;IAKnD,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIzC,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAYjD,UAAU,IAAI,aAAa;IAyB3B,KAAK,IAAI,IAAI;IAQb,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;CAG7C;AAED;;GAEG;AACH,qBAAa,oBAAqB,YAAW,gBAAgB;IAC3D,UAAU,IAAI,MAAM,IAAI;IAGxB,SAAS,IAAI,IAAI;IACjB,KAAK,IAAI,IAAI;IACb,SAAS,IAAI,IAAI;IACjB,UAAU,IAAI,aAAa;IAgB3B,KAAK,IAAI,IAAI;CACd"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Default in-memory metrics collector
3
+ */
4
+ export class DefaultMetricsCollector {
5
+ counters = new Map();
6
+ gauges = new Map();
7
+ histograms = new Map();
8
+ timers = new Map();
9
+ constructor() {
10
+ this.reset();
11
+ }
12
+ startTimer(operation) {
13
+ const start = performance.now();
14
+ return () => {
15
+ const duration = performance.now() - start;
16
+ this.histogram(`${operation}DurationMs`, duration);
17
+ };
18
+ }
19
+ increment(counter, value = 1) {
20
+ const current = this.counters.get(counter) || 0;
21
+ this.counters.set(counter, current + value);
22
+ }
23
+ gauge(gauge, value) {
24
+ this.gauges.set(gauge, value);
25
+ }
26
+ histogram(histogram, value) {
27
+ const values = this.histograms.get(histogram) || [];
28
+ // Bounded histogram - keep only last 1000 values (sliding window)
29
+ const MAX_HISTOGRAM_SIZE = 1000;
30
+ if (values.length >= MAX_HISTOGRAM_SIZE) {
31
+ // Remove oldest 10% when full
32
+ values.splice(0, Math.floor(MAX_HISTOGRAM_SIZE * 0.1));
33
+ }
34
+ values.push(value);
35
+ this.histograms.set(histogram, values);
36
+ }
37
+ getMetrics() {
38
+ const getCount = (key) => this.counters.get(key) || 0;
39
+ return {
40
+ totalDurationMs: this.timers.get('total') || 0,
41
+ loadDurationMs: this.timers.get('load') || 0,
42
+ executeDurationMs: this.timers.get('execute') || 0,
43
+ filesProcessed: getCount('filesProcessed'),
44
+ functionsExecuted: getCount('functionsExecuted'),
45
+ functionsEnabled: getCount('functionsEnabled'),
46
+ findingsCount: getCount('findings'),
47
+ findingsBySeverity: {
48
+ critical: getCount('findings.critical'),
49
+ high: getCount('findings.high'),
50
+ medium: getCount('findings.medium'),
51
+ low: getCount('findings.low'),
52
+ info: getCount('findings.info')
53
+ },
54
+ cacheHits: getCount('cacheHits'),
55
+ cacheMisses: getCount('cacheMisses'),
56
+ errorsCount: getCount('errors'),
57
+ blockedCount: getCount('blocked')
58
+ };
59
+ }
60
+ reset() {
61
+ this.counters.clear();
62
+ this.gauges.clear();
63
+ this.histograms.clear();
64
+ this.timers.clear();
65
+ }
66
+ // Internal method to set timer values
67
+ _setTimer(name, value) {
68
+ this.timers.set(name, value);
69
+ }
70
+ }
71
+ /**
72
+ * No-op metrics collector for when metrics are not needed
73
+ */
74
+ export class NoOpMetricsCollector {
75
+ startTimer() {
76
+ return () => { };
77
+ }
78
+ increment() { }
79
+ gauge() { }
80
+ histogram() { }
81
+ getMetrics() {
82
+ return {
83
+ totalDurationMs: 0,
84
+ loadDurationMs: 0,
85
+ executeDurationMs: 0,
86
+ filesProcessed: 0,
87
+ functionsExecuted: 0,
88
+ functionsEnabled: 0,
89
+ findingsCount: 0,
90
+ findingsBySeverity: {},
91
+ cacheHits: 0,
92
+ cacheMisses: 0,
93
+ errorsCount: 0,
94
+ blockedCount: 0
95
+ };
96
+ }
97
+ reset() { }
98
+ }
99
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/utils/metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { RegexConditionConfig, ConditionResult, FileInput, ExecutionContext } from '../types/index.js';
2
+ /**
3
+ * Validate regex pattern for complexity and known ReDoS patterns
4
+ * @throws Error if pattern is invalid or potentially dangerous
5
+ */
6
+ export declare function validateRegexPattern(pattern: string): void;
7
+ /**
8
+ * Clear the regex cache
9
+ */
10
+ export declare function clearRegexCache(): void;
11
+ /**
12
+ * Get the number of cached regex patterns
13
+ */
14
+ export declare function getRegexCacheSize(): number;
15
+ /**
16
+ * Compile a regex pattern with validation
17
+ * @throws Error if pattern is invalid or potentially dangerous
18
+ */
19
+ export declare function compileRegex(pattern: string, _timeoutMs?: number): RegExp;
20
+ /**
21
+ * Evaluate a regex condition against a file with timeout protection
22
+ * @throws Error if regex execution times out
23
+ */
24
+ export declare function evaluateRegexCondition(config: RegexConditionConfig, _context: ExecutionContext, file: FileInput): ConditionResult;
25
+ export declare function matchFileExtension(filePath: string, extensions?: string[]): boolean;
26
+ export declare function runWithTimeout<T>(promise: Promise<T>, timeoutMs: number, errorMessage: string): Promise<T>;
27
+ export declare function getSeverityWeight(severity: string): number;
28
+ export interface FunctionFilterOptions {
29
+ include?: string[];
30
+ exclude?: string[];
31
+ }
32
+ export declare function filterFunctionsByPattern(functions: import('../types/index.js').FunctionDefinition[], include?: string[], exclude?: string[]): import('../types/index.js').FunctionDefinition[];
33
+ //# sourceMappingURL=regex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex.d.ts","sourceRoot":"","sources":["../../src/utils/regex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAyB5G;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CA8C1D;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,GAAE,MAA2B,GAAG,MAAM,CAgB7F;AAQD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,SAAS,GACd,eAAe,CAsEjB;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,OAAO,CAUT;AAED,wBAAsB,cAAc,CAAC,CAAC,EACpC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,CAAC,CAAC,CAgBZ;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAS1D;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,OAAO,mBAAmB,EAAE,kBAAkB,EAAE,EAC3D,OAAO,GAAE,MAAM,EAAO,EACtB,OAAO,GAAE,MAAM,EAAO,GACrB,OAAO,mBAAmB,EAAE,kBAAkB,EAAE,CAoClD"}
@@ -0,0 +1,226 @@
1
+ import { DEFAULT_TIMEOUT_MS, MAX_REGEX_CACHE_SIZE } from '../constants.js';
2
+ import { LRUCache } from './cache.js';
3
+ const regexCache = new LRUCache(MAX_REGEX_CACHE_SIZE);
4
+ // Regex complexity limits
5
+ const MAX_PATTERN_LENGTH = 500;
6
+ const MAX_PATTERN_GROUPS = 10;
7
+ const MAX_PATTERN_ALTERNATIONS = 10;
8
+ // Known ReDoS patterns - patterns that can cause catastrophic backtracking
9
+ const REDOS_PATTERNS = [
10
+ { pattern: /\(\.\*\)\+/, message: 'Unbounded quantifier after group' },
11
+ { pattern: /\(\.\+\)\+/, message: 'Unbounded quantifier after group' },
12
+ { pattern: /\(\.\?\)\+/, message: 'Unbounded quantifier after group' },
13
+ { pattern: /\(\.\*\)\*/, message: 'Nested quantifier' },
14
+ { pattern: /\(\.\+\)\*/, message: 'Nested quantifier' },
15
+ { pattern: /\(\.\?\)\*/, message: 'Nested quantifier' },
16
+ { pattern: /\(\[^\]]+\]\+\)\+/, message: 'Character class with nested quantifier' },
17
+ { pattern: /\(\.\{[^}]+\}\)\+/, message: 'Quantifier after group with quantifier' },
18
+ { pattern: /\(\w\+\)\+/, message: 'Word character with nested quantifier' },
19
+ { pattern: /\(\d\+\)\+/, message: 'Digit with nested quantifier' },
20
+ ];
21
+ /**
22
+ * Validate regex pattern for complexity and known ReDoS patterns
23
+ * @throws Error if pattern is invalid or potentially dangerous
24
+ */
25
+ export function validateRegexPattern(pattern) {
26
+ // Check length
27
+ if (pattern.length > MAX_PATTERN_LENGTH) {
28
+ throw new Error(`Regex pattern exceeds maximum length of ${MAX_PATTERN_LENGTH} characters. ` +
29
+ `Pattern length: ${pattern.length}`);
30
+ }
31
+ // Check for known ReDoS patterns
32
+ for (const { pattern: redosPattern, message } of REDOS_PATTERNS) {
33
+ if (redosPattern.test(pattern)) {
34
+ throw new Error(`Regex pattern contains potentially dangerous construct: ${message}. ` +
35
+ 'This pattern may cause catastrophic backtracking on certain inputs.');
36
+ }
37
+ }
38
+ // Count groups
39
+ const groupMatches = pattern.match(/\((?!\?)/g);
40
+ const groupCount = groupMatches ? groupMatches.length : 0;
41
+ if (groupCount > MAX_PATTERN_GROUPS) {
42
+ throw new Error(`Regex pattern has too many capturing groups (${groupCount}). ` +
43
+ `Maximum allowed: ${MAX_PATTERN_GROUPS}`);
44
+ }
45
+ // Count alternations
46
+ const alternationMatches = pattern.match(/\|/g);
47
+ const alternationCount = alternationMatches ? alternationMatches.length : 0;
48
+ if (alternationCount > MAX_PATTERN_ALTERNATIONS) {
49
+ throw new Error(`Regex pattern has too many alternations (${alternationCount}). ` +
50
+ `Maximum allowed: ${MAX_PATTERN_ALTERNATIONS}`);
51
+ }
52
+ // Check for nested quantifiers on same character
53
+ const nestedQuantifierPattern = /[.+*][.+*]+/g;
54
+ if (nestedQuantifierPattern.test(pattern)) {
55
+ throw new Error('Regex pattern contains nested quantifiers which may cause catastrophic backtracking.');
56
+ }
57
+ }
58
+ /**
59
+ * Clear the regex cache
60
+ */
61
+ export function clearRegexCache() {
62
+ regexCache.clear();
63
+ }
64
+ /**
65
+ * Get the number of cached regex patterns
66
+ */
67
+ export function getRegexCacheSize() {
68
+ return regexCache.size();
69
+ }
70
+ /**
71
+ * Compile a regex pattern with validation
72
+ * @throws Error if pattern is invalid or potentially dangerous
73
+ */
74
+ export function compileRegex(pattern, _timeoutMs = DEFAULT_TIMEOUT_MS) {
75
+ // Validate pattern first
76
+ validateRegexPattern(pattern);
77
+ const cached = regexCache.get(pattern);
78
+ if (cached) {
79
+ return cached;
80
+ }
81
+ try {
82
+ const regex = new RegExp(pattern);
83
+ regexCache.set(pattern, regex);
84
+ return regex;
85
+ }
86
+ catch (error) {
87
+ throw new Error(`Invalid regex pattern: ${pattern}`);
88
+ }
89
+ }
90
+ /**
91
+ * Maximum time (ms) allowed for regex evaluation per line
92
+ * Prevents ReDoS by limiting execution time
93
+ */
94
+ const MAX_REGEX_TIME_PER_LINE_MS = 100;
95
+ /**
96
+ * Evaluate a regex condition against a file with timeout protection
97
+ * @throws Error if regex execution times out
98
+ */
99
+ export function evaluateRegexCondition(config, _context, file) {
100
+ const { pattern, matchAll = false } = config;
101
+ // Validate and compile regex (includes ReDoS pattern validation)
102
+ const regex = compileRegex(pattern);
103
+ const lines = file.content.split('\n');
104
+ const matches = [];
105
+ const startTime = performance.now();
106
+ for (let i = 0; i < lines.length; i++) {
107
+ // Check timeout every line
108
+ const elapsed = performance.now() - startTime;
109
+ const timePerLine = elapsed / (i + 1);
110
+ const estimatedTotal = timePerLine * lines.length;
111
+ // If we're exceeding per-line limit or estimated total exceeds limit, throw
112
+ if (timePerLine > MAX_REGEX_TIME_PER_LINE_MS || estimatedTotal > MAX_REGEX_TIME_PER_LINE_MS * lines.length) {
113
+ throw new Error(`Regex evaluation timed out: pattern '${pattern}' is taking too long. ` +
114
+ `This may indicate a catastrophic backtracking issue. ` +
115
+ `Processed ${i + 1} of ${lines.length} lines.`);
116
+ }
117
+ const line = lines[i];
118
+ const match = line.match(regex);
119
+ if (match) {
120
+ if (matchAll) {
121
+ let regexMatch;
122
+ let lineMatchCount = 0;
123
+ const lineStartTime = performance.now();
124
+ while ((regexMatch = regex.exec(line)) !== null) {
125
+ // Check timeout every 100 matches per line
126
+ lineMatchCount++;
127
+ if (lineMatchCount % 100 === 0 && performance.now() - lineStartTime > MAX_REGEX_TIME_PER_LINE_MS) {
128
+ throw new Error(`Regex evaluation timed out on line ${i + 1}: too many matches. ` +
129
+ `This may indicate a catastrophic backtracking issue.`);
130
+ }
131
+ const matchIdx = regexMatch.index;
132
+ matches.push({
133
+ line: i + 1,
134
+ column: matchIdx + 1,
135
+ text: regexMatch[0]
136
+ });
137
+ if (regexMatch[0].length === 0) {
138
+ // Prevent infinite loop on zero-length matches
139
+ break;
140
+ }
141
+ }
142
+ }
143
+ else {
144
+ const matchIdx = match.index ?? 0;
145
+ matches.push({
146
+ line: i + 1,
147
+ column: matchIdx + 1,
148
+ text: match[0]
149
+ });
150
+ }
151
+ }
152
+ }
153
+ return {
154
+ matched: matches.length > 0,
155
+ matches
156
+ };
157
+ }
158
+ export function matchFileExtension(filePath, extensions) {
159
+ if (!extensions || extensions.length === 0) {
160
+ return true;
161
+ }
162
+ const path = filePath.toLowerCase();
163
+ return extensions.some(ext => {
164
+ const normalizedExt = ext.startsWith('.') ? ext.toLowerCase() : `.${ext.toLowerCase()}`;
165
+ return path.endsWith(normalizedExt);
166
+ });
167
+ }
168
+ export async function runWithTimeout(promise, timeoutMs, errorMessage) {
169
+ let timeoutHandle;
170
+ const timeoutPromise = new Promise((_, reject) => {
171
+ timeoutHandle = setTimeout(() => {
172
+ reject(new Error(errorMessage));
173
+ }, timeoutMs);
174
+ });
175
+ try {
176
+ return await Promise.race([promise, timeoutPromise]);
177
+ }
178
+ finally {
179
+ if (timeoutHandle !== undefined) {
180
+ clearTimeout(timeoutHandle);
181
+ }
182
+ }
183
+ }
184
+ export function getSeverityWeight(severity) {
185
+ const weights = {
186
+ critical: 5,
187
+ high: 4,
188
+ medium: 3,
189
+ low: 2,
190
+ info: 1
191
+ };
192
+ return weights[severity] ?? 0;
193
+ }
194
+ export function filterFunctionsByPattern(functions, include = [], exclude = []) {
195
+ const result = [];
196
+ for (const fn of functions) {
197
+ const id = fn.id.toLowerCase();
198
+ // Check exclude patterns first
199
+ let excluded = false;
200
+ for (const pattern of exclude) {
201
+ const regex = compileRegex(pattern.toLowerCase());
202
+ if (regex.test(id)) {
203
+ excluded = true;
204
+ break;
205
+ }
206
+ }
207
+ if (excluded) {
208
+ continue;
209
+ }
210
+ // If no include patterns, include all
211
+ if (include.length === 0) {
212
+ result.push(fn);
213
+ continue;
214
+ }
215
+ // Check include patterns
216
+ for (const pattern of include) {
217
+ const regex = compileRegex(pattern.toLowerCase());
218
+ if (regex.test(id)) {
219
+ result.push(fn);
220
+ break;
221
+ }
222
+ }
223
+ }
224
+ return result;
225
+ }
226
+ //# sourceMappingURL=regex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex.js","sourceRoot":"","sources":["../../src/utils/regex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface SchemaError {
2
+ path: string;
3
+ message: string;
4
+ }
5
+ export declare function validateFunctionSet(data: unknown): SchemaError[];
6
+ export {};
7
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"AAKA,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,EAAE,CAsChE"}