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,151 @@
1
+ import type { FunctionDefinition, FileInput, ExecutionContext, EngineOptions, Finding, LoadResult, FileSystem, Logger } from '../types/index.js';
2
+ import { Registry } from './registry.js';
3
+ import { FileLoader } from './FileLoader.js';
4
+ import { Executor } from './Executor.js';
5
+ import { type MetricsCollector } from '../utils/metrics.js';
6
+ /**
7
+ * Error policy for execution behavior
8
+ */
9
+ export type ErrorPolicy = 'best-effort' | 'fail-fast';
10
+ /**
11
+ * Execution result with detailed error information
12
+ */
13
+ export interface ExecutionResult {
14
+ findings: Finding[];
15
+ errors: Array<{
16
+ functionId: string;
17
+ file: string;
18
+ error: string;
19
+ phase: 'condition' | 'action';
20
+ }>;
21
+ success: boolean;
22
+ }
23
+ /**
24
+ * Dependencies for Engine constructor (for dependency injection)
25
+ */
26
+ export interface EngineDependencies {
27
+ /** Custom registry instance */
28
+ registry?: Registry;
29
+ /** Custom file system implementation */
30
+ fileSystem?: FileSystem;
31
+ /** Custom logger implementation */
32
+ logger?: Logger;
33
+ /** Custom file loader implementation */
34
+ fileLoader?: FileLoader;
35
+ /** Custom executor implementation */
36
+ executor?: Executor;
37
+ /** Custom metrics collector implementation */
38
+ metrics?: MetricsCollector;
39
+ /** Error policy: 'best-effort' continues on errors, 'fail-fast' throws immediately */
40
+ errorPolicy?: ErrorPolicy;
41
+ }
42
+ /**
43
+ * Main entry point for the JSON Function Engine.
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const engine = new Engine({ timeout: 5000, parallel: true });
48
+ * await engine.loadFunctions('./functions.json');
49
+ * const findings = await engine.execute(files, { cwd: '.' });
50
+ * const output = engine.format(findings, 'json', { pretty: true });
51
+ * ```
52
+ */
53
+ export declare class Engine {
54
+ private functions;
55
+ private registry;
56
+ private fileSystem;
57
+ private logger;
58
+ private fileLoader;
59
+ private executor;
60
+ private options;
61
+ private errorPolicy;
62
+ constructor(options?: EngineOptions, dependencies?: EngineDependencies);
63
+ /**
64
+ * Get the file loader instance for custom configuration
65
+ * @returns FileLoader instance
66
+ */
67
+ getFileLoader(): FileLoader;
68
+ /**
69
+ * Get the executor instance for pipeline hooks and advanced control
70
+ * @returns Executor instance
71
+ */
72
+ getExecutor(): Executor;
73
+ /**
74
+ * Get execution metrics from the last run
75
+ * @returns MetricsCollector with execution statistics
76
+ */
77
+ getMetrics(): MetricsCollector;
78
+ /**
79
+ * Get execution errors from the last run
80
+ * @returns Array of classified errors with functionId, file, error, phase, and type
81
+ */
82
+ getErrors(): Array<{
83
+ functionId: string;
84
+ file: string;
85
+ error: string;
86
+ phase: 'condition' | 'action';
87
+ type: string;
88
+ }>;
89
+ /**
90
+ * Get the registry for registering custom conditions, actions, or reporters
91
+ * @returns Registry instance
92
+ */
93
+ getRegistry(): Registry;
94
+ /**
95
+ * Get all loaded functions from the engine
96
+ * @returns Array of FunctionDefinition objects
97
+ */
98
+ getFunctions(): FunctionDefinition[];
99
+ /**
100
+ * Get the count of loaded functions
101
+ * @returns Number of functions currently loaded
102
+ */
103
+ getFunctionCount(): number;
104
+ /**
105
+ * Add functions directly to the engine (useful for testing and programmatic use)
106
+ * @param functions Array of function definitions to add
107
+ */
108
+ addFunctions(functions: FunctionDefinition[]): void;
109
+ /**
110
+ * Clear all functions from the engine
111
+ */
112
+ clear(): void;
113
+ /**
114
+ * Set the error policy for execution
115
+ * @param policy 'best-effort' continues on errors, 'fail-fast' throws immediately
116
+ */
117
+ setErrorPolicy(policy: ErrorPolicy): void;
118
+ /**
119
+ * Get the current error policy
120
+ */
121
+ getErrorPolicy(): ErrorPolicy;
122
+ /**
123
+ * Load functions from JSON files
124
+ */
125
+ loadFunctions(paths: string | string[], options?: EngineOptions): Promise<LoadResult>;
126
+ execute(files: FileInput[], context?: ExecutionContext): Promise<Finding[]>;
127
+ /**
128
+ * Execute with best-effort policy - collects errors and continues
129
+ */
130
+ private executeBestEffort;
131
+ /**
132
+ * Validate all loaded function definitions
133
+ * @throws ValidationError if any function definition is invalid
134
+ */
135
+ private validateFunctions;
136
+ /**
137
+ * Deduplicate findings based on functionId, file, line, and column
138
+ */
139
+ private deduplicateFindings;
140
+ format(findings: Finding[], format: 'json' | 'text' | 'html' | 'sarif', options?: {
141
+ pretty?: boolean;
142
+ theme?: 'light' | 'dark';
143
+ version?: string;
144
+ }): string | Promise<string>;
145
+ scan(files: FileInput[], format?: 'json' | 'text' | 'html' | 'sarif', context?: ExecutionContext, formatOptions?: {
146
+ pretty?: boolean;
147
+ theme?: 'light' | 'dark';
148
+ version?: string;
149
+ }): Promise<string>;
150
+ }
151
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/engine/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,246 @@
1
+ import { Registry } from './registry.js';
2
+ import { FileLoader } from './FileLoader.js';
3
+ import { Executor } from './Executor.js';
4
+ import { getSeverityWeight } from '../utils/regex.js';
5
+ import { DEFAULT_TIMEOUT_MS } from '../constants.js';
6
+ import { createDefaultFileSystem, createDefaultLogger } from '../utils/factories.js';
7
+ import { ValidationError, ConfigurationError } from '../utils/errors.js';
8
+ /**
9
+ * Main entry point for the JSON Function Engine.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const engine = new Engine({ timeout: 5000, parallel: true });
14
+ * await engine.loadFunctions('./functions.json');
15
+ * const findings = await engine.execute(files, { cwd: '.' });
16
+ * const output = engine.format(findings, 'json', { pretty: true });
17
+ * ```
18
+ */
19
+ export class Engine {
20
+ functions = [];
21
+ registry;
22
+ fileSystem;
23
+ logger;
24
+ fileLoader;
25
+ executor;
26
+ options;
27
+ errorPolicy;
28
+ constructor(options = {}, dependencies = {}) {
29
+ // Validate options
30
+ if (options.timeout !== undefined && options.timeout <= 0) {
31
+ throw new ConfigurationError('timeout must be a positive number');
32
+ }
33
+ if (options.parallel !== undefined && typeof options.parallel !== 'boolean') {
34
+ throw new ConfigurationError('parallel must be a boolean');
35
+ }
36
+ if (options.include !== undefined && !Array.isArray(options.include)) {
37
+ throw new ConfigurationError('include must be an array');
38
+ }
39
+ if (options.exclude !== undefined && !Array.isArray(options.exclude)) {
40
+ throw new ConfigurationError('exclude must be an array');
41
+ }
42
+ this.registry = dependencies.registry ?? new Registry();
43
+ this.fileSystem = dependencies.fileSystem ?? createDefaultFileSystem();
44
+ this.logger = dependencies.logger ?? createDefaultLogger();
45
+ this.fileLoader = dependencies.fileLoader ?? new FileLoader({
46
+ fileSystem: this.fileSystem,
47
+ logger: this.logger
48
+ });
49
+ this.executor = dependencies.executor ?? new Executor({ registry: this.registry, logger: this.logger }, { timeout: options.timeout, parallel: options.parallel });
50
+ this.options = {
51
+ include: options.include || [],
52
+ exclude: options.exclude || [],
53
+ timeout: options.timeout || DEFAULT_TIMEOUT_MS,
54
+ parallel: options.parallel ?? true
55
+ };
56
+ this.errorPolicy = dependencies.errorPolicy ?? 'best-effort';
57
+ }
58
+ /**
59
+ * Get the file loader instance for custom configuration
60
+ * @returns FileLoader instance
61
+ */
62
+ getFileLoader() {
63
+ return this.fileLoader;
64
+ }
65
+ /**
66
+ * Get the executor instance for pipeline hooks and advanced control
67
+ * @returns Executor instance
68
+ */
69
+ getExecutor() {
70
+ return this.executor;
71
+ }
72
+ /**
73
+ * Get execution metrics from the last run
74
+ * @returns MetricsCollector with execution statistics
75
+ */
76
+ getMetrics() {
77
+ return this.executor.getMetrics();
78
+ }
79
+ /**
80
+ * Get execution errors from the last run
81
+ * @returns Array of classified errors with functionId, file, error, phase, and type
82
+ */
83
+ getErrors() {
84
+ return this.executor.getErrors();
85
+ }
86
+ /**
87
+ * Get the registry for registering custom conditions, actions, or reporters
88
+ * @returns Registry instance
89
+ */
90
+ getRegistry() {
91
+ return this.registry;
92
+ }
93
+ /**
94
+ * Get all loaded functions from the engine
95
+ * @returns Array of FunctionDefinition objects
96
+ */
97
+ getFunctions() {
98
+ return this.functions;
99
+ }
100
+ /**
101
+ * Get the count of loaded functions
102
+ * @returns Number of functions currently loaded
103
+ */
104
+ getFunctionCount() {
105
+ return this.functions.length;
106
+ }
107
+ /**
108
+ * Add functions directly to the engine (useful for testing and programmatic use)
109
+ * @param functions Array of function definitions to add
110
+ */
111
+ addFunctions(functions) {
112
+ this.functions = [...this.functions, ...functions];
113
+ }
114
+ /**
115
+ * Clear all functions from the engine
116
+ */
117
+ clear() {
118
+ this.functions = [];
119
+ this.fileLoader.clearCache();
120
+ }
121
+ /**
122
+ * Set the error policy for execution
123
+ * @param policy 'best-effort' continues on errors, 'fail-fast' throws immediately
124
+ */
125
+ setErrorPolicy(policy) {
126
+ this.errorPolicy = policy;
127
+ }
128
+ /**
129
+ * Get the current error policy
130
+ */
131
+ getErrorPolicy() {
132
+ return this.errorPolicy;
133
+ }
134
+ /**
135
+ * Load functions from JSON files
136
+ */
137
+ async loadFunctions(paths, options) {
138
+ const mergedOptions = { ...this.options, ...options };
139
+ // Use FileLoader to load and parse files
140
+ const result = await this.fileLoader.load(paths, {
141
+ include: mergedOptions.include,
142
+ exclude: mergedOptions.exclude
143
+ });
144
+ // Best-effort: collect errors but continue (strict mode removed)
145
+ this.functions = result.functions;
146
+ return { loaded: result.loaded, errors: result.errors };
147
+ }
148
+ async execute(files, context = { cwd: process.cwd() }) {
149
+ // Validate function definitions before execution
150
+ this.validateFunctions();
151
+ // Check for cancellation before starting
152
+ if (context.signal?.aborted) {
153
+ const error = new Error('The operation was cancelled');
154
+ error.name = 'AbortError';
155
+ throw error;
156
+ }
157
+ // Best-effort: continue on errors
158
+ return this.executeBestEffort(files, context);
159
+ }
160
+ /**
161
+ * Execute with best-effort policy - collects errors and continues
162
+ */
163
+ async executeBestEffort(files, context) {
164
+ // Set up abort listener if signal provided
165
+ let abortHandler = null;
166
+ if (context.signal) {
167
+ abortHandler = () => {
168
+ this.executor.cancel();
169
+ };
170
+ context.signal.addEventListener('abort', abortHandler);
171
+ }
172
+ try {
173
+ // Filter to enabled functions and apply framework filtering
174
+ let enabledFunctions = this.functions.filter(f => f.enabled !== false);
175
+ // Apply framework filtering if context has a framework specified
176
+ if (context.framework) {
177
+ enabledFunctions = enabledFunctions.filter(f => {
178
+ if (f.frameworks && f.frameworks.length > 0) {
179
+ return f.frameworks.includes(context.framework);
180
+ }
181
+ return true;
182
+ });
183
+ }
184
+ // Sort by priority
185
+ enabledFunctions = [...enabledFunctions].sort((a, b) => (a.priority ?? 999) - (b.priority ?? 999));
186
+ // Use Executor to run the functions - best-effort is default in Executor
187
+ const findings = await this.executor.execute(enabledFunctions, files, context);
188
+ // Deduplicate findings
189
+ const uniqueFindings = this.deduplicateFindings(findings);
190
+ // Sort by severity
191
+ return uniqueFindings.sort((a, b) => getSeverityWeight(b.severity) - getSeverityWeight(a.severity));
192
+ }
193
+ finally {
194
+ // Clean up the listener after execution completes
195
+ if (abortHandler && context.signal) {
196
+ context.signal.removeEventListener('abort', abortHandler);
197
+ }
198
+ }
199
+ }
200
+ /**
201
+ * Validate all loaded function definitions
202
+ * @throws ValidationError if any function definition is invalid
203
+ */
204
+ validateFunctions() {
205
+ for (const fn of this.functions) {
206
+ if (!fn.id) {
207
+ throw new ValidationError('Function definition is missing required field: id', 'id');
208
+ }
209
+ if (!fn.condition) {
210
+ throw new ValidationError(`Function definition '${fn.id}' is missing required field: condition`, `functions.${fn.id}.condition`);
211
+ }
212
+ if (!fn.action) {
213
+ throw new ValidationError(`Function definition '${fn.id}' is missing required field: action`, `functions.${fn.id}.action`);
214
+ }
215
+ if (fn.condition && !fn.condition.type) {
216
+ throw new ValidationError(`Function definition '${fn.id}' condition is missing required field: type`, `functions.${fn.id}.condition.type`);
217
+ }
218
+ if (fn.action && !fn.action.type) {
219
+ throw new ValidationError(`Function definition '${fn.id}' action is missing required field: type`, `functions.${fn.id}.action.type`);
220
+ }
221
+ }
222
+ }
223
+ /**
224
+ * Deduplicate findings based on functionId, file, line, and column
225
+ */
226
+ deduplicateFindings(findings) {
227
+ const seen = new Set();
228
+ const unique = [];
229
+ for (const finding of findings) {
230
+ const key = `${finding.functionId}:${finding.location.file}:${finding.location.line}:${finding.location.column ?? 0}`;
231
+ if (!seen.has(key)) {
232
+ seen.add(key);
233
+ unique.push(finding);
234
+ }
235
+ }
236
+ return unique;
237
+ }
238
+ format(findings, format, options) {
239
+ return this.registry.format(findings, format, options);
240
+ }
241
+ async scan(files, format = 'json', context, formatOptions) {
242
+ const findings = await this.execute(files, context);
243
+ return this.format(findings, format, formatOptions);
244
+ }
245
+ }
246
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/engine/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { ConditionConfig, RegexConditionConfig, ComparisonConditionConfig, ExistsConditionConfig, CompositeConditionConfig, MathConditionConfig, ArrayConditionConfig, ActionConfig, FlagActionConfig, BlockActionConfig, TransformActionConfig, NotifyActionConfig } from '../types/index.js';
2
+ export declare function isRegexCondition(config: ConditionConfig): config is RegexConditionConfig;
3
+ export declare function isComparisonCondition(config: ConditionConfig): config is ComparisonConditionConfig;
4
+ export declare function isExistsCondition(config: ConditionConfig): config is ExistsConditionConfig;
5
+ export declare function isCompositeCondition(config: ConditionConfig): config is CompositeConditionConfig;
6
+ export declare function isMathCondition(config: ConditionConfig): config is MathConditionConfig;
7
+ export declare function isArrayCondition(config: ConditionConfig): config is ArrayConditionConfig;
8
+ export declare function isFlagAction(config: ActionConfig): config is FlagActionConfig;
9
+ export declare function isBlockAction(config: ActionConfig): config is BlockActionConfig;
10
+ export declare function isTransformAction(config: ActionConfig): config is TransformActionConfig;
11
+ export declare function isNotifyAction(config: ActionConfig): config is NotifyActionConfig;
12
+ export declare function assertRegexCondition(config: ConditionConfig): asserts config is RegexConditionConfig;
13
+ export declare function assertComparisonCondition(config: ConditionConfig): asserts config is ComparisonConditionConfig;
14
+ export declare function assertExistsCondition(config: ConditionConfig): asserts config is ExistsConditionConfig;
15
+ export declare function assertCompositeCondition(config: ConditionConfig): asserts config is CompositeConditionConfig;
16
+ export declare function assertMathCondition(config: ConditionConfig): asserts config is MathConditionConfig;
17
+ export declare function assertArrayCondition(config: ConditionConfig): asserts config is ArrayConditionConfig;
18
+ export declare function assertFlagAction(config: ActionConfig): asserts config is FlagActionConfig;
19
+ export declare function assertBlockAction(config: ActionConfig): asserts config is BlockActionConfig;
20
+ export declare function assertTransformAction(config: ActionConfig): asserts config is TransformActionConfig;
21
+ export declare function assertNotifyAction(config: ActionConfig): asserts config is NotifyActionConfig;
22
+ //# sourceMappingURL=guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/engine/guards.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAG3B,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,IAAI,oBAAoB,CAExF;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,IAAI,yBAAyB,CAElG;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,IAAI,qBAAqB,CAE1F;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,IAAI,wBAAwB,CAEhG;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,IAAI,mBAAmB,CAEtF;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,IAAI,oBAAoB,CAExF;AAGD,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,IAAI,gBAAgB,CAE7E;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,IAAI,iBAAiB,CAE/E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,IAAI,qBAAqB,CAEvF;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,IAAI,kBAAkB,CAEjF;AAGD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,IAAI,oBAAoB,CAIpG;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,IAAI,yBAAyB,CAI9G;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,IAAI,qBAAqB,CAItG;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,IAAI,wBAAwB,CAI5G;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,IAAI,mBAAmB,CAIlG;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,IAAI,oBAAoB,CAIpG;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,IAAI,gBAAgB,CAIzF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,IAAI,iBAAiB,CAI3F;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,IAAI,qBAAqB,CAInG;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,IAAI,kBAAkB,CAI7F"}
@@ -0,0 +1,84 @@
1
+ // Condition type guards
2
+ export function isRegexCondition(config) {
3
+ return config.type === 'regex';
4
+ }
5
+ export function isComparisonCondition(config) {
6
+ return config.type === 'comparison';
7
+ }
8
+ export function isExistsCondition(config) {
9
+ return config.type === 'exists';
10
+ }
11
+ export function isCompositeCondition(config) {
12
+ return config.type === 'composite';
13
+ }
14
+ export function isMathCondition(config) {
15
+ return config.type === 'math';
16
+ }
17
+ export function isArrayCondition(config) {
18
+ return config.type === 'array';
19
+ }
20
+ // Action type guards
21
+ export function isFlagAction(config) {
22
+ return config.type === 'flag';
23
+ }
24
+ export function isBlockAction(config) {
25
+ return config.type === 'block';
26
+ }
27
+ export function isTransformAction(config) {
28
+ return config.type === 'transform';
29
+ }
30
+ export function isNotifyAction(config) {
31
+ return config.type === 'notify';
32
+ }
33
+ // Assert functions for type narrowing with throw
34
+ export function assertRegexCondition(config) {
35
+ if (!isRegexCondition(config)) {
36
+ throw new Error(`Expected regex condition, got ${config.type}`);
37
+ }
38
+ }
39
+ export function assertComparisonCondition(config) {
40
+ if (!isComparisonCondition(config)) {
41
+ throw new Error(`Expected comparison condition, got ${config.type}`);
42
+ }
43
+ }
44
+ export function assertExistsCondition(config) {
45
+ if (!isExistsCondition(config)) {
46
+ throw new Error(`Expected exists condition, got ${config.type}`);
47
+ }
48
+ }
49
+ export function assertCompositeCondition(config) {
50
+ if (!isCompositeCondition(config)) {
51
+ throw new Error(`Expected composite condition, got ${config.type}`);
52
+ }
53
+ }
54
+ export function assertMathCondition(config) {
55
+ if (!isMathCondition(config)) {
56
+ throw new Error(`Expected math condition, got ${config.type}`);
57
+ }
58
+ }
59
+ export function assertArrayCondition(config) {
60
+ if (!isArrayCondition(config)) {
61
+ throw new Error(`Expected array condition, got ${config.type}`);
62
+ }
63
+ }
64
+ export function assertFlagAction(config) {
65
+ if (!isFlagAction(config)) {
66
+ throw new Error(`Expected flag action, got ${config.type}`);
67
+ }
68
+ }
69
+ export function assertBlockAction(config) {
70
+ if (!isBlockAction(config)) {
71
+ throw new Error(`Expected block action, got ${config.type}`);
72
+ }
73
+ }
74
+ export function assertTransformAction(config) {
75
+ if (!isTransformAction(config)) {
76
+ throw new Error(`Expected transform action, got ${config.type}`);
77
+ }
78
+ }
79
+ export function assertNotifyAction(config) {
80
+ if (!isNotifyAction(config)) {
81
+ throw new Error(`Expected notify action, got ${config.type}`);
82
+ }
83
+ }
84
+ //# sourceMappingURL=guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.js","sourceRoot":"","sources":["../../src/engine/guards.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { ConditionDefinition, ActionDefinition, ReporterDefinition, ConditionConfig, ActionConfig, ReporterFormat, ExecutionContext, FileInput, ConditionResult, ActionResult, Finding, FormatOptions } from '../types/index.js';
2
+ export declare class Registry {
3
+ private conditions;
4
+ private actions;
5
+ private reporters;
6
+ constructor();
7
+ private registerBuiltInConditions;
8
+ private registerBuiltInActions;
9
+ private registerBuiltInReporters;
10
+ registerCondition(name: string, definition: ConditionDefinition): void;
11
+ registerAction(name: string, definition: ActionDefinition): void;
12
+ registerReporter(name: string, definition: ReporterDefinition): void;
13
+ hasCondition(type: string): boolean;
14
+ hasAction(type: string): boolean;
15
+ hasReporter(type: string): boolean;
16
+ evaluateCondition(config: ConditionConfig, context: ExecutionContext, file: FileInput): Promise<ConditionResult>;
17
+ executeAction(config: ActionConfig, context: ExecutionContext, conditionResult: ConditionResult, file: FileInput): Promise<ActionResult>;
18
+ format(findings: Finding[], format: ReporterFormat, options?: FormatOptions): string | Promise<string>;
19
+ getConditionNames(): string[];
20
+ getActionNames(): string[];
21
+ getReporterNames(): string[];
22
+ }
23
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/engine/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,eAAe,EACf,YAAY,EACZ,OAAO,EACP,aAAa,EACd,MAAM,mBAAmB,CAAC;AAmB3B,qBAAa,QAAQ;IACnB,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,OAAO,CAA4C;IAC3D,OAAO,CAAC,SAAS,CAA8C;;IAQ/D,OAAO,CAAC,yBAAyB;IASjC,OAAO,CAAC,sBAAsB;IAO9B,OAAO,CAAC,wBAAwB;IAQhC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,mBAAmB,GAAG,IAAI;IAItE,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,GAAG,IAAI;IAIhE,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,GAAG,IAAI;IAIpE,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAInC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIhC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI5B,iBAAiB,CACrB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,CAAC;IAoBrB,aAAa,CACjB,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,gBAAgB,EACzB,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,YAAY,CAAC;IAcxB,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IActG,iBAAiB,IAAI,MAAM,EAAE;IAI7B,cAAc,IAAI,MAAM,EAAE;IAI1B,gBAAgB,IAAI,MAAM,EAAE;CAG7B"}
@@ -0,0 +1,93 @@
1
+ import { matchFileExtension } from '../utils/regex.js';
2
+ import { RegistryError } from '../utils/errors.js';
3
+ import { regexCondition, comparisonCondition, existsCondition, compositeCondition, mathCondition, arrayCondition } from './conditions/index.js';
4
+ import { flagAction, blockAction, transformAction, notifyAction } from './actions/index.js';
5
+ import { builtInReporters } from './reporters/index.js';
6
+ export class Registry {
7
+ conditions = new Map();
8
+ actions = new Map();
9
+ reporters = new Map();
10
+ constructor() {
11
+ this.registerBuiltInConditions();
12
+ this.registerBuiltInActions();
13
+ this.registerBuiltInReporters();
14
+ }
15
+ registerBuiltInConditions() {
16
+ this.registerCondition('regex', regexCondition);
17
+ this.registerCondition('comparison', comparisonCondition);
18
+ this.registerCondition('exists', existsCondition);
19
+ this.registerCondition('composite', compositeCondition);
20
+ this.registerCondition('math', mathCondition);
21
+ this.registerCondition('array', arrayCondition);
22
+ }
23
+ registerBuiltInActions() {
24
+ this.registerAction('flag', flagAction);
25
+ this.registerAction('block', blockAction);
26
+ this.registerAction('transform', transformAction);
27
+ this.registerAction('notify', notifyAction);
28
+ }
29
+ registerBuiltInReporters() {
30
+ // Register all built-in reporters from separate module
31
+ for (const [name, reporter] of Object.entries(builtInReporters)) {
32
+ this.registerReporter(name, reporter);
33
+ }
34
+ }
35
+ // Public methods for custom registration
36
+ registerCondition(name, definition) {
37
+ this.conditions.set(name, definition);
38
+ }
39
+ registerAction(name, definition) {
40
+ this.actions.set(name, definition);
41
+ }
42
+ registerReporter(name, definition) {
43
+ this.reporters.set(name, definition);
44
+ }
45
+ hasCondition(type) {
46
+ return this.conditions.has(type);
47
+ }
48
+ hasAction(type) {
49
+ return this.actions.has(type);
50
+ }
51
+ hasReporter(type) {
52
+ return this.reporters.has(type);
53
+ }
54
+ async evaluateCondition(config, context, file) {
55
+ // Check file extension filter
56
+ if (!matchFileExtension(file.path, config.fileExtensions)) {
57
+ return { matched: false };
58
+ }
59
+ const definition = this.conditions.get(config.type);
60
+ if (!definition) {
61
+ throw new RegistryError(`Unknown condition type: '${config.type}' for file '${file.path}'. ` +
62
+ `Available types: ${Array.from(this.conditions.keys()).join(', ')}`, config.type, Array.from(this.conditions.keys()));
63
+ }
64
+ // Pass registry reference to conditions that need it (like composite)
65
+ return definition.evaluate(config, context, file, this);
66
+ }
67
+ async executeAction(config, context, conditionResult, file) {
68
+ const definition = this.actions.get(config.type);
69
+ if (!definition) {
70
+ throw new RegistryError(`Unknown action type: '${config.type}' for file '${file.path}'. ` +
71
+ `Available types: ${Array.from(this.actions.keys()).join(', ')}`, config.type, Array.from(this.actions.keys()));
72
+ }
73
+ return definition.execute(config, context, conditionResult, file);
74
+ }
75
+ format(findings, format, options) {
76
+ const definition = this.reporters.get(format);
77
+ if (!definition) {
78
+ throw new RegistryError(`Unknown reporter format: '${format}'. ` +
79
+ `Available formats: ${Array.from(this.reporters.keys()).join(', ')}`, format, Array.from(this.reporters.keys()));
80
+ }
81
+ return definition.format(findings, options);
82
+ }
83
+ getConditionNames() {
84
+ return Array.from(this.conditions.keys());
85
+ }
86
+ getActionNames() {
87
+ return Array.from(this.actions.keys());
88
+ }
89
+ getReporterNames() {
90
+ return Array.from(this.reporters.keys());
91
+ }
92
+ }
93
+ //# sourceMappingURL=registry.js.map