fix(core): update
This commit is contained in:
		
							
								
								
									
										23
									
								
								test/test.smartobject.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								test/test.smartobject.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| import { expect, expectAsync, tap} from '@pushrocks/tapbundle'; | ||||
| import * as smartobject from '../ts'; | ||||
|  | ||||
| let testSmartobject: smartobject.SmartObject; | ||||
|  | ||||
| tap.test('should create a smartobject', async () => { | ||||
|   const originalObject = { | ||||
|     test: 'hey', | ||||
|     deep: { | ||||
|       yeah: 'so deep', | ||||
|       evendeeper: { | ||||
|         sodeep: 2, | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   testSmartobject = new smartobject.SmartObject(originalObject); | ||||
|   testSmartobject.addValueAtFlatPathString('deep.nice', 'yeah that has been added'); | ||||
|   console.log(testSmartobject.originalObject); | ||||
|   console.log(testSmartobject.toFlatObject()) | ||||
|   expect(testSmartobject.getValueAtFlatPathString('deep.yeah')).toEqual('so deep'); | ||||
| }); | ||||
|  | ||||
| tap.start(); | ||||
							
								
								
									
										201
									
								
								ts/index.ts
									
									
									
									
									
								
							
							
						
						
									
										201
									
								
								ts/index.ts
									
									
									
									
									
								
							| @@ -1,203 +1,6 @@ | ||||
| import * as plugins from './smartobject.plugins'; | ||||
|  | ||||
| const fastDeepEqual = plugins.fastDeepEqual; | ||||
| export { fastDeepEqual }; | ||||
|  | ||||
| export interface IObjectCompareResult { | ||||
|   presentInBothProperties: string[]; | ||||
|   missingProperties: string[]; | ||||
|   additionalProperties: string[]; | ||||
|   nulledProperties: string[]; | ||||
|   undefinedProperties: string[]; | ||||
|   divergingProperties: string[]; | ||||
|   equalProperties: string[]; | ||||
| } | ||||
|  | ||||
| export const compareObjects = ( | ||||
|   referenceObjectArg: any, | ||||
|   comparisonObjectArg: any | ||||
| ): IObjectCompareResult => { | ||||
|   const returnComparisonObject = { | ||||
|     missingProperties: [] as string[], | ||||
|     additionalProperties: [] as string[], | ||||
|     presentInBothProperties: [] as string[], | ||||
|     nulledProperties: [] as string[], | ||||
|     undefinedProperties: [] as string[], | ||||
|     divergingProperties: [] as string[], | ||||
|     equalProperties: [] as string[], | ||||
|   }; | ||||
|  | ||||
|   const allProperties = Object.keys(referenceObjectArg).concat(Object.keys(comparisonObjectArg)); | ||||
|   for (const currentProperty of allProperties) { | ||||
|     // lets find presentInBothProperties | ||||
|     if (referenceObjectArg[currentProperty] && comparisonObjectArg[currentProperty]) { | ||||
|       returnComparisonObject.presentInBothProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find missingProperties | ||||
|     if (referenceObjectArg[currentProperty] && !comparisonObjectArg[currentProperty]) { | ||||
|       returnComparisonObject.missingProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find additionalProperties | ||||
|     if (!referenceObjectArg[currentProperty] && comparisonObjectArg[currentProperty]) { | ||||
|       returnComparisonObject.additionalProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find nulledProperties | ||||
|     if (comparisonObjectArg[currentProperty] === null) { | ||||
|       returnComparisonObject.nulledProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find undefinedProperties | ||||
|     if (comparisonObjectArg[currentProperty] === undefined) { | ||||
|       returnComparisonObject.undefinedProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find divergingProperties | ||||
|     if ( | ||||
|       JSON.stringify(referenceObjectArg[currentProperty]) !== | ||||
|       JSON.stringify(comparisonObjectArg[currentProperty]) | ||||
|     ) { | ||||
|       returnComparisonObject.divergingProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find equalProperties | ||||
|     if ( | ||||
|       JSON.stringify(referenceObjectArg[currentProperty]) === | ||||
|       JSON.stringify(comparisonObjectArg[currentProperty]) | ||||
|     ) { | ||||
|       returnComparisonObject.equalProperties.push(currentProperty); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   for (const currentProperty of Object.keys(returnComparisonObject)) { | ||||
|     const onlyUnique = (value: any, index: number, self: Array<any>) => { | ||||
|       return self.indexOf(value) === index; | ||||
|     }; | ||||
|     const uniqueArray = returnComparisonObject[currentProperty as keyof(typeof returnComparisonObject)].filter(onlyUnique); | ||||
|     returnComparisonObject[currentProperty as keyof(typeof returnComparisonObject)] = uniqueArray; | ||||
|   } | ||||
|  | ||||
|   return returnComparisonObject; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * adds an object to the parent object if it doesn't exists | ||||
|  * @param parentObject | ||||
|  * @param childParam | ||||
|  * @param logBool | ||||
|  * @returns {boolean} | ||||
|  */ | ||||
| export const smartAdd = ( | ||||
|   parentObject: object, | ||||
|   childParam: string, | ||||
|   valueArg: any = {}, | ||||
|   optionsArg?: { | ||||
|     interpretDotsAsLevel: boolean; | ||||
|   } | ||||
| ): typeof parentObject & any => { | ||||
|   optionsArg = { | ||||
|     interpretDotsAsLevel: true, | ||||
|     ...optionsArg | ||||
|   }; | ||||
|  | ||||
|   let paramLevels: string[]; | ||||
|   let referencePointer: any = parentObject; | ||||
|   if (optionsArg.interpretDotsAsLevel) { | ||||
|     paramLevels = childParam.split('.'); | ||||
|   } else { | ||||
|     paramLevels = [childParam]; | ||||
|   } | ||||
|  | ||||
|   for (let i = 0; i !== paramLevels.length; i++) { | ||||
|     const varName: string = paramLevels[i]; | ||||
|  | ||||
|     // is there a next variable ? | ||||
|     const varNameNext: string = (() => { | ||||
|       if (paramLevels[i + 1]) { | ||||
|         return paramLevels[i + 1]; | ||||
|       } | ||||
|       return null; | ||||
|     })(); | ||||
|  | ||||
|     // build the tree in parentObject | ||||
|     if (!referencePointer[varName] && !varNameNext) { | ||||
|       referencePointer[varName] = valueArg; | ||||
|       referencePointer = null; | ||||
|     } else if (!referencePointer[varName] && varNameNext) { | ||||
|       referencePointer[varName] = {}; | ||||
|       referencePointer = referencePointer[varName]; | ||||
|     } else if (referencePointer[varName] && varNameNext) { | ||||
|       referencePointer = referencePointer[varName]; | ||||
|     } else { | ||||
|       throw new Error('Something is strange!'); | ||||
|     } | ||||
|   } | ||||
|   return parentObject; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * gets an object from the parent object using dots as levels by default | ||||
|  * @param parentObject | ||||
|  * @param childParam | ||||
|  * @param optionsArg | ||||
|  */ | ||||
| export const smartGet = <T>( | ||||
|   parentObject: object, | ||||
|   childParam: string, | ||||
|   optionsArg?: { | ||||
|     interpretDotsAsLevel: boolean; | ||||
|   } | ||||
| ): T => { | ||||
|   optionsArg = { | ||||
|     interpretDotsAsLevel: true, | ||||
|     ...optionsArg | ||||
|   }; | ||||
|  | ||||
|   let paramLevels: string[]; | ||||
|   if (optionsArg.interpretDotsAsLevel) { | ||||
|     paramLevels = childParam.split('.'); | ||||
|   } else { | ||||
|     paramLevels = [childParam]; | ||||
|   } | ||||
|  | ||||
|   let referencePointer: any = parentObject; | ||||
|   for (const level of paramLevels) { | ||||
|     if (referencePointer[level as any]) { | ||||
|       referencePointer = referencePointer[level as any]; | ||||
|     } else { | ||||
|       return null; | ||||
|     } | ||||
|   } | ||||
|   return referencePointer as T; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * checks if an object has a parameter with a given key name, returns true if yes. | ||||
|  * @param parentObject | ||||
|  * @param childParam | ||||
|  * @returns {boolean} | ||||
|  */ | ||||
| export let exists = (parentObject: object, childParam: string): boolean => { | ||||
|   if (parentObject.hasOwnProperty(childParam)) { | ||||
|     return true; | ||||
|   } | ||||
|   return false; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * runs a function for all properties of an object whose key matches a regex expression | ||||
|  * @param parentObjectArg the parent object | ||||
|  * @param wildcardArg the rege expression to match the property keys against | ||||
|  * @param callbackArg the function to run with those properties | ||||
|  */ | ||||
| export let forEachMinimatch = async (parentObjectArg: any, wildcardArg: string, callbackArg: (matchedArg: string) => void) => { | ||||
|   let propertyNames = Object.getOwnPropertyNames(parentObjectArg); | ||||
|   let propertyNamesMatched = propertyNames.filter(propertyNameArg => { | ||||
|     return plugins.minimatch(propertyNameArg, wildcardArg); | ||||
|   }); | ||||
|   for (let propertyNameArg of propertyNamesMatched) { | ||||
|     await callbackArg(parentObjectArg[propertyNameArg]); | ||||
|   } | ||||
| }; | ||||
| export * from './smartobject.classes.smartobject'; | ||||
| export * from './tools'; | ||||
|   | ||||
							
								
								
									
										25
									
								
								ts/smartobject.classes.smartobject.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								ts/smartobject.classes.smartobject.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| import * as tools from './tools'; | ||||
|  | ||||
| /** | ||||
|  * a smartobject that simplifies accessing objects | ||||
|  */ | ||||
| export class SmartObject { | ||||
|  | ||||
|   // instance | ||||
|   public originalObject: object; | ||||
|   constructor(originalObjectArg: object) { | ||||
|     this.originalObject = originalObjectArg; | ||||
|   } | ||||
|  | ||||
|   public getValueAtFlatPathString(pathArg: string) { | ||||
|     return tools.smartGet(this.originalObject, pathArg); | ||||
|   } | ||||
|  | ||||
|   public addValueAtFlatPathString(pathArg: string, valueArg: any) { | ||||
|     return tools.smartAdd(this.originalObject, pathArg, valueArg); | ||||
|   } | ||||
|  | ||||
|   public toFlatObject() { | ||||
|     return tools.toFlatObject(this.originalObject); | ||||
|   } | ||||
| } | ||||
| @@ -1,4 +1,3 @@ | ||||
|  | ||||
| // thirdparty scope | ||||
| // tslint:disable-next-line: no-submodule-imports | ||||
| import fastDeepEqual from 'fast-deep-equal/es6'; | ||||
|   | ||||
							
								
								
									
										79
									
								
								ts/tools/compareobjects.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								ts/tools/compareobjects.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| import * as plugins from '../smartobject.plugins'; | ||||
|  | ||||
| export interface IObjectCompareResult { | ||||
|   presentInBothProperties: string[]; | ||||
|   missingProperties: string[]; | ||||
|   additionalProperties: string[]; | ||||
|   nulledProperties: string[]; | ||||
|   undefinedProperties: string[]; | ||||
|   divergingProperties: string[]; | ||||
|   equalProperties: string[]; | ||||
| } | ||||
|  | ||||
| export const compareObjects = ( | ||||
|   referenceObjectArg: any, | ||||
|   comparisonObjectArg: any | ||||
| ): IObjectCompareResult => { | ||||
|   const returnComparisonObject = { | ||||
|     missingProperties: [] as string[], | ||||
|     additionalProperties: [] as string[], | ||||
|     presentInBothProperties: [] as string[], | ||||
|     nulledProperties: [] as string[], | ||||
|     undefinedProperties: [] as string[], | ||||
|     divergingProperties: [] as string[], | ||||
|     equalProperties: [] as string[], | ||||
|   }; | ||||
|  | ||||
|   const allProperties = Object.keys(referenceObjectArg).concat(Object.keys(comparisonObjectArg)); | ||||
|   for (const currentProperty of allProperties) { | ||||
|     // lets find presentInBothProperties | ||||
|     if (referenceObjectArg[ currentProperty ] && comparisonObjectArg[ currentProperty ]) { | ||||
|       returnComparisonObject.presentInBothProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find missingProperties | ||||
|     if (referenceObjectArg[ currentProperty ] && !comparisonObjectArg[ currentProperty ]) { | ||||
|       returnComparisonObject.missingProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find additionalProperties | ||||
|     if (!referenceObjectArg[ currentProperty ] && comparisonObjectArg[ currentProperty ]) { | ||||
|       returnComparisonObject.additionalProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find nulledProperties | ||||
|     if (comparisonObjectArg[ currentProperty ] === null) { | ||||
|       returnComparisonObject.nulledProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find undefinedProperties | ||||
|     if (comparisonObjectArg[ currentProperty ] === undefined) { | ||||
|       returnComparisonObject.undefinedProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find divergingProperties | ||||
|     if ( | ||||
|       JSON.stringify(referenceObjectArg[ currentProperty ]) !== | ||||
|       JSON.stringify(comparisonObjectArg[ currentProperty ]) | ||||
|     ) { | ||||
|       returnComparisonObject.divergingProperties.push(currentProperty); | ||||
|     } | ||||
|  | ||||
|     // lets find equalProperties | ||||
|     if ( | ||||
|       plugins.fastDeepEqual(referenceObjectArg[ currentProperty ], comparisonObjectArg[ currentProperty ]) | ||||
|     ) { | ||||
|       returnComparisonObject.equalProperties.push(currentProperty); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   for (const currentProperty of Object.keys(returnComparisonObject)) { | ||||
|     const onlyUnique = (value: any, index: number, self: Array<any>) => { | ||||
|       return self.indexOf(value) === index; | ||||
|     }; | ||||
|     const uniqueArray = returnComparisonObject[ currentProperty as keyof (typeof returnComparisonObject) ].filter(onlyUnique); | ||||
|     returnComparisonObject[ currentProperty as keyof (typeof returnComparisonObject) ] = uniqueArray; | ||||
|   } | ||||
|  | ||||
|   return returnComparisonObject; | ||||
| }; | ||||
							
								
								
									
										14
									
								
								ts/tools/exists.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								ts/tools/exists.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| import * as plugins from '../smartobject.plugins'; | ||||
|  | ||||
| /** | ||||
|  * checks if an object has a parameter with a given key name, returns true if yes. | ||||
|  * @param parentObject | ||||
|  * @param childParam | ||||
|  * @returns {boolean} | ||||
|  */ | ||||
|  export let exists = (parentObject: object, childParam: string): boolean => { | ||||
|   if (parentObject.hasOwnProperty(childParam)) { | ||||
|     return true; | ||||
|   } | ||||
|   return false; | ||||
| }; | ||||
							
								
								
									
										17
									
								
								ts/tools/foreachminimatch.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								ts/tools/foreachminimatch.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| import * as plugins from '../smartobject.plugins'; | ||||
|  | ||||
| /** | ||||
|  * runs a function for all properties of an object whose key matches a regex expression | ||||
|  * @param parentObjectArg the parent object | ||||
|  * @param wildcardArg the rege expression to match the property keys against | ||||
|  * @param callbackArg the function to run with those properties | ||||
|  */ | ||||
|  export let forEachMinimatch = async (parentObjectArg: any, wildcardArg: string, callbackArg: (matchedArg: string) => void) => { | ||||
|   let propertyNames = Object.getOwnPropertyNames(parentObjectArg); | ||||
|   let propertyNamesMatched = propertyNames.filter(propertyNameArg => { | ||||
|     return plugins.minimatch(propertyNameArg, wildcardArg); | ||||
|   }); | ||||
|   for (let propertyNameArg of propertyNamesMatched) { | ||||
|     await callbackArg(parentObjectArg[propertyNameArg]); | ||||
|   } | ||||
| }; | ||||
							
								
								
									
										5
									
								
								ts/tools/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								ts/tools/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| export * from './compareobjects'; | ||||
| export * from './exists'; | ||||
| export * from './foreachminimatch'; | ||||
| export * from './smart_add_get'; | ||||
| export * from './toFlatObject'; | ||||
							
								
								
									
										92
									
								
								ts/tools/smart_add_get.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								ts/tools/smart_add_get.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| import * as plugins from '../smartobject.plugins'; | ||||
|  | ||||
| /** | ||||
|  * adds an object to the parent object if it doesn't exists | ||||
|  * @param parentObject | ||||
|  * @param childParam | ||||
|  * @param logBool | ||||
|  * @returns {boolean} | ||||
|  */ | ||||
|  export const smartAdd = ( | ||||
|   parentObject: object, | ||||
|   childParam: string, | ||||
|   valueArg: any = {}, | ||||
|   optionsArg?: { | ||||
|     interpretDotsAsLevel: boolean; | ||||
|   } | ||||
| ): typeof parentObject & any => { | ||||
|   optionsArg = { | ||||
|     interpretDotsAsLevel: true, | ||||
|     ...optionsArg | ||||
|   }; | ||||
|  | ||||
|   let paramLevels: string[]; | ||||
|   let referencePointer: any = parentObject; | ||||
|   if (optionsArg.interpretDotsAsLevel) { | ||||
|     paramLevels = childParam.split('.'); | ||||
|   } else { | ||||
|     paramLevels = [childParam]; | ||||
|   } | ||||
|  | ||||
|   for (let i = 0; i !== paramLevels.length; i++) { | ||||
|     const varName: string = paramLevels[i]; | ||||
|  | ||||
|     // is there a next variable ? | ||||
|     const varNameNext: string = (() => { | ||||
|       if (paramLevels[i + 1]) { | ||||
|         return paramLevels[i + 1]; | ||||
|       } | ||||
|       return null; | ||||
|     })(); | ||||
|  | ||||
|     // build the tree in parentObject | ||||
|     if (!referencePointer[varName] && !varNameNext) { | ||||
|       referencePointer[varName] = valueArg; | ||||
|       referencePointer = null; | ||||
|     } else if (!referencePointer[varName] && varNameNext) { | ||||
|       referencePointer[varName] = {}; | ||||
|       referencePointer = referencePointer[varName]; | ||||
|     } else if (referencePointer[varName] && varNameNext) { | ||||
|       referencePointer = referencePointer[varName]; | ||||
|     } else { | ||||
|       throw new Error('Something is strange!'); | ||||
|     } | ||||
|   } | ||||
|   return parentObject; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * gets an object from the parent object using dots as levels by default | ||||
|  * @param parentObject | ||||
|  * @param childParam | ||||
|  * @param optionsArg | ||||
|  */ | ||||
| export const smartGet = <T>( | ||||
|   parentObject: object, | ||||
|   childParam: string, | ||||
|   optionsArg?: { | ||||
|     interpretDotsAsLevel: boolean; | ||||
|   } | ||||
| ): T => { | ||||
|   optionsArg = { | ||||
|     interpretDotsAsLevel: true, | ||||
|     ...optionsArg | ||||
|   }; | ||||
|  | ||||
|   let paramLevels: string[]; | ||||
|   if (optionsArg.interpretDotsAsLevel) { | ||||
|     paramLevels = childParam.split('.'); | ||||
|   } else { | ||||
|     paramLevels = [childParam]; | ||||
|   } | ||||
|  | ||||
|   let referencePointer: any = parentObject; | ||||
|   for (const level of paramLevels) { | ||||
|     if (referencePointer[level as any]) { | ||||
|       referencePointer = referencePointer[level as any]; | ||||
|     } else { | ||||
|       return null; | ||||
|     } | ||||
|   } | ||||
|   return referencePointer as T; | ||||
| }; | ||||
							
								
								
									
										18
									
								
								ts/tools/toFlatObject.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								ts/tools/toFlatObject.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| export const toFlatObject = (objectArg: object) => { | ||||
|   const returnObject: {[key: string]: any} = {}; | ||||
|   const extractLayer = (subObject: {[key: string]: any}, pathArg: string, loopProtection: object[]) => { | ||||
|     if (subObject) | ||||
|       for (const key of Object.keys(subObject)) { | ||||
|         let localPathArg = pathArg; | ||||
|         if (typeof subObject[ key ] === 'object') { | ||||
|           const newLoopbackArray = loopProtection.slice(); | ||||
|           newLoopbackArray.push(subObject); | ||||
|           extractLayer(subObject[ key ], localPathArg ? localPathArg += `.${key}` : key, newLoopbackArray); | ||||
|         } else { | ||||
|           returnObject[localPathArg ? localPathArg += `.${key}` : key] = subObject[key]; | ||||
|         } | ||||
|       } | ||||
|   } | ||||
|   extractLayer(objectArg, '', []); | ||||
|   return returnObject; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user