@smakss/search
Version:
Enhance your searching capabilities with @smakss/search. Effortlessly find keywords in arrays, nested arrays, and objects, perfect for deep search needs in various data structures.
150 lines (146 loc) • 5.8 kB
JavaScript
/**
* Determines whether a given key is included in the search based on the include parameter and the keys provided.
*
* @param {string} key - The key to check.
* @param {string[]} keys - The list of keys to consider in the search.
* @param {boolean} include - Flag determining if the keys should be included or excluded from the search.
* @returns {boolean} - True if the key is included in the search, false otherwise.
*
* @example
* // Check if 'name' is included in a search considering only 'name' and 'age':
* console.log(isKeyIncluded('name', ['name', 'age'], true)); // Output: true
* console.log(isKeyIncluded('address', ['name', 'age'], true)); // Output: false
*/
function isKeyIncluded(key, keys, include) {
return include ? keys.includes(key) : !keys.includes(key);
}
/**
* Adds a search item to the results if it's not already included.
*
* @template T - The type of the object to search within, extending SearchItem.
* @param {T[]} results - The current list of search results.
* @param {T} item - The item to potentially add to the results.
*
* @example
* // Example usage of addUniqueMatch
* const results: SearchItem[] = [];
* const itemToAdd: SearchItem = { name: 'John', age: 30 };
* addUniqueMatch(results, itemToAdd);
* console.log(results); // Output: [{ name: 'John', age: 30 }]
*/
function addUniqueMatch(results, item) {
if (!results.includes(item)) {
results.push(item);
}
}
/**
* Searches for matches within an object based on a regex pattern.
* If a match is found within the specified keys, it adds the object to the results.
*
* @template T - The type of the object to search within, extending SearchItem.
* @param {T} object - The object to search within.
* @param {string[]} keys - The keys to include or exclude in the search.
* @param {boolean} include - Whether to include or exclude the specified keys in the search.
* @param {RegExp} regex - The regex pattern to match against the object values.
* @param {T[]} results - The array to store matching objects.
*
* @example
* // Define an object to search
* const person = { name: "John", lastName: "Doe" };
* const results = [];
*
* // Search within the object for the name 'John'
* searchWithinObject(person, ['name'], true, /John/i, results);
*
* // results will contain the person object
* console.log(results); // [{ name: "John", lastName: "Doe" }]
*/
function searchWithinObject(object, keys, include, regex, results) {
for (const key of Object.keys(object)) {
if (isKeyIncluded(key, keys, include) && regex.test(String(object[key]))) {
addUniqueMatch(results, object);
break;
}
}
}
/**
* Recursively searches through items for matches based on a regex pattern.
* It handles both arrays and individual objects.
*
* @template T - The type of the items to search through, extending SearchItem.
* @param {T | T[]} items - The items to search through. Can be a single item or an array of items.
* @param {string[]} keys - The keys to include or exclude in the search.
* @param {boolean} include - Whether to include or exclude the specified keys in the search.
* @param {RegExp} regex - The regex pattern to match against item values.
* @param {SearchItem[]} results - The array to store matching items.
*
* @example
* // Define a list of objects to search
* const people = [
* { name: "John", lastName: "Doe" },
* { name: "Jane", lastName: "Doe" },
* ];
* const searchResults = [];
*
* // Recursively search for the term 'doe' in the list of people
* recursiveSearch(people, ['lastName'], true, /doe/i, searchResults);
*
* // searchResults will contain both person objects
* console.log(searchResults); // [{ name: "John", lastName: "Doe" }, { name: "Jane", lastName: "Doe" }]
*/
function recursiveSearch(items, keys, include, regex, results) {
if (Array.isArray(items)) {
for (const item of items) {
recursiveSearch(item, keys, include, regex, results);
}
}
else if (typeof items === 'object' && items !== null) {
searchWithinObject(items, keys, include, regex, results);
}
else if (regex.test(String(items))) {
addUniqueMatch(results, items);
}
}
/**
* Searches for items within a collection that match the given search text.
*
* @param {SearchOptions} options - The search parameters including searchText, searchItems, keys to search in,
* whether to include keys and if the search is exact.
* @template T - The type of the items to search through, extending SearchItem.
* @returns {T[]} The matched items as an array.
*
* @example
* type Person = { name: string; lastName: string; }
* // Define a list of objects to search
* const people: Person[] = [
* { name: "John", lastName: "Doe" },
* { name: "Jane", lastName: "Smith" },
* ];
*
* // Options for searching
* const options = {
* searchText: "doe",
* searchItems: people,
* keys: ['lastName'],
* include: true,
* exact: false
* };
*
* // Perform the search
* const found = search<Person>(options);
*
* // found will contain the object with lastName 'Doe'
* console.log(found); // [{ name: "John", lastName: "Doe" }]
*/
function search({ searchText, searchItems, keys = [], include = true, exact = false }) {
const regex = new RegExp(exact ? `^${searchText}$` : searchText, 'i');
const results = [];
const preparedItems = Array.isArray(searchItems)
? searchItems
: [searchItems];
const preparedKeys = keys.length > 0 ? keys : Object.keys(preparedItems[0] || {});
recursiveSearch(preparedItems, preparedKeys, include, regex, results);
return results;
}
export { search as default };
//# sourceMappingURL=index.js.map