Compare commits

..

10 Commits

Author SHA1 Message Date
6fdf08c8a9 4.0.0 2020-05-04 00:09:21 +00:00
de04d75e18 BREAKING CHANGE(core): refactored ObjectMap and introduced concat feature 2020-05-04 00:09:20 +00:00
5159d7e4bf 3.0.19 2020-02-16 23:15:51 +00:00
7b78aaea72 fix(FastMap): added .clean() method 2020-02-16 23:15:50 +00:00
54a63d1f41 3.0.18 2020-02-15 21:25:50 +00:00
dd5a009d0f fix(core): update 2020-02-15 21:25:49 +00:00
e7933cd7f4 3.0.17 2020-02-07 16:32:58 +00:00
56a8d9182b fix(core): update 2020-02-07 16:32:58 +00:00
3a971301a4 3.0.16 2020-02-06 15:31:59 +00:00
b880036b64 fix(Objectmap): switch to an object map with unique keys 2020-02-06 15:31:58 +00:00
9 changed files with 223 additions and 68 deletions

41
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "@pushrocks/lik", "name": "@pushrocks/lik",
"version": "3.0.15", "version": "4.0.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -385,6 +385,17 @@
"luxon": "^1.16.0" "luxon": "^1.16.0"
} }
}, },
"@pushrocks/smartunique": {
"version": "3.0.1",
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartunique/-/smartunique-3.0.1.tgz",
"integrity": "sha512-xBu9ZB4C0BA0S/pbFFZn2ItPfnodPKpzrYIq1yN5XDs6OaookwcDF/iBwfS9+EYMSPENC9wAsOxg2RGMm4Qicw==",
"requires": {
"@types/shortid": "^0.0.29",
"@types/uuid": "^3.0.0",
"shortid": "^2.2.8",
"uuid": "^3.1.0"
}
},
"@pushrocks/tapbundle": { "@pushrocks/tapbundle": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://verdaccio.lossless.one/@pushrocks%2ftapbundle/-/tapbundle-3.2.0.tgz", "resolved": "https://verdaccio.lossless.one/@pushrocks%2ftapbundle/-/tapbundle-3.2.0.tgz",
@ -540,6 +551,11 @@
"resolved": "https://verdaccio.lossless.one/@types%2fnode/-/node-13.7.0.tgz", "resolved": "https://verdaccio.lossless.one/@types%2fnode/-/node-13.7.0.tgz",
"integrity": "sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ==" "integrity": "sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ=="
}, },
"@types/shortid": {
"version": "0.0.29",
"resolved": "https://verdaccio.lossless.one/@types%2fshortid/-/shortid-0.0.29.tgz",
"integrity": "sha1-gJPuBBam4r8qpjOBCRFLP7/6Dps="
},
"@types/through2": { "@types/through2": {
"version": "2.0.34", "version": "2.0.34",
"resolved": "https://verdaccio.lossless.one/@types%2fthrough2/-/through2-2.0.34.tgz", "resolved": "https://verdaccio.lossless.one/@types%2fthrough2/-/through2-2.0.34.tgz",
@ -549,6 +565,11 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/uuid": {
"version": "3.4.7",
"resolved": "https://verdaccio.lossless.one/@types%2fuuid/-/uuid-3.4.7.tgz",
"integrity": "sha512-C2j2FWgQkF1ru12SjZJyMaTPxs/f6n90+5G5qNakBxKXjTBc/YTSelHh4Pz1HUDwxFXD9WvpQhOGCDC+/Y4mIQ=="
},
"@types/vinyl": { "@types/vinyl": {
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://verdaccio.lossless.one/@types%2fvinyl/-/vinyl-2.0.3.tgz", "resolved": "https://verdaccio.lossless.one/@types%2fvinyl/-/vinyl-2.0.3.tgz",
@ -1259,6 +1280,11 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true "dev": true
}, },
"nanoid": {
"version": "2.1.11",
"resolved": "https://verdaccio.lossless.one/nanoid/-/nanoid-2.1.11.tgz",
"integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA=="
},
"nice-try": { "nice-try": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://verdaccio.lossless.one/nice-try/-/nice-try-1.0.5.tgz", "resolved": "https://verdaccio.lossless.one/nice-try/-/nice-try-1.0.5.tgz",
@ -1542,6 +1568,14 @@
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
"dev": true "dev": true
}, },
"shortid": {
"version": "2.2.15",
"resolved": "https://verdaccio.lossless.one/shortid/-/shortid-2.2.15.tgz",
"integrity": "sha512-5EaCy2mx2Jgc/Fdn9uuDuNIIfWBpzY4XIlhoqtXF6qsf+/+SGZ+FxDdX/ZsMZiWupIWNqAEmiNY4RC+LSmCeOw==",
"requires": {
"nanoid": "^2.1.0"
}
},
"signal-exit": { "signal-exit": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://verdaccio.lossless.one/signal-exit/-/signal-exit-3.0.2.tgz", "resolved": "https://verdaccio.lossless.one/signal-exit/-/signal-exit-3.0.2.tgz",
@ -1755,6 +1789,11 @@
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true "dev": true
}, },
"uuid": {
"version": "3.4.0",
"resolved": "https://verdaccio.lossless.one/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"vinyl": { "vinyl": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://verdaccio.lossless.one/vinyl/-/vinyl-2.2.0.tgz", "resolved": "https://verdaccio.lossless.one/vinyl/-/vinyl-2.2.0.tgz",

View File

@ -1,6 +1,6 @@
{ {
"name": "@pushrocks/lik", "name": "@pushrocks/lik",
"version": "3.0.15", "version": "4.0.0",
"private": false, "private": false,
"description": "light little helpers for node", "description": "light little helpers for node",
"main": "dist/index.js", "main": "dist/index.js",
@ -33,6 +33,7 @@
"@pushrocks/smartpromise": "^3.0.6", "@pushrocks/smartpromise": "^3.0.6",
"@pushrocks/smartrx": "^2.0.5", "@pushrocks/smartrx": "^2.0.5",
"@pushrocks/smarttime": "^3.0.12", "@pushrocks/smarttime": "^3.0.12",
"@pushrocks/smartunique": "^3.0.1",
"@types/minimatch": "^3.0.3", "@types/minimatch": "^3.0.3",
"minimatch": "^3.0.4", "minimatch": "^3.0.4",
"symbol-tree": "^3.2.4" "symbol-tree": "^3.2.4"

View File

@ -11,7 +11,7 @@ interface ITestObject {
propOne: string; propOne: string;
propTwo: string; propTwo: string;
} }
let testObjectmap: lik.Objectmap<ITestObject>; let testObjectmap: lik.ObjectMap<ITestObject>;
let testObject1: ITestObject = { let testObject1: ITestObject = {
propOne: 'hello', propOne: 'hello',
propTwo: 'hello2' propTwo: 'hello2'
@ -22,8 +22,8 @@ let testObject2: ITestObject = {
}; };
tap.test('new lik.Objectmap() -> should correctly instantiate an Objectmap', async () => { tap.test('new lik.Objectmap() -> should correctly instantiate an Objectmap', async () => {
testObjectmap = new lik.Objectmap<ITestObject>(); testObjectmap = new lik.ObjectMap<ITestObject>();
expect(testObjectmap).be.instanceof(lik.Objectmap); expect(testObjectmap).be.instanceof(lik.ObjectMap);
}); });
tap.test('lik.Objectmap.add() -> should correctly add an object to Objectmap', async () => { tap.test('lik.Objectmap.add() -> should correctly add an object to Objectmap', async () => {

View File

@ -1,7 +1,4 @@
import * as plugins from './lik.plugins'; export * from './lik.fastmap';
// import modules
export * from './lik.interestmap'; export * from './lik.interestmap';
export * from './lik.limitedarray'; export * from './lik.limitedarray';
export * from './lik.looptracker'; export * from './lik.looptracker';

View File

@ -1,11 +1,82 @@
import * as plugins from './lik.plugins'; import * as plugins from './lik.plugins';
/**
* fast map allows for very quick lookups of objects with a unique key
*/
export class FastMap<T> { export class FastMap<T> {
private mapObject: { [key: string]: T } = {}; private mapObject: { [key: string]: T } = {};
public isUniqueKey() {} public isUniqueKey(keyArg: string): boolean {
return this.mapObject[keyArg] ? false : true;
}
public addToMap(identifier: string, objectArg: T) { public addToMap(
this.mapObject[identifier] = objectArg; keyArg: string,
objectArg: T,
optionsArg?: {
force: boolean;
}
): boolean {
if (this.isUniqueKey(keyArg) || (optionsArg && optionsArg.force)) {
this.mapObject[keyArg] = objectArg;
return true;
} else {
return false;
}
}
public getByKey(keyArg: string) {
return this.mapObject[keyArg];
}
public removeFromMap(keyArg): T {
const removedItem = this.getByKey(keyArg);
delete this.mapObject[keyArg];
return removedItem;
}
public getKeys() {
const keys: string[] = [];
for (const keyArg in this.mapObject) {
if (this.mapObject[keyArg]) {
keys.push(keyArg);
}
}
return keys;
}
public clean() {
this.mapObject = {};
}
/**
* returns a new Objectmap that includes
*/
public concat(fastMapArg: FastMap<T>) {
const concatedFastmap = new FastMap<T>();
for (const key of this.getKeys()) {
concatedFastmap.addToMap(key, this.getByKey(key));
}
for (const key of fastMapArg.getKeys()) {
concatedFastmap.addToMap(key, fastMapArg.getByKey(key), {
force: true
});
}
return concatedFastmap;
}
/**
* tries to merge another Objectmap
* Note: uniqueKeyCollisions will cause overwrite
* @param objectMapArg
*/
public addAllFromOther(fastMapArg: FastMap<T>) {
for (const key of fastMapArg.getKeys()) {
this.addToMap(key, fastMapArg.getByKey(key), {
force: true
});
}
} }
} }

View File

@ -1,5 +1,5 @@
import * as plugins from './lik.plugins'; import * as plugins from './lik.plugins';
import { Objectmap } from './lik.objectmap'; import { ObjectMap } from './lik.objectmap';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
@ -11,7 +11,7 @@ export class InterestMap<DTInterestId, DTInterestFullfillment> {
/** /**
* stores interests that are currently fullfilled by the cache * stores interests that are currently fullfilled by the cache
*/ */
private interestObjectMap = new Objectmap<Interest<DTInterestId, DTInterestFullfillment>>(); private interestObjectMap = new ObjectMap<Interest<DTInterestId, DTInterestFullfillment>>();
/** /**
* a function to compare interests * a function to compare interests
@ -106,8 +106,8 @@ export class InterestMap<DTInterestId, DTInterestFullfillment> {
*/ */
public findInterest(objectArg: DTInterestId): Interest<DTInterestId, DTInterestFullfillment> { public findInterest(objectArg: DTInterestId): Interest<DTInterestId, DTInterestFullfillment> {
const comparableString = this.comparisonFunc(objectArg); const comparableString = this.comparisonFunc(objectArg);
const interest = this.interestObjectMap.find(interest => { const interest = this.interestObjectMap.find(interestArg => {
return interest.comparisonString === comparableString; return interestArg.comparisonString === comparableString;
}); });
return interest; // if an interest is found, the interest is returned, otherwise interest is null return interest; // if an interest is found, the interest is returned, otherwise interest is null
} }

View File

@ -1,9 +1,9 @@
import * as plugins from './lik.plugins'; import * as plugins from './lik.plugins';
import { Objectmap } from './lik.objectmap'; import { ObjectMap } from './lik.objectmap';
export class LoopTracker<T> { export class LoopTracker<T> {
referenceObjectMap = new Objectmap<any>(); referenceObjectMap = new ObjectMap<any>();
constructor() { constructor() {
// nothing here // nothing here
} }
@ -12,7 +12,12 @@ export class LoopTracker<T> {
* checks and tracks an object * checks and tracks an object
* @param objectArg * @param objectArg
*/ */
checkAndTrack(objectArg: T) { checkAndTrack(objectArg: T): boolean {
return this.referenceObjectMap.add(objectArg); if (!this.referenceObjectMap.checkForObject(objectArg)) {
this.referenceObjectMap.add(objectArg);
return true;
} else {
return false;
}
} }
} }

View File

@ -12,9 +12,8 @@ export interface IObjectmapFindFunction<T> {
/** /**
* allows keeping track of objects * allows keeping track of objects
*/ */
export class Objectmap<T> { export class ObjectMap<T> {
private fastMap = new FastMap<T>(); private fastMap = new FastMap<T>();
private objectArray: T[] = [];
// events // events
public eventSubject = new plugins.smartrx.rxjs.Subject<any>(); public eventSubject = new plugins.smartrx.rxjs.Subject<any>();
@ -30,45 +29,51 @@ export class Objectmap<T> {
* adds an object mapped to a string * adds an object mapped to a string
* the string must be unique * the string must be unique
*/ */
addMappedUnique(uniqueKey: string, objectArg: T) { addMappedUnique(uniqueKeyArg: string, objectArg: T) {
this.add(objectArg); this.fastMap.addToMap(uniqueKeyArg, objectArg);
this.fastMap.addToMap(uniqueKey, objectArg);
} }
/** /**
* fastest way to get an object from the map * fastest way to get an object from the map
* @param uniqueKey * @param uniqueKey
*/ */
public getMappedUnique(uniqueKey: string) {} public getMappedUnique(uniqueKeyArg: string) {
return this.fastMap.getByKey(uniqueKeyArg);
}
/** /**
* remove key * remove key
* @param functionArg * @param functionArg
*/ */
public removeMappedUnique() {} public removeMappedUnique(uniqueKey: string) {
const object = this.getMappedUnique(uniqueKey);
}
/** /**
* add object to Objectmap * add object to Objectmap
* returns false if the object is already in the map * returns false if the object is already in the map
* returns true if the object was added successfully * returns true if the object was added successfully
*/ */
public add(objectArg: T): boolean { public add(objectArg: T): string {
if (this.checkForObject(objectArg)) { // lets search for an existing unique key
// the object is already in the objectmap for (const keyArg of this.fastMap.getKeys()) {
return false; const object = this.fastMap.getByKey(keyArg);
} else { if (object === objectArg) {
// the object is not yet in the objectmap return keyArg;
this.objectArray.push(objectArg); }
this.eventSubject.next('add');
return true;
} }
// otherwise lets create it
const uniqueKey = plugins.smartunique.shortId();
this.addMappedUnique(uniqueKey, objectArg);
return uniqueKey;
} }
/** /**
* like .add but adds an whole array of objects * like .add but adds an whole array of objects
*/ */
public addArray(objectArrayArg: T[]) { public addArray(objectArrayArg: T[]) {
for (let item of objectArrayArg) { for (const item of objectArrayArg) {
this.add(item); this.add(item);
} }
} }
@ -76,19 +81,34 @@ export class Objectmap<T> {
/** /**
* check if object is in Objectmap * check if object is in Objectmap
*/ */
public checkForObject(objectArg: T) { public checkForObject(objectArg: T): boolean {
return this.objectArray.indexOf(objectArg) !== -1; return !!this.getKeyForObject(objectArg);
}
/**
* get key for object
* @param findFunction
*/
public getKeyForObject(objectArg: T) {
let foundKey: string = null;
for (const keyArg of this.fastMap.getKeys()) {
if (!foundKey && this.fastMap.getByKey(keyArg) === objectArg) {
foundKey = keyArg;
} else {
continue;
}
}
return foundKey;
} }
/** /**
* find object * find object
*/ */
public find(findFunction: IObjectmapFindFunction<T>) { public find(findFunction: IObjectmapFindFunction<T>): T {
const resultArray = this.objectArray.filter(findFunction); for (const keyArg of this.fastMap.getKeys()) {
if (resultArray.length > 0) { if (findFunction(this.fastMap.getByKey(keyArg))) {
return resultArray[0]; return this.getMappedUnique(keyArg);
} else { }
return null;
} }
} }
@ -107,8 +127,8 @@ export class Objectmap<T> {
* run function for each item in Objectmap * run function for each item in Objectmap
*/ */
public async forEach(functionArg: IObjectmapForEachFunction<T>) { public async forEach(functionArg: IObjectmapForEachFunction<T>) {
for (let object of this.objectArray) { for (const keyArg of this.fastMap.getKeys()) {
await functionArg(object); await functionArg(this.fastMap.getByKey(keyArg));
} }
} }
@ -116,9 +136,15 @@ export class Objectmap<T> {
* gets an object in the Observablemap and removes it, so it can't be retrieved again * gets an object in the Observablemap and removes it, so it can't be retrieved again
*/ */
public getOneAndRemove(): T { public getOneAndRemove(): T {
const removedItem = this.objectArray.shift(); const keys = this.fastMap.getKeys();
this.eventSubject.next('remove'); if (keys.length === 0) {
return removedItem; return null;
} else {
const keyToUse = keys[0];
const removedItem = this.fastMap.removeFromMap(keyToUse);
this.eventSubject.next('remove');
return removedItem;
}
} }
/** /**
@ -126,8 +152,8 @@ export class Objectmap<T> {
*/ */
public getArray(): T[] { public getArray(): T[] {
const returnArray: any[] = []; const returnArray: any[] = [];
for (const objectItem of this.objectArray) { for (const keyArg of this.fastMap.getKeys()) {
returnArray.push(objectItem); returnArray.push(this.fastMap.getByKey(keyArg));
} }
return returnArray; return returnArray;
} }
@ -136,32 +162,47 @@ export class Objectmap<T> {
* check if Objectmap ist empty * check if Objectmap ist empty
*/ */
public isEmpty(): boolean { public isEmpty(): boolean {
if (this.objectArray.length === 0) { return this.fastMap.getKeys().length === 0;
return true;
} else {
return false;
}
} }
/** /**
* remove object from Objectmap * remove object from Objectmap
*/ */
public remove(objectArg: T) { public remove(objectArg: T): T {
let replacementArray = []; if (this.checkForObject(objectArg)) {
for (let item of this.objectArray) { const keyArg = this.getKeyForObject(objectArg);
if (item !== objectArg) { const removedObject = this.fastMap.removeFromMap(keyArg);
replacementArray.push(item); this.eventSubject.next('remove');
} return removedObject;
} }
this.objectArray = replacementArray; return null;
this.eventSubject.next('remove');
} }
/** /**
* wipe Objectmap * wipe Objectmap
*/ */
public wipe() { public wipe() {
this.objectArray = []; for (const keyArg of this.fastMap.getKeys()) {
this.eventSubject.next('wiped'); this.fastMap.removeFromMap(keyArg);
}
}
/**
* returns a new Objectmap that includes
*/
public concat(objectMapArg: ObjectMap<T>) {
const concattedObjectMap = new ObjectMap<T>();
concattedObjectMap.fastMap.addAllFromOther(this.fastMap);
concattedObjectMap.fastMap.addAllFromOther(objectMapArg.fastMap);
return concattedObjectMap;
}
/**
* tries to merge another Objectmap
* Note: uniqueKeyCollisions will cause overwrite
* @param objectMapArg
*/
public addAllFromOther(objectMapArg: ObjectMap<T>) {
this.fastMap.addAllFromOther(objectMapArg.fastMap);
} }
} }

View File

@ -13,8 +13,9 @@ import * as smartdelay from '@pushrocks/smartdelay';
import * as smartpromise from '@pushrocks/smartpromise'; import * as smartpromise from '@pushrocks/smartpromise';
import * as smartrx from '@pushrocks/smartrx'; import * as smartrx from '@pushrocks/smartrx';
import * as smarttime from '@pushrocks/smarttime'; import * as smarttime from '@pushrocks/smarttime';
import * as smartunique from '@pushrocks/smartunique';
export { smartdelay, smartpromise, smartrx, smarttime }; export { smartdelay, smartpromise, smartrx, smarttime, smartunique };
// ============== // ==============
// third party // third party