@aikotools/datafilter 1.0.1 → 1.0.2
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.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const $=require("luxon");function k(i){return"matchAny"in i}function E(i){return"match"in i&&"expected"in i}function y(i,s){const t=[];if(s.length===0)return{value:i,found:!0,validPath:[]};let e=i;for(let n=0;n<s.length;n++){const r=s[n];if(e==null)return{value:void 0,found:!1,error:`Cannot read property '${r}' of ${e}`,validPath:t};if(Array.isArray(e)){const a=typeof r=="number"?r:parseInt(String(r),10);if(isNaN(a))return{value:void 0,found:!1,error:`Array index must be a number, got '${r}'`,validPath:t};if(a<0||a>=e.length)return{value:void 0,found:!1,error:`Array index ${a} out of bounds (length: ${e.length})`,validPath:t};t.push(a),e=e[a];continue}if(typeof e=="object"){const a=String(r);if(!(a in e))return{value:void 0,found:!1,error:`Property '${a}' does not exist`,validPath:t};t.push(a),e=e[a];continue}return{value:void 0,found:!1,error:`Cannot access property '${r}' of primitive type ${typeof e}`,validPath:t}}return{value:e,found:!0,validPath:t}}function M(i,s){const t=y(i,s);return t.found&&t.value!==void 0}function P(i,s,t){const e=y(i,s);return e.found&&e.value!==void 0?e.value:t}class S{constructor(s){this.context=s}evaluateCriterion(s,t){const e=t.check;return"value"in e?this.checkValue(s,t.path,e):"exists"in e?this.checkExists(s,t.path,e):"itemExists"in e&&"item"in e?this.checkArrayElement(s,t.path,e):"type"in e&&"size"in e?this.checkArraySize(s,t.path,e):"min"in e&&"max"in e?typeof e.min=="number"&&typeof e.max=="number"?this.checkNumericRange(s,t.path,e):this.checkTimeRange(s,t.path,e):{status:!1,checkType:"unknown",reason:`Unknown check type: ${JSON.stringify(e)}`}}checkValue(s,t,e){const n=y(s,t);if(!n.found)return{status:!1,checkType:"checkValue",reason:{message:n.error||"Path not found",path:t}};const r=n.value,a=e.value;return this.deepEqual(r,a)?{status:!0,checkType:"checkValue"}:{status:!1,checkType:"checkValue",reason:{message:"Value mismatch",path:t,expected:a,actual:r}}}checkExists(s,t,e){const n=y(s,t),r=n.found&&n.value!==void 0;return e.exists===r?{status:!0,checkType:"checkExists"}:{status:!1,checkType:"checkExists",reason:{message:e.exists?`Path should exist but doesn't: ${n.error}`:"Path should not exist but does",path:t}}}checkArrayElement(s,t,e){const n=y(s,t);if(!n.found)return{status:!1,checkType:"checkArrayElement",reason:{message:n.error||"Path not found",path:t}};const r=n.value;if(!Array.isArray(r))return{status:!1,checkType:"checkArrayElement",reason:{message:"Value is not an array",path:t,actualType:typeof r}};const a=r.some(u=>this.deepEqual(u,e.item));return e.itemExists===a?{status:!0,checkType:"checkArrayElement"}:{status:!1,checkType:"checkArrayElement",reason:{message:e.itemExists?"Item should exist in array but doesn't":"Item should not exist in array but does",path:t,item:e.item}}}checkArraySize(s,t,e){const n=y(s,t);if(!n.found)return{status:!1,checkType:"checkArraySize",reason:{message:n.error||"Path not found",path:t}};const r=n.value;if(!Array.isArray(r))return{status:!1,checkType:"checkArraySize",reason:{message:"Value is not an array",path:t,actualType:typeof r}};const a=r.length,u=e.size;let l=!1,f="";switch(e.type){case"equal":l=a===u,f=`Array length should be ${u} but is ${a}`;break;case"lessThan":l=a<u,f=`Array length should be less than ${u} but is ${a}`;break;case"greaterThan":l=a>u,f=`Array length should be greater than ${u} but is ${a}`;break}return l?{status:!0,checkType:"checkArraySize"}:{status:!1,checkType:"checkArraySize",reason:{message:f,path:t,expected:u,actual:a}}}checkTimeRange(s,t,e){const n=y(s,t);if(!n.found)return{status:!1,checkType:"checkTimeRange",reason:{message:n.error||"Path not found",path:t}};const r=n.value;if(typeof r=="number"){const a=parseInt(e.min),u=parseInt(e.max);return isNaN(a)||isNaN(u)?{status:!1,checkType:"checkTimeRange",reason:{message:"Min or max is not a valid number",min:e.min,max:e.max}}:r>=a&&r<=u?{status:!0,checkType:"checkTimeRange"}:{status:!1,checkType:"checkTimeRange",reason:{message:`Timestamp ${r} is outside range [${a}, ${u}]`,path:t,actual:r,min:a,max:u}}}if(typeof r=="string"){const a=$.DateTime.fromISO(r),u=$.DateTime.fromISO(e.min),l=$.DateTime.fromISO(e.max);return a.isValid?!u.isValid||!l.isValid?{status:!1,checkType:"checkTimeRange",reason:{message:"Invalid min or max time",min:e.min,max:e.max}}:a>=u&&a<=l?{status:!0,checkType:"checkTimeRange"}:{status:!1,checkType:"checkTimeRange",reason:{message:`Timestamp ${r} is outside range [${e.min}, ${e.max}]`,path:t,actual:r,min:e.min,max:e.max}}:{status:!1,checkType:"checkTimeRange",reason:{message:`Invalid timestamp: ${r}`,path:t}}}return{status:!1,checkType:"checkTimeRange",reason:{message:`Timestamp must be a string or number, got ${typeof r}`,path:t}}}checkNumericRange(s,t,e){const n=y(s,t);if(!n.found)return{status:!1,checkType:"checkNumericRange",reason:{message:n.error||"Path not found",path:t}};const r=n.value;return typeof r!="number"?{status:!1,checkType:"checkNumericRange",reason:{message:`Value must be a number, got ${typeof r}`,path:t,actual:r}}:r>=e.min&&r<=e.max?{status:!0,checkType:"checkNumericRange"}:{status:!1,checkType:"checkNumericRange",reason:{message:`Value ${r} is outside range [${e.min}, ${e.max}]`,path:t,actual:r,min:e.min,max:e.max}}}deepEqual(s,t){if(s===t)return!0;if(s===null||t===null||s===void 0||t===void 0)return s===t;if(typeof s!=typeof t)return!1;if(s instanceof Date&&t instanceof Date)return s.getTime()===t.getTime();if(Array.isArray(s)&&Array.isArray(t))return s.length!==t.length?!1:s.every((e,n)=>this.deepEqual(e,t[n]));if(typeof s=="object"&&typeof t=="object"){const e=Object.keys(s),n=Object.keys(t);return e.length!==n.length?!1:e.every(r=>this.deepEqual(s[r],t[r]))}return s===t}}class w{constructor(s){this.engine=new S(s)}matchFile(s,t){const n=(k(t)?t.matchAny:t.match).map(a=>this.engine.evaluateCriterion(s.data,a));return{matched:n.every(a=>a.status),checks:n,rule:t}}applyPreFilter(s,t){return s.filter(e=>t.map(r=>this.engine.evaluateCriterion(e.data,r)).every(r=>r.status))}filterFiles(s,t,e,n){const r=n?this.applyPreFilter(s,n):s,a=e?[...r].sort(e):[...r],u=[],l=[],f=[],g=new Set,x=new Map;let o=0,c=0;for(;o<a.length;){const h=a[o];if(c>=t.length){g.has(o)||f.push({file:h,attemptedRules:[]}),o++;continue}const m=t[c],v=[];let R=!1;if(Array.isArray(m)){for(let p=0;p<m.length;p++){if(x.get(c)?.has(p))continue;const T=m[p],F=this.matchFile(h,T);if(v.push(F),F.matched&&E(T)){x.has(c)||x.set(c,new Set);const b=x.get(c);b&&b.add(p),u.push({expected:T.expected,file:h,matchResult:F,optional:T.optional||!1,info:T.info}),g.add(o),R=!0;break}}x.get(c)?.size===m.length&&c++,o++}else{const d=m,p=this.matchFile(h,d);v.push(p),p.matched?E(d)?(u.push({expected:d.expected,file:h,matchResult:p,optional:d.optional||!1,info:d.info}),g.add(o),c++,o++):k(d)&&(l.push({file:h,matchResult:p,info:d.info}),g.add(o),d.greedy||c++,o++):d.optional||k(d)?c++:(f.push({file:h,attemptedRules:v}),o++)}}const A={totalFiles:s.length,mappedFiles:u.length,wildcardMatchedFiles:l.length,unmappedFiles:f.length,totalRules:this.countRules(t),mandatoryRules:this.countMandatoryRules(t),optionalRules:this.countOptionalRules(t)};return{mapped:u,wildcardMatched:l,unmapped:f,stats:A}}countRules(s){return s.reduce((t,e)=>Array.isArray(e)?t+e.length:t+1,0)}countMandatoryRules(s){return s.reduce((t,e)=>Array.isArray(e)?t+e.filter(n=>!n.optional&&!k(n)).length:t+(e.optional||k(e)?0:1),0)}countOptionalRules(s){return s.reduce((t,e)=>Array.isArray(e)?t+e.filter(n=>n.optional||k(n)).length:t+(e.optional||k(e)?1:0),0)}filterFilesWithGroups(s,t,e,n){const r=n?this.applyPreFilter(s,n):s,a=e?[...r].sort(e):[...r],u=[],l=[],f=[];for(const o of t){const c=a.filter(m=>o.groupFilter.map(R=>this.engine.evaluateCriterion(m.data,R)).every(R=>R.status));if(c.length===0)continue;const A=o.rules.map(m=>(Array.isArray(m),m)),h=this.filterFiles(c,A);u.push(...h.mapped),l.push(...h.wildcardMatched),f.push(...h.unmapped)}const g=t.flatMap(o=>o.rules),x={totalFiles:s.length,mappedFiles:u.length,wildcardMatchedFiles:l.length,unmappedFiles:f.length,totalRules:this.countRules(g),mandatoryRules:this.countMandatoryRules(g),optionalRules:this.countOptionalRules(g)};return{mapped:u,wildcardMatched:l,unmapped:f,stats:x}}}function V(i){const s=new w(i.context);if(i.rules&&i.groups)throw new Error('FilterRequest: Provide either "rules" or "groups", not both');if(!i.rules&&!i.groups)throw new Error('FilterRequest: Must provide either "rules" or "groups"');if(i.groups)return s.filterFilesWithGroups(i.files,i.groups,i.sortFn,i.preFilter);if(!i.rules)throw new Error("FilterRequest: Rules are required");return s.filterFiles(i.files,i.rules,i.sortFn,i.preFilter)}exports.FilterEngine=S;exports.Matcher=w;exports.filterFiles=V;exports.getValueFromPath=y;exports.getValueOr=P;exports.isSingleMatchRule=E;exports.isWildcardRule=k;exports.pathExists=M;
|
package/package.json
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aikotools/datafilter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Advanced data filtering engine for JSON file matching in E2E testing",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/aikotools-datafilter.cjs",
|
|
7
|
+
"module": "dist/aikotools-datafilter.mjs",
|
|
7
8
|
"types": "dist/src/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/src/index.d.ts",
|
|
13
|
+
"default": "./dist/aikotools-datafilter.mjs"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/src/index.d.ts",
|
|
17
|
+
"default": "./dist/aikotools-datafilter.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
8
21
|
"files": [
|
|
9
22
|
"dist/**/*"
|
|
10
23
|
],
|