data-ferret is a tiny yet powerful util library to scan or transform deeply nested and complex object-like data with ease. It is created, maintained, and released as open source under MIT license by a group of passionate individuals in Enio.
News
- 2023-01-25 - Added four new functions
locateText()
, removeKey()
, renameKey()
and replaceText()
. - 2023-01-24 - Added two new functions
locateKey()
and getUniqueKeys()
. - 2023-01-23 - Added two new functions
getValue()
and getDepth()
. Updated API to ensure custom iterable classes are fully supported.
Key Features
- Ideal for managing, indexing, searching, and transforming complex data whose interface or shape cannot be guaranteed, in other words, messy data.
- Designed to be extensible to support custom class instances or iterables, beyond the native JavaScript data types.
- Provides first-class support for handling objects with circular references.
- Zero dependencies.
- Bug-free. Features have been thoroughly tested, and published versions have a 100% code coverage guarantee.
Status: Complete :heavy_check_mark:
All features originally planned have been implemented. :technologist: :confetti_ball:
The project is now under active maintenance.
If you find this project useful and would like to see more projects like this, consider signing up for support. You can find details are at the very end. :point_down: :seedling:
Installation
Using npm:
$ npm i -g npm
$ npm i --save @enio.ai/data-ferret
How to Use
You can import utils from data-ferret just as you would with other npm packages.
import { isIdentical, hasCircularReference } from '@enio.ai/data-ferret'
Overview
API
Data Comparison
data-ferret provides a suite of utils for data comparison and evaluation.
Util | Description |
---|
getType() | Returns the data type of the target. Uses native typeof, however, makes a separate distinction for 'null' and 'array' values. Additionally, when classes are registered as types, it checks if objects are instances of a known class. specs :book: |
sameType() | Returns the matching data type for both values, otherwise, returns false. specs :book: |
sameStructure() | Returns the matching type when both values have the same type or structure (non-primitive type), which compares each value's enumerable property names by default for arrays and objects, otherwise returns false. It supports other iterable data types, provided these have been made known using registerIterableClass() . specs :book: |
isIterable() | Returns true when a value is iterable. By default, arrays and objects are considered iterable. Additional iterable types can be assigned by using registerIterableClass() . specs :book: |
isIdentical() | Returns true when both values are identical. For primitive values, use strict equality comparison. For non-primitive values, it checks equality by reviewing values' properties and values. specs :book: |
containsKeys() | A predicate that returns true when the value contains the keys that are expected. It supports other iterable data types, provided these have been made known using registerIterableClass() . specs :book: |
Data Search
data-ferret provides a suite of convenient util functions that allows it to perform read and search operators.
Util | Description |
---|
getValue() | Drills down the data structure of the target value for each key in the path. specs :book: |
getDepth() | Returns the total depth of a value's data structure, and returns a list of locations that are the most deeply nested. specs :book: |
locateKey() | Returns a list of locations where the key name matches a pattern or an exact value anywhere in the data structure of the target. specs :book: |
getUniqueKeys() | Returns a list of unique key names that match a pattern or an exact value anywhere in the data structure of the target. specs :book: |
locateText() | Returns a list of locations where a text value matches a pattern or an exact value anywhere in the data structure of the target. specs :book: |
Data Manipulation
data-ferret provides a suite of convenient util functions that allows it to perform quick data transformations with ease.
Util | Description |
---|
selectiveCopy() | Creates a clone of the target value. Options can be provided to selectively copy values, to partially clone. Due to JavaScript language limitations context of bound functions is not known, thus functions cannot be reliably cloned. This algorithm instead copies function references by default instead. For the same reason getters and setters are not replicate, only their return values. specs :book: |
renameKey() | Renames any key names that match a pattern or an exact value anywhere in the data structure of the target and returns the location of keys that were edited. specs :book: |
removeKey() | Removes any key names that match a pattern or an exact value anywhere in the data structure of the target and returns the location of keys that were removed. specs :book: |
replaceText() | Edits any text by replacing any string or substring that matches a pattern or an exact value anywhere in the data structure of the target and returns the location of the original text values that were edited. specs :book: |
traverse() | It invokes a callback function for every data point in the data structure of the target value to let you do read and write operations. A depth option is available to narrow down the iteration scope. specs :book: |
createTraversal() | A higher-order function that takes a single predicate function to generate an algorithm that traverses data points on a data structure. specs :book: |
Circular Reference Data Support
data-ferret comes equipped with a configurable API that allows it to work with circular referenced data with ease.
Note!: Circular reference detection is not supported for immutable data. E.g. Object.freeze(data)
.
Util | Description |
---|
hasCircularReference() | Returns true for values that have circular references. specs :book: |
locateCircularReference() | Returns a list of locations where circular references occur. specs :book: |
isIdentical() | Same util as described in the previous section. Additionally, it can compare values with circular references. Just need to set the detectCircularReferences configuration ON. specs :book: |
selectiveCopy() | Same util as described in the previous section. Additionally, it can clone values with circular references. By default, it will skip over circular references. When detectCircularReferences configuration ON, the algorithm will also recreate the circular references. specs :book: |
traverse() | Same util as described in the previous section. Additionally, it can skip over circular references to avoid infinite recursion. specs :book: |
getDepth() | Same util as described in the previous section. Additionally, it can skip over circular references to avoid infinite recursion. specs :book: |
locateKey() | Same util as described in the previous section. Additionally, it can skip over circular references to avoid infinite recursion. specs :book: |
getUniqueKeys() | Same util as described in the previous section. Additionally, it can skip over circular references to avoid infinite recursion. specs :book: |
locateText() | Same util as described in the previous section. Additionally, it can skip over circular references to avoid infinite recursion. specs :book: |
renameKey() | Same util as described in the previous section. Additionally, it can skip over circular references to avoid infinite recursion. specs :book: |
removeKey() | Same util as described in the previous section. Additionally, it can skip over circular references to avoid infinite recursion. specs :book: |
replaceText() | Same util as described in the previous section. Additionally, it can skip over circular references to avoid infinite recursion. specs :book: |
Beyond Native Constructs Support
data-ferret is designed to be extensible. It provides some utils that let it understand constructs that are not native JavaScript data types.
For example, passing the class definition and key selector function registerIterableClass()
allows data-ferret to iterate for members of that class and also treats it like a separate data type instead of a plain object.
Util | Description |
---|
registerClassTypes() | Registers one or more classes which will be used on the rest of the API to treat instances to treat instances of said class or classes as having their own unique data type that corresponds to their class. specs :book: |
registerIterableClass() | Registers an iterable class which will be used on the rest of the API to treat instances of said class as having their own unique data type that corresponds to their class. specs :book: |
deregisterClassTypes() | Removes one or more registered classes. Removes all registered classes when no references are provided. specs :book: |
deregisterIterableClass() | Removes one or more registered iterable classes. Removes all registered iterable classes when no references are provided. specs :book: |
Configurable Behavior
Some read/write utils to set global util behavior.
Util | Description |
---|
setConfig() | Sets the global settings for data-ferret utils. |
getConfig() | Returns the global settings for data-ferret utils. |
Options
Key | Description |
---|
samePositionOfOwnProperties | A flag that indicates the API that two values can match if their properties are in the same order when set to true. |
detectCircularReferences | A flag that indicates the API that circular references may exist and should keep a tally of reference stack. Turning this flag ON comes at a performance cost, so enable only when necessary. |
Maintenance of this project is made possible by all the contributors and sponsors. If you'd like to sponsor this project and have your avatar or company logo appear below click here. 💖
(This list will be automatically generated in the future.)