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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Peter Williams
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,509 @@
1
+ # json-function-engine
2
+
3
+ A standalone JavaScript/TypeScript library for executing logic defined in JSON configuration files. Define functions, conditions, and actions in JSON — execute them against source code, JSON data, or any input. Lightweight, embeddable, and extensible.
4
+
5
+ ## Features
6
+
7
+ - **Define functions in JSON** - Express logic as conditions and actions in JSON
8
+ - **Execute against source files** - Scan codebases with regex, file filtering, and more
9
+ - **Extensible** - Register custom conditions, actions, and reporters
10
+ - **Multiple output formats** - JSON, Text, HTML, SARIF
11
+ - **Performance** - Regex caching, parallel execution, ReDoS protection
12
+ - **Zero runtime dependencies** - Keep your bundle small
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install json-function-engine
18
+ # or
19
+ pnpm add json-function-engine
20
+ # or
21
+ yarn add json-function-engine
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ```typescript
27
+ import { Engine } from 'json-function-engine';
28
+
29
+ const engine = new Engine();
30
+
31
+ // Define functions inline
32
+ const functions = {
33
+ version: "1.0",
34
+ functions: [
35
+ {
36
+ id: "NO_TODO",
37
+ name: "No TODO comments",
38
+ enabled: true,
39
+ priority: 1,
40
+ condition: {
41
+ type: "regex",
42
+ pattern: "TODO",
43
+ fileExtensions: [".ts", ".tsx"]
44
+ },
45
+ action: {
46
+ type: "flag",
47
+ severity: "info",
48
+ message: "TODO comment found"
49
+ }
50
+ }
51
+ ]
52
+ };
53
+
54
+ // Add functions to engine
55
+ engine.addFunctions(functions.functions);
56
+
57
+ // Execute against source files
58
+ const findings = await engine.execute([
59
+ { path: "src/auth.ts", content: "const TODO = 'implement auth';" }
60
+ ], { cwd: process.cwd() });
61
+
62
+ // Format output
63
+ console.log(engine.format(findings, "json", { pretty: true }));
64
+ ```
65
+
66
+ ## Your First Function
67
+
68
+ A 5-minute guide to creating and running your first function:
69
+
70
+ ### Step 1: Create a function definition file
71
+
72
+ Create `my-functions.json`:
73
+
74
+ ```json
75
+ {
76
+ "version": "1.0",
77
+ "functions": [
78
+ {
79
+ "id": "DETECT_SECRETS",
80
+ "name": "No hardcoded secrets",
81
+ "condition": {
82
+ "type": "regex",
83
+ "pattern": "(api_key|password|secret)\\s*[:=]\\s*['\"][^'\"]+['\"]",
84
+ "fileExtensions": [".ts", ".js", ".env"]
85
+ },
86
+ "action": {
87
+ "type": "flag",
88
+ "severity": "critical",
89
+ "message": "Potential hardcoded secret detected"
90
+ }
91
+ }
92
+ ]
93
+ }
94
+ ```
95
+
96
+ ### Step 2: Load and execute
97
+
98
+ ```typescript
99
+ import { Engine } from 'json-function-engine';
100
+
101
+ const engine = new Engine();
102
+
103
+ // Load functions from file
104
+ const result = await engine.loadFunctions('./my-functions.json');
105
+ console.log(`Loaded ${result.loaded} functions`);
106
+
107
+ // Execute against your codebase
108
+ const findings = await engine.execute([
109
+ { path: "src/config.ts", content: "const api_key = 'sk-1234567890';" }
110
+ ]);
111
+
112
+ // See results
113
+ console.log(engine.format(findings, 'text'));
114
+ ```
115
+
116
+ ### Step 3: Output in different formats
117
+
118
+ ```typescript
119
+ // JSON for programmatic use
120
+ const json = engine.format(findings, 'json');
121
+
122
+ // SARIF for GitHub Security
123
+ const sarif = engine.format(findings, 'sarif', { version: '2.1' });
124
+
125
+ // HTML report
126
+ const html = engine.format(findings, 'html', { theme: 'dark' });
127
+ ```
128
+
129
+ ## Usage with Attune
130
+
131
+ ```typescript
132
+ import { Engine } from 'json-function-engine';
133
+
134
+ const engine = new Engine();
135
+ const result = await engine.loadFunctions('./functions/*.json');
136
+
137
+ console.log(`Loaded ${result.loaded} functions (${result.errors.length} errors)`);
138
+
139
+ const findings = await engine.execute([
140
+ { path: 'src/index.ts', content: '...' }
141
+ ], { framework: 'nextjs' });
142
+
143
+ // Get SARIF output for GitHub Security
144
+ const sarif = engine.format(findings, 'sarif', { version: '2.1' });
145
+ ```
146
+
147
+ ## JSON Schema
148
+
149
+ Validate your function definitions using the JSON Schema:
150
+
151
+ ```json
152
+ {
153
+ "$schema": "https://json-function-engine.dev/schema/v1/functions.json",
154
+ "version": "1.0",
155
+ "rules": [...]
156
+ }
157
+ ```
158
+
159
+ Download the schema from [`schema/v1/functions.json`](schema/v1/functions.json) or use with VS Code:
160
+
161
+ ```json
162
+ {
163
+ "$schema": "./node_modules/json-function-engine/schema/v1/functions.json"
164
+ }
165
+ ```
166
+
167
+ ## Function Schema
168
+
169
+ ```json
170
+ {
171
+ "version": "1.0",
172
+ "functions": [
173
+ {
174
+ "id": "UNIQUE_FUNCTION_ID",
175
+ "name": "Human readable name",
176
+ "description": "What this function detects or does",
177
+ "enabled": true,
178
+ "priority": 1,
179
+ "frameworks": ["react", "vue"],
180
+ "condition": { ... },
181
+ "action": { ... }
182
+ }
183
+ ]
184
+ }
185
+ ```
186
+
187
+ ## Condition Types
188
+
189
+ | Type | Description |
190
+ |------|-------------|
191
+ | `regex` | Pattern matching |
192
+ | `comparison` | Value comparison (==, !=, >, <, contains, etc.) |
193
+ | `exists` | Field presence check |
194
+ | `composite` | AND/OR/NOT logic |
195
+
196
+ ### Regex Condition
197
+
198
+ ```json
199
+ {
200
+ "type": "regex",
201
+ "pattern": "TODO",
202
+ "matchAll": false,
203
+ "fileExtensions": [".ts", ".tsx"]
204
+ }
205
+ ```
206
+
207
+ ### Comparison Condition
208
+
209
+ ```json
210
+ {
211
+ "type": "comparison",
212
+ "operator": "==",
213
+ "field": "framework",
214
+ "value": "nextjs"
215
+ }
216
+ ```
217
+
218
+ ### Exists Condition
219
+
220
+ ```json
221
+ {
222
+ "type": "exists",
223
+ "field": "framework"
224
+ }
225
+ ```
226
+
227
+ ### Composite Condition
228
+
229
+ ```json
230
+ {
231
+ "type": "composite",
232
+ "operator": "AND",
233
+ "conditions": [
234
+ { "type": "regex", "pattern": "..." },
235
+ { "type": "exists", "field": "..." }
236
+ ]
237
+ }
238
+ ```
239
+
240
+ ## Action Types
241
+
242
+ | Type | Description |
243
+ |------|-------------|
244
+ | `flag` | Create a finding |
245
+ | `block` | Stop execution |
246
+ | `transform` | Modify a value |
247
+ | `notify` | Send an alert |
248
+
249
+ ### Flag Action
250
+
251
+ ```json
252
+ {
253
+ "type": "flag",
254
+ "severity": "high",
255
+ "message": "Issue description"
256
+ }
257
+ ```
258
+
259
+ ### Block Action
260
+
261
+ ```json
262
+ {
263
+ "type": "block",
264
+ "message": "Stopping execution",
265
+ "severity": "critical"
266
+ }
267
+ ```
268
+
269
+ ## Reporters
270
+
271
+ | Format | Description |
272
+ |--------|-------------|
273
+ | `json` | JSON output |
274
+ | `text` | Human-readable text |
275
+ | `html` | HTML report |
276
+ | `sarif` | SARIF for CI integration |
277
+
278
+ ## Extending the Engine
279
+
280
+ ### Custom Conditions
281
+
282
+ ```typescript
283
+ const engine = new Engine();
284
+ engine.getRegistry().registerCondition('fileExists', {
285
+ name: 'fileExists',
286
+ evaluate: async (config, context, file) => {
287
+ return {
288
+ matched: fs.existsSync(path.join(context.cwd, config.path))
289
+ };
290
+ }
291
+ });
292
+ ```
293
+
294
+ ### Custom Actions
295
+
296
+ ```typescript
297
+ engine.getRegistry().registerAction('slackNotify', {
298
+ name: 'slackNotify',
299
+ execute: async (config, context, matches, file) => {
300
+ await slack.webhook.send({ channel: config.channel, text: ... });
301
+ return { success: true, notified: true };
302
+ }
303
+ });
304
+ ```
305
+
306
+ ### Custom Reporters
307
+
308
+ ```typescript
309
+ engine.getRegistry().registerReporter('junit', {
310
+ name: 'JUnit',
311
+ format: (findings) => {
312
+ return `<?xml version="1.0"?>
313
+ <testsuite tests="${findings.length}">
314
+ ${findings.map(f => ` <testcase name="${f.message}"/>`).join('\n')}
315
+ </testsuite>`;
316
+ }
317
+ });
318
+ ```
319
+
320
+ ## API
321
+
322
+ ### Engine
323
+
324
+ ```typescript
325
+ const engine = new Engine(options?: EngineOptions)
326
+
327
+ // Load functions from file paths
328
+ const result = await engine.loadFunctions(paths: string | string[], options?: EngineOptions)
329
+ // Returns: { loaded: number, errors: Array<{ path: string, error: string }> }
330
+
331
+ // Add functions programmatically
332
+ engine.addFunctions(functions: Rule[])
333
+
334
+ // Get loaded function count
335
+ const count = engine.getFunctionCount()
336
+
337
+ // Inspect loaded functions
338
+ const functions = engine.getFunctions()
339
+
340
+ // Clear all functions
341
+ engine.clear()
342
+
343
+ // Execute functions against files
344
+ const findings = await engine.execute(files: FileInput[], context?: ExecutionContext)
345
+
346
+ // Format findings
347
+ const output = engine.format(findings: Finding[], format: ReporterFormat, options?: FormatOptions)
348
+
349
+ // Convenience method
350
+ const output = await engine.scan(files, format?, context?, formatOptions?)
351
+ ```
352
+
353
+ ### Options
354
+
355
+ ```typescript
356
+ interface EngineOptions {
357
+ include?: string[]; // Only include functions matching patterns
358
+ exclude?: string[]; // Exclude functions matching patterns
359
+ timeout?: number; // Timeout per function in ms (default: 5000)
360
+ parallel?: boolean; // Execute functions in parallel (default: true)
361
+ strict?: boolean; // Throw on errors instead of collecting them
362
+ }
363
+ ```
364
+
365
+ ## Execution Context
366
+
367
+ The execution context provides additional information during function execution:
368
+
369
+ ```typescript
370
+ interface ExecutionContext {
371
+ cwd: string; // Current working directory
372
+ framework?: string; // Target framework (e.g., 'nextjs', 'react')
373
+ signal?: AbortSignal; // Cancellation signal
374
+ [key: string]: unknown; // Custom context values
375
+ }
376
+ ```
377
+
378
+ ### Framework Filtering
379
+
380
+ Functions can be targeted to specific frameworks:
381
+
382
+ ```json
383
+ {
384
+ "id": "NEXTJS_ONLY",
385
+ "frameworks": ["nextjs"],
386
+ "condition": { "type": "regex", "pattern": "getServerSideProps" },
387
+ "action": { "type": "flag", "severity": "info", "message": "Server-side rendering detected" }
388
+ }
389
+ ```
390
+
391
+ When executing, specify the framework to run only matching functions:
392
+
393
+ ```typescript
394
+ const findings = await engine.execute(files, {
395
+ cwd: '.',
396
+ framework: 'nextjs' // Only runs functions that target nextjs or have no framework restriction
397
+ });
398
+ ```
399
+
400
+ ### Cancellation
401
+
402
+ Support cancellation via AbortSignal:
403
+
404
+ ```typescript
405
+ const controller = new AbortController();
406
+
407
+ const findings = await engine.execute(files, {
408
+ cwd: '.',
409
+ signal: controller.signal
410
+ });
411
+
412
+ // Cancel after timeout
413
+ setTimeout(() => controller.abort(), 5000);
414
+ ```
415
+
416
+ ### Metrics
417
+
418
+ Access execution metrics:
419
+
420
+ ```typescript
421
+ await engine.execute(files, { cwd: '.' });
422
+ const metrics = engine.getMetrics().getMetrics();
423
+
424
+ console.log({
425
+ functionsExecuted: metrics.functionsExecuted,
426
+ filesProcessed: metrics.filesProcessed,
427
+ findingsCount: metrics.findingsCount,
428
+ errorsCount: metrics.errorsCount,
429
+ findingsBySeverity: metrics.findingsBySeverity
430
+ });
431
+ ```
432
+
433
+ ### Error Aggregation
434
+
435
+ Get execution errors:
436
+
437
+ ```typescript
438
+ await engine.execute(files, { cwd: '.' });
439
+ const errors = engine.getErrors();
440
+
441
+ for (const error of errors) {
442
+ console.log(`Function ${error.functionId} on ${error.file}: ${error.error}`);
443
+ }
444
+ ```
445
+
446
+ ## Error Handling
447
+
448
+ ### Invalid JSON Files
449
+
450
+ If a JSON file is malformed, `loadFunctions()` will log a warning and continue:
451
+
452
+ ```typescript
453
+ const result = await engine.loadFunctions('./functions/*.json');
454
+ // If some files fail:
455
+ // result.loaded = 5 // successfully loaded
456
+ // result.errors = [{ path: './functions/bad.json', error: 'Unexpected token }' }]
457
+ ```
458
+
459
+ ### Invalid Regex Patterns
460
+
461
+ Invalid regex patterns in conditions are logged as warnings. The function is skipped:
462
+
463
+ ```json
464
+ {
465
+ "condition": {
466
+ "type": "regex",
467
+ "pattern": "[invalid("
468
+ }
469
+ }
470
+ // Warning: Invalid regex pattern in function INVALID_FUNC
471
+ ```
472
+
473
+ ### Duplicate Function IDs
474
+
475
+ When the same function ID is defined multiple times, later definitions override earlier ones. A warning is logged.
476
+
477
+ ### Timeout Handling
478
+
479
+ Each function has a configurable timeout (default: 5 seconds). If execution exceeds the timeout, it's terminated and a warning is logged:
480
+
481
+ ```typescript
482
+ const engine = new Engine({ timeout: 1000 }); // 1 second timeout
483
+ const findings = await engine.execute(files);
484
+ // If a function takes >1s, it's terminated and execution continues
485
+ ```
486
+
487
+ ## Performance
488
+
489
+ - **Bundle size**: < 15KB gzipped
490
+ - **Regex caching**: Compiled patterns are cached
491
+ - **ReDoS protection**: Configurable timeout per function (default: 5s)
492
+ - **Parallel execution**: Functions can run concurrently
493
+
494
+ ## Use Cases
495
+
496
+ | Use Case | Description |
497
+ |----------|-------------|
498
+ | Code scanning | Scan source for secrets, TODOs, patterns |
499
+ | Data validation | Validate API responses against functions |
500
+ | Config processing | Evaluate conditions in config files |
501
+ | Simple workflows | Conditional data pipelines |
502
+
503
+ ## Interested in Consolidating?
504
+
505
+ If you're a maintainer considering rolling similar functionality into your core package, I'm happy to point users your direction instead. Open an issue to discuss.
506
+
507
+ ## License
508
+
509
+ MIT
@@ -0,0 +1,13 @@
1
+ export declare const DEFAULT_TIMEOUT_MS = 5000;
2
+ export declare const MAX_REGEX_CACHE_SIZE = 1000;
3
+ export declare const SEVERITY_WEIGHTS: {
4
+ readonly critical: 5;
5
+ readonly high: 4;
6
+ readonly medium: 3;
7
+ readonly low: 2;
8
+ readonly info: 1;
9
+ };
10
+ export declare const DEFAULT_PARALLEL = true;
11
+ export declare const DEFAULT_INCLUDE_PATTERNS: string[];
12
+ export declare const DEFAULT_EXCLUDE_PATTERNS: string[];
13
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAGvC,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAGzC,eAAO,MAAM,gBAAgB;;;;;;CAMnB,CAAC;AAGX,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAGrC,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAAO,CAAC;AACrD,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAAO,CAAC"}
@@ -0,0 +1,18 @@
1
+ // Default timeout for function execution in milliseconds
2
+ export const DEFAULT_TIMEOUT_MS = 5000;
3
+ // Regex cache limits
4
+ export const MAX_REGEX_CACHE_SIZE = 1000;
5
+ // Severity weights for sorting findings (higher = more severe)
6
+ export const SEVERITY_WEIGHTS = {
7
+ critical: 5,
8
+ high: 4,
9
+ medium: 3,
10
+ low: 2,
11
+ info: 1
12
+ };
13
+ // Default parallel processing setting
14
+ export const DEFAULT_PARALLEL = true;
15
+ // File loading defaults
16
+ export const DEFAULT_INCLUDE_PATTERNS = [];
17
+ export const DEFAULT_EXCLUDE_PATTERNS = [];
18
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC,qBAAqB;AACrB,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAEzC,+DAA+D;AAC/D,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;CACC,CAAC;AAEX,sCAAsC;AACtC,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC,wBAAwB;AACxB,MAAM,CAAC,MAAM,wBAAwB,GAAa,EAAE,CAAC;AACrD,MAAM,CAAC,MAAM,wBAAwB,GAAa,EAAE,CAAC"}
@@ -0,0 +1,92 @@
1
+ import type { FunctionDefinition, FileInput, ExecutionContext, Finding, Logger } from '../types/index.js';
2
+ import type { Registry } from './registry.js';
3
+ import { Pipeline } from './Pipeline.js';
4
+ import { type MetricsCollector } from '../utils/metrics.js';
5
+ export interface ExecutorDependencies {
6
+ registry: Registry;
7
+ logger?: Logger;
8
+ metrics?: MetricsCollector;
9
+ }
10
+ export interface ExecutorOptions {
11
+ timeout?: number;
12
+ parallel?: boolean;
13
+ }
14
+ /**
15
+ * Classified error information
16
+ */
17
+ export interface ClassifiedError {
18
+ functionId: string;
19
+ file: string;
20
+ error: string;
21
+ phase: 'condition' | 'action';
22
+ type: 'validation' | 'timeout' | 'runtime' | 'unknown';
23
+ }
24
+ export declare class Executor {
25
+ private registry;
26
+ private logger;
27
+ private options;
28
+ private pipeline;
29
+ private metrics;
30
+ private errors;
31
+ private cancelled;
32
+ constructor(dependencies: ExecutorDependencies, options?: ExecutorOptions);
33
+ /**
34
+ * Cancel the current execution
35
+ */
36
+ cancel(): void;
37
+ /**
38
+ * Check if execution was cancelled
39
+ */
40
+ isCancelled(): boolean;
41
+ /**
42
+ * Reset cancelled state for next execution
43
+ */
44
+ private resetCancellation;
45
+ /**
46
+ * Get the execution pipeline
47
+ */
48
+ getPipeline(): Pipeline;
49
+ /**
50
+ * Execute functions against files
51
+ */
52
+ execute(functions: FunctionDefinition[], files: FileInput[], context: ExecutionContext): Promise<Finding[]>;
53
+ /**
54
+ * Get execution errors with classification
55
+ */
56
+ getErrors(): ClassifiedError[];
57
+ /**
58
+ * Get the metrics collector
59
+ */
60
+ getMetrics(): MetricsCollector;
61
+ /**
62
+ * Classify an error based on its characteristics
63
+ */
64
+ private classifyError;
65
+ /**
66
+ * Process files sequentially
67
+ */
68
+ private sequentialProcess;
69
+ /**
70
+ * Process a single file through all enabled functions
71
+ */
72
+ processFile(file: FileInput & {
73
+ lines: string[];
74
+ }, fns: FunctionDefinition[], context: ExecutionContext): Promise<Finding[]>;
75
+ /**
76
+ * Evaluate a function against a file
77
+ */
78
+ evaluateFunction(fn: FunctionDefinition, file: FileInput, context: ExecutionContext): Promise<{
79
+ findings?: Finding[];
80
+ blocked?: boolean;
81
+ error?: string;
82
+ }>;
83
+ /**
84
+ * Set the logger (acceptable to change at runtime)
85
+ */
86
+ setLogger(logger: Logger): void;
87
+ /**
88
+ * Update options
89
+ */
90
+ setOptions(options: Partial<ExecutorOptions>): void;
91
+ }
92
+ //# sourceMappingURL=Executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Executor.d.ts","sourceRoot":"","sources":["../../src/engine/Executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAiC,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACzI,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAgB,MAAM,eAAe,CAAC;AAGvD,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAErF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,GAAG,QAAQ,CAAC;IAC9B,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;CACxD;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,SAAS,CAAkB;gBAEvB,YAAY,EAAE,oBAAoB,EAAE,OAAO,GAAE,eAAoB;IAe7E;;OAEG;IACH,MAAM,IAAI,IAAI;IAId;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACH,WAAW,IAAI,QAAQ;IAIvB;;OAEG;IACG,OAAO,CACX,SAAS,EAAE,kBAAkB,EAAE,EAC/B,KAAK,EAAE,SAAS,EAAE,EAClB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,OAAO,EAAE,CAAC;IAyDrB;;OAEG;IACH,SAAS,IAAI,eAAe,EAAE;IAI9B;;OAEG;IACH,UAAU,IAAI,gBAAgB;IAI9B;;OAEG;IACH,OAAO,CAAC,aAAa;IA8CrB;;OAEG;YACW,iBAAiB;IAmB/B;;OAEG;IACG,WAAW,CACf,IAAI,EAAE,SAAS,GAAG;QAAE,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,EACrC,GAAG,EAAE,kBAAkB,EAAE,EACzB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,OAAO,EAAE,CAAC;IAqDrB;;OAEG;IACG,gBAAgB,CACpB,EAAE,EAAE,kBAAkB,EACtB,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC;QACT,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;QACrB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAoCF;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;CAGpD"}