import type { UnknownResource } from "@src/component"; const calculatePertinenceScoreRecursive = ( data: any, lowerCaseString: string, isTargetProperty: boolean, ): number => { if (data === null || data === undefined) { return 0; } if (typeof data !== "object") { if (!isTargetProperty) { return 0; } const valueString = String(data).toLowerCase(); const escapedString = lowerCaseString.replace( /[.*+?^${}()|[\]\\]/g, "\\$&", ); const wholeWordRegex = new RegExp(`\\b${escapedString}\\b`); let score = 0; if (wholeWordRegex.test(valueString)) { score = 2; } else if (valueString.includes(lowerCaseString)) { score = 1; } return score; } if (Array.isArray(data)) { let maxScore = 0; for (const item of data) { maxScore = Math.max( maxScore, calculatePertinenceScoreRecursive( item, lowerCaseString, isTargetProperty, ), ); if (maxScore === 2) break; } return maxScore; } let maxScore = 0; for (const value of Object.values(data)) { maxScore = Math.max( maxScore, calculatePertinenceScoreRecursive( value, lowerCaseString, isTargetProperty, ), ); if (maxScore === 2) break; } return maxScore; }; const filterObjectByNamedValue = ( array: UnknownResource[], propName: string, searchString: string, ): UnknownResource[] => { if (!propName || !searchString || searchString.trim() === "") { return array; } const lowerCaseString = searchString.toLowerCase(); const propPath = propName.split("."); return array .map((obj) => { let current: any = obj; for (const segment of propPath) { if (current && typeof current === "object" && segment in current) { current = current[segment]; } else { current = null; break; } } let score = 0; if (current) { score = calculatePertinenceScoreRecursive( current, lowerCaseString, true, ); } return { obj, score }; }) .filter((item) => item.score > 0) .sort((a, b) => b.score - a.score) .map((item) => item.obj); }; export default filterObjectByNamedValue;