diff --git a/packages/object-util/.eslintrc.js b/packages/object-util/.eslintrc.js
new file mode 100644
index 0000000..7a0472e
--- /dev/null
+++ b/packages/object-util/.eslintrc.js
@@ -0,0 +1,5 @@
+module.exports = {
+ "parserOptions": {
+ "project": __dirname + "/tsconfig.json"
+ }
+}
\ No newline at end of file
diff --git a/packages/object-util/README.md b/packages/object-util/README.md
new file mode 100644
index 0000000..80cdd23
--- /dev/null
+++ b/packages/object-util/README.md
@@ -0,0 +1,65 @@
+# URL Manager
+
+simple to use yet powerful Urls parser and formatter
+
+## Usage
+
+- Import URLManager
+
+```typescript
+import ObjectUtil from '@dzeio/object-util'
+// or
+const ObjectUtil = require('@dzeio/object-util').default
+
+// or you can import each funcitons individually
+```
+
+- or import it from the browser
+
+```html
+
+
+```
+
+- Create a new instance
+
+```typescript
+// Create a new instance
+const url = new URLManager() // you can have an URL, URLSearchParams Objects or a string as parameter
+// or
+const url = URLManager.fromLocation() // Browser only return a new instance from the current location
+```
+
+- explore !
+
+```typescript
+
+// Does the same as Array.map
+objectMap(object, (value, key) => {value + "pouet"})
+
+// does the same as Array.forEach with the addon of stopping if false is returned (like break)
+// and return if loop was finished or not
+objectLoop(object, (value, key) => {})
+
+// return the values of an object as an array
+objectToArray(object)
+
+// return the keys of an object as an array
+ObjectKeys(object)
+
+// return the count of an object keys
+objectSize(object)
+
+// like Array.sort it sort and return an ordered object
+objectSort(object, /*optionnal*/ (key1, key2) => key1 - key2)
+
+// deeply clone an object
+cloneObject(object)
+
+// deeply set an object value while creating empty childs if necessary
+//ex: this will return {path1, [{path3: 'value'}]} if object is an empty object
+objectSet(object, ['path1', 0, 'path3'], 'value')
+
+// deeply compare two objects
+objectEqual(object, object2)
+```
diff --git a/packages/object-util/__tests__/index.test.ts b/packages/object-util/__tests__/index.test.ts
index ee8ccdf..c3d7010 100644
--- a/packages/object-util/__tests__/index.test.ts
+++ b/packages/object-util/__tests__/index.test.ts
@@ -1,9 +1,58 @@
///
-import { objectSize, objectToArray, objectMap, objectSort, cloneObject, objectEqual } from '../src/ObjectUtil'
+import { objectSize, objectToArray, objectMap, objectSort, cloneObject, objectEqual, objectKeys, objectSet, objectLoop } from '../src/ObjectUtil'
+describe('Object Map tests', () => {
+ it('should works', () => {
+ const obj = {
+ pouet: 'first',
+ toto: 'second'
+ }
+ expect(objectMap(obj, (value, index) => {
+ return [index, value]
+ })).toEqual([['pouet', 'first'],['toto','second']])
+ })
+})
-describe('Basic tests', () => {
+describe('Object Loop Tests', () => {
+ it('Should works', () => {
+ const obj = {
+ pouet: true,
+ toto: 'object-util'
+ }
+ objectLoop(obj, (value, key) => {
+ if (key === 'pouet') {
+ expect(value).toBe(true)
+ } else if (key === 'toto') {
+ expect(value).toBe('object-util')
+ } else {
+ throw "it should not come here"
+ }
+ })
+ })
+})
+
+describe('Object To Array Tests', () => {
+ it('Should Works', () => {
+ const obj = {
+ pouet: 'first',
+ toto: 'second'
+ }
+ expect(objectToArray(obj)).toEqual(['first', 'second'])
+ })
+})
+
+describe('Object Keys Tests', () => {
+ it('Should Works', () => {
+ const obj = {
+ pouet: 'first',
+ toto: 'second'
+ }
+ expect(objectKeys(obj)).toEqual(['pouet', 'toto'])
+ })
+})
+
+describe('Object Sort Tests', () => {
it('shoud return length of the object', () => {
const obj = {
index0: true,
@@ -20,25 +69,9 @@ describe('Basic tests', () => {
}
expect(objectSize(obj)).toBe(11)
})
+})
- it('should convert the object to an array', () => {
- const obj = {
- pouet: 'first',
- toto: 'second'
- }
- expect(objectToArray(obj)).toEqual(['first', 'second'])
- })
-
- it('should run through the object', () => {
- const obj = {
- pouet: 'first',
- toto: 'second'
- }
- expect(objectMap(obj, (value, index) => {
- return [index, value]
- })).toEqual([['pouet', 'first'],['toto','second']])
- })
-
+describe('Object sort Tests', () => {
it('should sort the object', () => {
const obj = {
b: 'first',
@@ -49,7 +82,9 @@ describe('Basic tests', () => {
b: 'first'
})
})
+})
+describe('Object Clone Tests', () => {
it('should clone the object', () => {
const obj = {
pouet: 'first',
@@ -71,7 +106,39 @@ describe('Basic tests', () => {
clone.toto = 'third'
expect(clone).not.toEqual(obj)
})
-});
+})
+
+describe('Object Set Tests', () => {
+ it('set the value of an empty object', () => {
+ const obj = {}
+ objectSet(obj, ['test'], true)
+ expect(obj).toEqual({test: true})
+ })
+
+ it('set the deep value of an empty object', () => {
+ const obj = {}
+ objectSet(obj, ['test', 'pouet'], true)
+ expect(obj).toEqual({test: {'pouet': true}})
+ })
+
+ it('set the deep first array value of an empty object', () => {
+ const obj = {}
+ objectSet(obj, ['test', 0], true)
+ expect(obj).toEqual({test: [true]})
+ })
+
+ it('set the deep any array value of an empty object', () => {
+ const obj = {}
+ objectSet(obj, ['test', 2], true)
+ expect(obj).toEqual({test: [undefined, undefined, true]})
+ })
+
+ it('delete the deep value of an object', () => {
+ const obj = {test: {pouet: true}}
+ objectSet(obj, ['test', 'pouet'], undefined)
+ expect(obj).toEqual({test: {}})
+ })
+})
describe('Object Equal Test', () => {
it('should be equal', () => {
@@ -83,6 +150,13 @@ describe('Object Equal Test', () => {
it('should be deeply equal', () => {
expect(objectEqual({pouet: {is: true}}, {pouet: {is: true}})).toBe(true)
})
+ it('should not be equal if lengths are differents', () => {
+ expect(objectEqual({pouet: true, added: true }, {pouet: true})).toBe(false)
+ expect(objectEqual({pouet: true }, {pouet: true, added: true})).toBe(false)
+ })
+ it('should not be equal if lengths are equal but content different', () => {
+ expect(objectEqual({pouet: true, added: true }, {pouet: true, removed: true})).toBe(false)
+ })
it('should not be deeply equal', () => {
expect(objectEqual({pouet: {is: true}}, {pouet: {is: false}})).toBe(false)
})
diff --git a/packages/object-util/src/ObjectUtil.ts b/packages/object-util/src/ObjectUtil.ts
index d4f496d..1ac240c 100644
--- a/packages/object-util/src/ObjectUtil.ts
+++ b/packages/object-util/src/ObjectUtil.ts
@@ -1,43 +1,84 @@
-export const objectMap = (items: Record, fn: (el: T, key: string) => J) => {
+/**
+ * Remap an object to an array through a function
+ *
+ * (Same as Array.map)
+ * @param obj the object to remap
+ * @param fn the fn to run
+ */
+export function objectMap(obj: Record, fn: (value: T, key: string) => J): Array {
const list: Array = []
- objectLoop(items, (item, key) => {
+ objectLoop(obj, (item, key) => {
list.push(fn(item, key))
})
return list
}
-export const objectLoop = (items: Record, fn: (el: T, key: string) => void | boolean) => {
- let res: void | boolean
- for (const key in items) {
- if (!Object.prototype.hasOwnProperty.call(items, key)) {
+/**
+ * Loop through the object
+ * @param obj the object to loop through
+ * @param fn the function to run for each childs
+ */
+export function objectLoop(obj: Record, fn: (value: T, key: string) => boolean | void): boolean {
+ for (const key in obj) {
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) {
continue
}
- res = fn(items[key], key)
- if (typeof res === 'boolean' && !res) {
- return res
+ const stop = fn(obj[key], key)
+ if (stop === false) {
+ return false
}
}
- return res
+ return true
}
+/**
+ * Transform an object to an array removing the keys
+ * @param obj the object to transform
+ */
export function objectToArray(obj: Record): Array {
return Object.values(obj)
}
-export function objectSize(obj: Record) {
- return Object.keys(obj).length
+/**
+ * return the keys of th object
+ * @param obj the object
+ */
+export function objectKeys(obj: Record): Array {
+ return Object.keys(obj)
}
-export function objectSort>(obj: Record, fn?: (a: string, b: string) => number): T {
- const ordered: any = {};
- for (const key of Object.keys(obj).sort(fn)) {
+/**
+ * return the length of an object
+ * @param obj the object
+ */
+export function objectSize(obj: Record): number {
+ return objectKeys(obj).length
+}
+
+/**
+ * Sort an object by its keys
+ *
+ * Same as Array.sort
+ * @param obj the object to sort
+ * @param fn (Optionnal) the function to run to sort
+ */
+export function objectSort>(
+ obj: Record,
+ fn?: (a: string, b: string) => number
+): T {
+ const ordered: any = {}
+ for (const key of objectKeys(obj).sort(fn)) {
ordered[key] = obj[key]
}
return ordered
}
+/**
+ * Deeply clone an object
+ * @param obj the object to clone
+ */
export function cloneObject>(obj: T): T {
- const clone: T = {} as any
+ const clone: Partial = {}
objectLoop(obj, (value, key) => {
if (typeof value === 'object' && value != null) {
clone[key as Extract] = cloneObject(value)
@@ -45,10 +86,20 @@ export function cloneObject>(obj: T): T {
}
clone[key as Extract] = value
})
- return clone
+ return clone as T
}
-export function objectSet(obj: Record, path: Array, value: any) {
+/**
+ * deeply set the value at the path given
+ *
+ * (Create sub object/array if not made)
+ *
+ * _NOTE: it is way quicker to use obj[path][path]... = value_
+ * @param obj the object to set the value
+ * @param path the path
+ * @param value the value
+ */
+export function objectSet(obj: Record, path: Array, value: any): void {
let pointer = obj
for (let index = 0; index < path.length; index++) {
const key = path[index]
@@ -74,7 +125,15 @@ export function objectSet(obj: Record, path: Array
}
}
+/**
+ * deeply compare objects and return if they are equal or not
+ * @param x the first object
+ * @param y the second object
+ */
export function objectEqual(x: Record, y: Record): boolean {
+ if (objectSize(x) !== objectSize(y)) {
+ return false
+ }
const res = objectLoop(x, (item, key) => {
if (!(key in y)) {
return false
@@ -85,9 +144,6 @@ export function objectEqual(x: Record, y: Record): boo
}
return item === item2
})
- if (typeof res !== 'boolean') {
- return true
- }
return res
}
@@ -95,6 +151,7 @@ export default {
objectMap,
objectLoop,
objectToArray,
+ objectKeys,
objectSize,
objectSort,
cloneObject,