@aikotools/datafilter 1.0.4 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -7
- package/dist/aikotools-datafilter.cjs +937 -1
- package/dist/aikotools-datafilter.cjs.map +1 -0
- package/dist/aikotools-datafilter.mjs +677 -354
- package/dist/aikotools-datafilter.mjs.map +1 -0
- package/dist/src/core/types.d.ts +46 -0
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/matcher/Matcher.d.ts +10 -4
- package/dist/src/matcher/Matcher.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@ Advanced data filtering engine for JSON file matching in E2E testing.
|
|
|
13
13
|
|
|
14
14
|
- **Flexible Matching**: Match files using various filter criteria (value, exists, array checks, time ranges)
|
|
15
15
|
- **Order Handling**: Support for both strict and flexible ordering of expected files
|
|
16
|
+
- **🆕 Optional Mode**: Automatically treat unmatched files as optional without explicit rules
|
|
16
17
|
- **🆕 Wildcard Optionals**: Match arbitrary number of optional files without explicit specification
|
|
17
18
|
- **Greedy vs. Non-Greedy**: Control whether wildcards match once or multiple times
|
|
18
19
|
- **PreFilter Support**: Global file filtering before rule matching
|
|
@@ -180,6 +181,81 @@ Validate timestamps (ISO strings or numeric):
|
|
|
180
181
|
|
|
181
182
|
## Advanced Features
|
|
182
183
|
|
|
184
|
+
### 🆕 Optional Mode - Automatic Optional File Handling (NEW)
|
|
185
|
+
|
|
186
|
+
Optional mode allows you to focus on matching critical files while automatically treating unmatched files as optional. This eliminates the need to create explicit wildcard rules for every gap between expected files.
|
|
187
|
+
|
|
188
|
+
**Use Case:** Event streams, log files, or test executions where you want to validate specific checkpoints but allow arbitrary intermediate files.
|
|
189
|
+
|
|
190
|
+
#### Three Matching Modes
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// Mode 1: 'strict' (default) - Current behavior
|
|
194
|
+
// Every file must match a rule, non-matching files → unmapped (error)
|
|
195
|
+
const result = filterFiles({
|
|
196
|
+
files,
|
|
197
|
+
rules,
|
|
198
|
+
mode: 'strict' // or omit for default
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Mode 2: 'optional' - Permissive mode
|
|
202
|
+
// Files between matches are automatically treated as optional
|
|
203
|
+
// Non-matched files → optionalFiles (not an error)
|
|
204
|
+
const result = filterFiles({
|
|
205
|
+
files: [
|
|
206
|
+
{ fileName: 'critical_A.json', data: { type: 'critical' } },
|
|
207
|
+
{ fileName: 'info_1.json', data: { type: 'info' } }, // ← automatically optional
|
|
208
|
+
{ fileName: 'debug_1.json', data: { type: 'debug' } }, // ← automatically optional
|
|
209
|
+
{ fileName: 'critical_B.json', data: { type: 'critical' } },
|
|
210
|
+
],
|
|
211
|
+
rules: [
|
|
212
|
+
{ match: [{ path: ['type'], check: { value: 'critical' } }], expected: 'A' },
|
|
213
|
+
{ match: [{ path: ['type'], check: { value: 'critical' } }], expected: 'B' },
|
|
214
|
+
],
|
|
215
|
+
mode: 'optional' // Enable permissive mode
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Result:
|
|
219
|
+
// - mapped: critical_A.json, critical_B.json
|
|
220
|
+
// - optionalFiles: info_1.json, debug_1.json (with position and context)
|
|
221
|
+
// - unmapped: [] (always empty in optional mode)
|
|
222
|
+
|
|
223
|
+
// Mode 3: 'strict-optional' - Balanced approach
|
|
224
|
+
// Similar to optional mode but respects optional flags on rules
|
|
225
|
+
const result = filterFiles({
|
|
226
|
+
files,
|
|
227
|
+
rules,
|
|
228
|
+
mode: 'strict-optional'
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### Optional File Information
|
|
233
|
+
|
|
234
|
+
When files are treated as optional, they include detailed context:
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
result.optionalFiles = [
|
|
238
|
+
{
|
|
239
|
+
fileName: 'info_1.json',
|
|
240
|
+
position: 1,
|
|
241
|
+
between: {
|
|
242
|
+
afterRule: 'A', // After which matched rule
|
|
243
|
+
beforeRule: 'B' // Before which matched rule
|
|
244
|
+
},
|
|
245
|
+
failedMatches: [...] // Why this file didn't match any rule
|
|
246
|
+
},
|
|
247
|
+
// ...
|
|
248
|
+
]
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### Benefits
|
|
252
|
+
|
|
253
|
+
✅ **Simplicity**: No need for explicit wildcard matchers at every position
|
|
254
|
+
✅ **Flexibility**: Handle variable numbers of files between rules
|
|
255
|
+
✅ **Transparency**: Track which files were optional and why
|
|
256
|
+
✅ **Debugging**: `failedMatches` helps understand filter behavior
|
|
257
|
+
✅ **Clarity**: `unmapped` empty when optional mode active - clear intent
|
|
258
|
+
|
|
183
259
|
### PreFilter - Global File Exclusion
|
|
184
260
|
|
|
185
261
|
PreFilter allows you to exclude files globally **before** any rule matching occurs. Files not matching the preFilter criteria are collected in the `preFiltered` property of the result, separate from `unmapped` files.
|
|
@@ -378,14 +454,19 @@ Main filtering function.
|
|
|
378
454
|
- `rules: (MatchRule | MatchRule[])[]` - Matching rules
|
|
379
455
|
- `sortFn?: (a, b) => number` - Optional sort function
|
|
380
456
|
- `preFilter?: FilterCriterion[]` - Optional pre-filter criteria (files not matching are collected in `preFiltered`)
|
|
457
|
+
- `mode?: 'strict' | 'strict-optional' | 'optional'` - 🆕 Matching mode (default: 'strict')
|
|
458
|
+
- `'strict'`: All files must match a rule (unmapped = errors)
|
|
459
|
+
- `'optional'`: Unmatched files → optionalFiles (unmapped always empty)
|
|
460
|
+
- `'strict-optional'`: Similar to optional but respects optional flags
|
|
381
461
|
- `context?: { startTimeScript?, startTimeTest?, pathTime? }` - Optional context
|
|
382
462
|
|
|
383
463
|
**FilterResult:**
|
|
384
464
|
- `mapped: MappedFile[]` - Successfully mapped files
|
|
385
465
|
- `wildcardMatched: WildcardMappedFile[]` - Files matched by wildcards
|
|
386
|
-
- `
|
|
466
|
+
- `optionalFiles: OptionalFile[]` - 🆕 Files treated as optional (with position and context)
|
|
467
|
+
- `unmapped: UnmappedFile[]` - Files that passed preFilter but couldn't be matched to any rule (empty when mode is 'optional' or 'strict-optional')
|
|
387
468
|
- `preFiltered: PreFilteredFile[]` - Files excluded by preFilter criteria (with failed check details)
|
|
388
|
-
- `stats: { totalFiles, mappedFiles, wildcardMatchedFiles, unmappedFiles, preFilteredFiles, ... }`
|
|
469
|
+
- `stats: { totalFiles, mappedFiles, wildcardMatchedFiles, optionalFiles, unmappedFiles, preFilteredFiles, ... }`
|
|
389
470
|
|
|
390
471
|
### filterFilesWithGroups(request: FilterGroupRequest): FilterResult
|
|
391
472
|
|
|
@@ -396,6 +477,7 @@ Filtering with grouped rules for categorized file processing.
|
|
|
396
477
|
- `groups: FilterGroup[]` - Filter groups with common criteria and rules
|
|
397
478
|
- `sortFn?: (a, b) => number` - Optional sort function
|
|
398
479
|
- `preFilter?: FilterCriterion[]` - Optional pre-filter criteria (applied before group filtering)
|
|
480
|
+
- `mode?: 'strict' | 'strict-optional' | 'optional'` - 🆕 Matching mode (default: 'strict')
|
|
399
481
|
- `context?: { startTimeScript?, startTimeTest?, pathTime? }` - Optional context
|
|
400
482
|
|
|
401
483
|
**FilterGroup:**
|
|
@@ -413,11 +495,11 @@ import { Matcher } from '@aikotools/datafilter';
|
|
|
413
495
|
|
|
414
496
|
const matcher = new Matcher({ startTimeScript, startTimeTest });
|
|
415
497
|
|
|
416
|
-
// With preFilter
|
|
417
|
-
const result = matcher.filterFiles(files, rules, sortFn, preFilter);
|
|
498
|
+
// With preFilter and mode
|
|
499
|
+
const result = matcher.filterFiles(files, rules, sortFn, preFilter, mode);
|
|
418
500
|
|
|
419
|
-
// With groups
|
|
420
|
-
const groupResult = matcher.filterFilesWithGroups(files, groups, sortFn, preFilter);
|
|
501
|
+
// With groups and mode
|
|
502
|
+
const groupResult = matcher.filterFilesWithGroups(files, groups, sortFn, preFilter, mode);
|
|
421
503
|
```
|
|
422
504
|
|
|
423
505
|
### FilterEngine Class
|
|
@@ -488,12 +570,16 @@ const value = getValueOr(obj, ['data', 'missing'], 'default');
|
|
|
488
570
|
|
|
489
571
|
## Test Results
|
|
490
572
|
|
|
491
|
-
✅ **
|
|
573
|
+
✅ **194/194 tests passing** (97.93% coverage for Matcher module)
|
|
492
574
|
- ✅ Basic filtering with single matches
|
|
493
575
|
- ✅ Flexible ordering (array of rules)
|
|
494
576
|
- ✅ Optional rules
|
|
577
|
+
- ✅ 🆕 Optional mode (automatic optional file handling)
|
|
578
|
+
- ✅ 🆕 Strict-optional mode
|
|
495
579
|
- ✅ 🆕 Wildcard matches (greedy & non-greedy)
|
|
496
580
|
- ✅ All filter check types (value, exists, array, time)
|
|
581
|
+
- ✅ PreFilter support
|
|
582
|
+
- ✅ Group filtering
|
|
497
583
|
- ✅ Complex real-world scenarios
|
|
498
584
|
- ✅ Sort function integration
|
|
499
585
|
|