A JS/TS Library that allow developers to easily manipulate javascript object by providing a bunch of useful method that will make working with object as simple as working with arrays.
- 🟢 Spicy Object
Spicy_Object is a TS/JS NPM Package to enhance javascript Object capabilities by adding a bunch of methods that help manipulate them easily.
To use this library you need to install it using :
npm install spicy_object --save
//or
npm i spicy_object --save
or:
yarn add spicy_object
After installation you need to import the library using :
import { _Object } from "spicy_object"
A basic usage would be to test if an object is empty
let myObject = {}
console.log(_Object(myObject).isEmpty())
//expected output
true
For further usage please go to the next section.
This is not a method this is an attribute that allow you to get the size of an object
Syntax :
_Object(yourObject).size
use case :
const yourObject = {/*object entries*/}
const result = _Object(yourObject).size
console.log(result)
//expected output
0
This method help us determine whether an object is empty or not.
Syntax :
_Object(yourObject).isEmpty()
use case :
const yourObject = {/*object entries*/}
const result = _Object(yourObject).isEmpty()
console.log(result)
//expected output
true
For simplicity to illustrate a use case of following methos those Object will be used
const userInfo = {
name:"John",
age:30,
car:null,
job: "Developer",
address: "Dakar",
interest: {
music: [
"rnb",
"rap",
{
drill: ["uk", "sn", "us"]
}
],
sports: ["football", "basketball"]
}
}
//This could be returned by a backend
const users = {
0:{
name:"John",
age:30,
car:null,
job: "Developer",
address: "Dakar",
interest: {
music: ["rnb", "rap"],
sports: ["football", "basketball"],
food: [
{
senegal: {0:"yassa", 1:"mafé"},
mali: ["yassa", "mafé", "jolof rice"]
},
{
usa: ["burger", "nuggets",
[
{jfr:["jfr_sn", "jfr_ng"]}
]
]
},
{
italia: ["pizza", "peperoni"]
}
]
}
},
1:{
name:"Jane",
age:20,
car:null,
job: "attorney",
address: "Dakar",
interest: {
music: ["rnb", "rap"],
sports: ["football", "basketball"],
language: ["deutch", "english"]
}
},
2:{
name:"Moussa",
age:26,
car:null,
job: "plice officer",
address: "Dakar",
interest: {
music: ["rnb", "rap", "trap"],
sports: ["basketball", "handball"],
countries: {
Africa: ["Senegal", "Rwanda", "Morroco"],
Europe: ["England", "Russia"],
Asia: ["China", "Saudi Arabia", "Palestine"],
America: ["Brasil", "Mexico", "USA"],
Oceania: ["Australia"]
}
}
}
}
This method allow you to convert your object to a map.
Syntax :
_Object(yourObject).toMap()
use case :
const myMap = _Object(userInfo).toMap()
console.log(myMap)
//expected output
{
name → "John",
age → 30,
car → null,
job → "Developer",
address → "Dakar",
interest → {
music: ["rnb","rap",{drill: ["uk", "sn", "us"]}],
sports: ["football", "basketball"]
}
}
This method allow you to get the first entry of an object.
Syntax :
_Object(yourObject).getFirstEntry()
use case :
const firstEntry = _Object(userInfo).getFirstEntry()
console.log(firstEntry)
//expected output
"John"
This method allow you to get the last entry of an object.
Syntax :
_Object(yourObject).getLastEntry()
use case :
const lastEntry = _Object(userInfo).getLastEntry()
console.log(lastEntry)
//expected output
{
music: ["rnb","rap",{drill: ["uk", "sn", "us"]}],
sports: ["football", "basketball"]
}
This method allow you to get the value of an deeply nested entry inside an object by only passing his key as parameter.
Syntax :
_Object(yourObject).getEntryByKey(key)
use case :
/*In this example we are using our users object declared previously and we are tryin to access the jfr key
*/
//using vanilla js
let result = users[0].interest.food[1].usa[2][0].jfr
//using this library
let result = _Object(users).getEntryByKey("jfr")
//expected output for both method
[ "jfr_sn", "jfr_ng" ]
This method allow you to get the value of an deeply nested
entry inside an object by only passing the path that lead to this entry as parameter.
Syntax :
_Object(yourObject).getEntryByPath(path)
use case :
/*In this example we are using our users object declared previously and we are tryin to access the jfr key
by using the path that leads to this key
*/
//using vanilla js
let result = users[0].interest.food[1].usa[2][0].jfr
//using this library
let result = _Object(users).getEntryByPath("0.interest.food.1.usa.2.0.jfr")
//expected output for both method
[ "jfr_sn", "jfr_ng" ]
This method allow you to filter an object by passing a filter function that returns a boolean.
It works just like the filter method of arrays.
It returns the filtered Object
Syntax :
_Object(yourObject).filter((value, key?optional, index?optional) => {/*body*/})
use case :
const filtered = _Object(userInfo).filter((info) => `${info}`.includes('D'))
console.log(filtered)
//expected output
{ job: "Developer", address: "Dakar" }
//More advanced filter
const products = {
0: { name: 'Orbit', color: 'Blue', size: 50, locations: ['USA', 'Europe'], details: { length: 20, width: 70 } },
1: { name: 'Galsen', color: 'Blue', size: 60, locations: [], details: { length: 20, width: 70 } },
2: { name: 'DaoudaBa', color: 'Black', size: 70, locations: ['Japan'], details: { length: 20, width: 71 } },
3: { name: 'Mouhamed', color: 'Green', size: 50, locations: ['USA'], details: { length: 20, width: 71 } }
};
console.log(
_Object(products).filter(
(_) => (
_.size === 50 || _.size === 70
&& ['blue', 'black'].includes(_.color.toLowerCase())
&& _.locations.find(x => ['JAPAN', 'USA'].includes(x.toUpperCase()))
&& 30 > _.details.length >= 70
)
)
)
//expected output
{
0: { name: 'Orbit', color: 'Blue', size: 50, locations: ['USA', 'Europe'], details: { length: 20, width: 70 },
1: { name: 'DaoudaBa', color: 'Black', size: 70, locations: ['Japan'], details: { length: 20, width: 71 } }
}
This method allow you to map through an object
Note: Inside the map you wouldn't try to modify the initial object.
If you want to do that use the next method.
Syntax :
_Object(yourObject).map((value, key?optional, index?optional) => {/*body*/})
use case :
/*Let's say i want to have a users object where evry user have a password property*/
const newObject = _Object(users).map(user => {
user.password = null
return user
})
console.log(newObject)
This method allow you to Loop through an Object and have access to his keys, values and index inside the function passed in parameter.
Syntax :
_Object(yourObject).forEach((value, key?optional, index?optional) => {/*body*/})
use case :
/*Let's say i want to add a password property to evry user of my users Object*/
_Object(users).forEach(user => {
user.password = null
})
console.log(users)
This method allow you to freeze an object according to the depth level that you want to be frozen
Syntax :
_Object(yourObject).freeze(depthLevel)
use case :
_Object(userInfo).freeze()
/*This only going to froze the property that are directly inside the object(not nested)*/
console.log(Object.isFrozen(userInfo.interest))
//expected output
false
//To froze The first Level of depth we have to pass 1 as depth level
_Object(userInfo).freeze(1)
console.log(Object.isFrozen(userInfo.interest))
//expected output
true
//To froze the entire Object we need to pass 2 as depth level beacause this is a two depth level object
_Object(userInfo).freeze(2)
//after that the object become immutable
This method allow you to extract some properties of an object and group them to create another
object regardless of the level of depth of those properties inside the object until you give a
valid path to them.
It takes an unlimited number of parameters
Syntax :
//a param have to be a key or a path to a key
_Object(yourObject).extract(...params)
use case :
// Simple
const extracted = _Object(userInfo).extract("name")
console.log(extracted)
//expected output
{name: "John"}
//## More Complex
/*Let's say we want to create a users object where a user is only represented by his name and his music interest from our users object*/
const newObj = _Object(users).map(
user => _Object(user).extract("name", "interest.music")
)
//This reduce our huge user object to this
{
0: {
name: "John",
"interest.music": [ "rnb", "rap" ]
}
1: {
name: "Jane",
"interest.music": [ "rnb", "rap" ]
}
2: {
name: "Moussa",
"interest.music": [ "rnb", "rap", "trap" ]
}
}
/*For Longer path like "0.interest.food.1.usa.2.0.jfr"
the extracted key become very messy we can use .as(new_key_name) at the end of the path to rename the output key let's apply it to our precedent use case
*/
const newObj = _Object(users).map(
user => _Object(user).extract("name", "interest.music.as(music)")
)
//This reduce our huge user object to this
{
0: {
name: "John",
music: [ "rnb", "rap" ]
}
1: {
name: "Jane",
music: [ "rnb", "rap" ]
}
2: {
name: "Moussa",
music: [ "rnb", "rap", "trap" ]
}
}
This method allow you to test if an object contain a certain key even if the key is deeply nested
inside the object
It returns an array where the first element is true or false, the second element is the path to the
key or an empty string, depending on whether or not the key was found inside the object
Syntax :
//a param have to be a key
_Object(yourObject).includes(key)
use case :
const result = _Object(users).includes("jfr")
console.log(result)
//expected output
[ true, "0.interest.food.1.usa.2.0.jfr" ]
This method allow you to make an object nullsafe it means to delete all of his entries that
have null values or nullish values like {} and [] or undefined
Syntax :
//a param have to be a key
_Object(yourObject).makeNullSafe()
use case :
let myObject = {
"mo": {"john": 8, "jane": 5, "doe": null},
"tu": {"john": 8, "jane": 5, "doe": null}
"we": {"john": 5, "jane": 9, "doe": null}
"th": {"john": 6, "jane": 3, "doe": null}
"fr": {"john": null, "jane": null, "doe": null}
}
_Object(myObject).makeNullSafe()
console.log(myObject)
//expected output
{
"mo": {"john": 8, "jane": 5},
"tu": {"john": 8, "jane": 5}
"we": {"john": 5, "jane": 9}
"th": {"john": 6, "jane": 3}
}
For min, max, sum, and avg methods we are going to use this object to ilustrate our example
let myObject = {
1: {
firstName: "Moussa",
lastName: "Diop",
age: 23,
job: "Web Developer",
salary: 1500
},
2: {
firstName: "Tacko",
lastName: "Fall",
age: 21,
job: "App Developer",
salary: 1500
},
3: {
firstName: "Lamine",
lastName: "sarr",
age: 32,
job: "Manager",
salary: 2500
},
4: {
firstName: "Awa",
lastName: "sarr",
age: 24,
job: "IT Engineer",
salary: 2000
}
}
This method allow you to get the maximum value based on a key inside the object
This method apply for objects that contains other object of same structure one another
Syntax :
//a param have to be a key
_Object(yourObject).max(key)
use case :
const maxAge = _Object(myObject).max("age")
console.log(maxAge)
//expected output
32
This method allow you to get the minimum value based on a key inside the object
This method apply for objects that contains other object of same structure one another
Syntax :
//a param have to be a key
_Object(yourObject).min(key)
use case :
const minAge = _Object(myObject).min("age")
console.log(minAge)
//expected output
21
This method allow you to get the sum of values based on a key inside the object
This method apply for objects that contains other object of same structure one another
Syntax :
//a param have to be a key
_Object(yourObject).sum(key)
use case :
const totalSalary = _Object(myObject).sum("salary")
console.log(totalSalary)
//expected output
7500
This method allow you to get the average value based on a key inside the object
This method apply for objects that contains other object of same structure one another
Syntax :
//a param have to be a key
_Object(yourObject).avg(key)
use case :
const averageSalary = _Object(myObject).avg("salary")
console.log(averageSalary)
//expected output
1875
This method allow you to compare to objects by values or by keys.
The default is comparison by values (if you don't pass a second parameter to this method).
You can also compare object by keys to test if they have the same structure
(but this comparison just apply to the first-level keys of these two objects)
Syntax :
_Object(yourObject).equals(ObjectToCompareTo, by="values")
use case :
const myObject1 = {
1: {
firstName: "Moussa",
lastName: "Diop",
age: 23,
job: "Web Developer",
salary: 1500,
music: ["rap", "rnb", {drill: ["uk", "usa", "sn"]}]
},
2: {
firstName: "Tacko",
lastName: "Fall",
age: 21,
job: "App Developer",
salary: 1500
}
}
const myObject3 = {
1: {
firstName: "Moussa",
lastName: "Diop",
age: 23,
job: "Web Developer",
salary: 1500,
music: ["rap", "rnb", {drill: ["uk", "usa", "sn"]}]
},
2: {
firstName: "Tacko",
lastName: "Fall",
age: 21,
job: "App Developer",
salary: 1500
}
}
const myObject2 = {
1: {
firstName: "Lamine",
lastName: "sarr",
age: 32,
job: "Manager",
salary: 2500
},
2: {
firstName: "Awa",
lastName: "sarr",
age: 24,
job: "IT Engineer",
salary: 2000
}
}
console.log(_Object(myObject1).equals(myObject2))
// expected output
false
console.log(_Object(myObject1).equals(myObject3))
// expected output
true
👋🏾 Pull requests are welcome!
If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The Responsible Disclosure Program details the procedure for disclosing security issues.
TheCode @mouhamed1296
This project is licensed under the MIT license. See the LICENSE file for more info.
❤ MADE WITH LOVE ❤