Compare commits

...

4 Commits

Author SHA1 Message Date
2dfa96bbc5 3.0.2 2018-11-23 20:33:45 +01:00
a7484e791a fix(core): update 2018-11-23 20:33:44 +01:00
2dba68df8c Merge branch 'master' into 'master'
implement JSON methods for tree

See merge request pushrocks/lik!1
2018-09-01 14:38:56 +00:00
6aff4c9031 implement JSON methods for tree 2018-08-31 17:24:35 +02:00
16 changed files with 996 additions and 187 deletions

View File

@ -26,6 +26,7 @@ mirror:
snyk: snyk:
stage: security stage: security
script: script:
- npmci npm prepare
- npmci command npm install -g snyk - npmci command npm install -g snyk
- npmci command npm install --ignore-scripts - npmci command npm install --ignore-scripts
- npmci command snyk test - npmci command snyk test
@ -39,6 +40,7 @@ snyk:
testLEGACY: testLEGACY:
stage: test stage: test
script: script:
- npmci npm prepare
- npmci node install legacy - npmci node install legacy
- npmci npm install - npmci npm install
- npmci npm test - npmci npm test
@ -51,6 +53,7 @@ testLEGACY:
testLTS: testLTS:
stage: test stage: test
script: script:
- npmci npm prepare
- npmci node install lts - npmci node install lts
- npmci npm install - npmci npm install
- npmci npm test - npmci npm test
@ -62,6 +65,7 @@ testLTS:
testSTABLE: testSTABLE:
stage: test stage: test
script: script:
- npmci npm prepare
- npmci node install stable - npmci node install stable
- npmci npm install - npmci npm install
- npmci npm test - npmci npm test
@ -117,8 +121,10 @@ pages:
image: hosttoday/ht-docker-node:npmci image: hosttoday/ht-docker-node:npmci
stage: metadata stage: metadata
script: script:
- npmci command npm install -g npmpage - npmci command npm install -g typedoc typescript
- npmci command npmpage - npmci npm prepare
- npmci npm install
- npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/
tags: tags:
- docker - docker
- notpriv - notpriv
@ -129,13 +135,3 @@ pages:
paths: paths:
- public - public
allow_failure: true allow_failure: true
windowsCompatibility:
image: stefanscherer/node-windows:10-build-tools
stage: metadata
script:
- npm install & npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- windows
allow_failure: true

775
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,13 @@
{ {
"name": "@pushrocks/lik", "name": "@pushrocks/lik",
"version": "3.0.1", "version": "3.0.2",
"private": false, "private": false,
"description": "light little helpers for node", "description": "light little helpers for node",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "dist/index.d.ts", "typings": "dist/index.d.ts",
"scripts": { "scripts": {
"test": "tsrun test/test.ts", "test": "(tstest test/)",
"build": "(npmts)" "build": "(tsbuild)"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -20,15 +20,20 @@
}, },
"homepage": "https://gitlab.com/pushrocks/lik#README", "homepage": "https://gitlab.com/pushrocks/lik#README",
"devDependencies": { "devDependencies": {
"@gitzone/tsrun": "^1.1.9", "@gitzone/tsbuild": "^2.0.22",
"@pushrocks/tapbundle": "^3.0.1", "@gitzone/tsrun": "^1.1.13",
"@types/node": "^10.5.2" "@gitzone/tstest": "^1.0.15",
"@pushrocks/tapbundle": "^3.0.7",
"@types/node": "^10.12.10",
"tslint": "^5.11.0",
"tslint-config-prettier": "^1.16.0"
}, },
"dependencies": { "dependencies": {
"@pushrocks/smartdelay": "^2.0.2",
"@pushrocks/smartpromise": "^2.0.5", "@pushrocks/smartpromise": "^2.0.5",
"@types/lodash": "^4.14.112", "@pushrocks/smartrx": "^2.0.2",
"@pushrocks/smarttime": "^3.0.5",
"@types/minimatch": "^3.0.3", "@types/minimatch": "^3.0.3",
"lodash": "^4.17.10",
"minimatch": "^3.0.4", "minimatch": "^3.0.4",
"symbol-tree": "^3.2.2" "symbol-tree": "^3.2.2"
} }

25
test/test.interestmap.ts Normal file
View File

@ -0,0 +1,25 @@
import { tap, expect } from '@pushrocks/tapbundle';
import * as lik from '../ts/index';
let testInterestmap: lik.InterestMap<number, number>;
tap.test('should create an interestmap', async () => {
testInterestmap = new lik.InterestMap((numberArg) => {
return numberArg.toString();
});
});
tap.test('should create an interest', async () => {
testInterestmap.addInterest(3);
testInterestmap.addInterest(4);
});
tap.test('should return an already existing interest', async () => {
await testInterestmap.addInterest(3);
});
tap.test('should be able to inform about a lost interest', async () => {
testInterestmap.informLostInterest(3);
});
tap.start();

View File

@ -1,7 +1,7 @@
// import test framework // import test framework
import { expect, tap } from '@pushrocks/tapbundle'; import { expect, tap } from '@pushrocks/tapbundle';
import * as events from 'events'; import * as events from 'events';
import * as smartq from 'smartq'; import * as smartpromise from '@pushrocks/smartpromise';
// import the module // import the module
import * as lik from '../ts/index'; import * as lik from '../ts/index';

View File

@ -1,7 +1,7 @@
// import test framework // import test framework
import { expect, tap } from '@pushrocks/tapbundle'; import { expect, tap } from '@pushrocks/tapbundle';
import * as events from 'events'; import * as events from 'events';
import * as smartq from 'smartq'; import * as smartpromise from '@pushrocks/smartpromise';
// import the module // import the module
import * as lik from '../ts/index'; import * as lik from '../ts/index';

View File

@ -1,7 +1,7 @@
// import test framework // import test framework
import { expect, tap } from '@pushrocks/tapbundle'; import { expect, tap } from '@pushrocks/tapbundle';
import * as events from 'events'; import * as events from 'events';
import * as smartq from 'smartq'; import * as smartpromise from '@pushrocks/smartpromise';
// import the module // import the module
import * as lik from '../ts/index'; import * as lik from '../ts/index';

View File

@ -1,14 +1,20 @@
import { tap, expect } from '@pushrocks/tapbundle'; import { tap, expect } from '@pushrocks/tapbundle';
import * as lik from '../ts/index'; import * as lik from '../ts/index';
let testTree = new lik.Tree<TestClass>();
class TestClass { class TestClass {
constructor(public hey: string) { constructor(public hey: string) {
// nothing here // nothing here
} }
} }
let testTree = new lik.Tree<TestClass>();
let testInstance = new TestClass('first'); let testInstance = new TestClass('first');
let testInstance2 = new TestClass('second');
let testInstance3 = new TestClass('third');
let testInstance4 = new TestClass('fourth');
let testInstance5 = new TestClass('fifth');
let testInstance6 = new TestClass('sixth');
tap.test('create a valid tree instance', async () => { tap.test('create a valid tree instance', async () => {
testTree = new lik.Tree(); testTree = new lik.Tree();
@ -21,4 +27,14 @@ tap.test('should insert an object', async () => {
expect(resultArray).to.contain(testInstance); expect(resultArray).to.contain(testInstance);
}); });
tap.test('should add other objects in a hierachy', async () => {
testTree.appendChild(testInstance, testInstance2);
testTree.appendChild(testInstance, testInstance3);
testTree.appendChild(testInstance, testInstance4);
});
tap.test("should create a JSON object that reflects a tree's hierachy", async () => {
const jsonTreet = testTree.toJsonWithHierachy(testInstance);
});
tap.start(); tap.start();

View File

@ -2,8 +2,9 @@ import * as plugins from './lik.plugins';
// import modules // import modules
export * from './lik.interestmap';
export * from './lik.limitedarray';
export * from './lik.looptracker'; export * from './lik.looptracker';
export * from './lik.objectmap'; export * from './lik.objectmap';
export * from './lik.stringmap'; export * from './lik.stringmap';
export * from './lik.limitedarray';
export * from './lik.tree'; export * from './lik.tree';

View File

@ -0,0 +1,76 @@
import * as plugins from './lik.plugins';
import { InterestMap, IInterestComparisonFunc} from './lik.interestmap';
export class Interest<DTInterestId, DTInterestFullfillment> {
private interestMapRef: InterestMap<DTInterestId, DTInterestFullfillment>;
public originalInterest: DTInterestId;
public comparisonFunc: IInterestComparisonFunc<DTInterestId>;
public destructionTimer = new plugins.smarttime.Timer(10000);
public isFullfilled = false;
/**
* a generic store to store objects in that are needed for fullfillment;
*/
public fullfillmentStore: any[] = [];
/**
* quick access to a string that makes the interest comparable for checking for similar interests
*/
public get comparisonString() {
return this.comparisonFunc(this.originalInterest);
}
private interestDeferred: plugins.smartpromise.Deferred<DTInterestFullfillment> = new plugins.smartpromise.Deferred();
public interestFullfilled = this.interestDeferred.promise;
/**
* fullfill the interest
*/
public fullfillInterest(objectArg: DTInterestFullfillment) {
this.isFullfilled = true;
this.fullfillmentStore = [];
this.interestDeferred.resolve(objectArg);
}
/**
*
*/
constructor(
interestMapArg: InterestMap<DTInterestId, DTInterestFullfillment>,
interestArg: DTInterestId,
comparisonFuncArg: IInterestComparisonFunc<DTInterestId>
) {
this.originalInterest = interestArg;
this.comparisonFunc = comparisonFuncArg;
this.interestMapRef = interestMapArg;
this.destructionTimer.completed.then(() => {
this.destroy();
});
}
// ===============================
// LIFECYCLE MANAGEMENT
// ===============================
/**
* self destructs the interest
*/
public destroy() {
this.interestMapRef.removeInterest(this);
}
/**
* notifies the interest that the interest in it has been lost
*/
public markLost() {
this.destructionTimer.start();
}
/**
* notifies the interest that the interest in it has been restored
*/
public renew() {
this.destructionTimer.reset();
}
}

117
ts/lik.interestmap.ts Normal file
View File

@ -0,0 +1,117 @@
import * as plugins from './lik.plugins';
import { Objectmap } from './lik.objectmap';
import { Observable } from 'rxjs';
import { Interest } from './lik.interestmap.interest';
export type IInterestComparisonFunc<T> = (objectArg: T) => string;
export class InterestMap<DTInterestId, DTInterestFullfillment> {
/**
* stores interests that are currently fullfilled by the cache
*/
private interestObjectMap = new Objectmap<Interest<DTInterestId, DTInterestFullfillment>>();
/**
* a function to compare interests
*/
private comparisonFunc: IInterestComparisonFunc<DTInterestId>;
constructor(comparisonFuncArg: IInterestComparisonFunc<DTInterestId>) {
this.comparisonFunc = comparisonFuncArg;
}
/**
* adds an interest to the InterestMap
* @param objectArg
*/
public async addInterest(
objectArg: DTInterestId
): Promise<Interest<DTInterestId, DTInterestFullfillment>> {
const comparisonString = this.comparisonFunc(objectArg);
let returnInterest: Interest<DTInterestId, DTInterestFullfillment>;
const newInterest = new Interest<DTInterestId, DTInterestFullfillment>(
this,
objectArg,
this.comparisonFunc
);
let interestExists = false;
await this.interestObjectMap.forEach(interestArg => {
if (!interestExists && interestArg.comparisonString === newInterest.comparisonString) {
console.log('info', `interest already exists for ${newInterest.comparisonString}`);
interestExists = true;
returnInterest = interestArg;
returnInterest.renew();
}
});
if (!returnInterest) {
returnInterest = newInterest;
this.interestObjectMap.add(returnInterest);
}
this.interestObservable.push(returnInterest);
return returnInterest;
}
// tslint:disable-next-line:member-ordering
public interestObservable = new plugins.smartrx.ObservableIntake<Interest<DTInterestId, any>>();
/**
* removes an interest from the interest map
* @param objectArg removes an interest from the InterestMap
*/
public removeInterest(interestArg: Interest<DTInterestId, DTInterestFullfillment>) {
const interestToRemove = this.interestObjectMap.findOneAndRemove(interestArg2 => {
return interestArg.comparisonString === interestArg2.comparisonString;
});
}
/**
* check interest
*/
public checkInterest(objectArg: DTInterestId): boolean {
const comparisonString = this.comparisonFunc(objectArg);
return this.checkInterestByString(comparisonString);
}
/**
* checks an interest
* @param comparisonStringArg
*/
public checkInterestByString(comparisonStringArg: string): boolean {
const foundInterest = this.interestObjectMap.find(interest => {
return interest.comparisonString === comparisonStringArg;
});
if (foundInterest) {
return true;
} else {
return false;
}
}
/**
* inform lost interest
* @param interestId
*/
public informLostInterest (interestId: DTInterestId) {
const wantedInterest = this.findInterest(interestId);
if (wantedInterest) {
wantedInterest.markLost();
}
}
/**
* finds an interest
* @param objectArg
*/
public findInterest(objectArg: DTInterestId): Interest<DTInterestId, DTInterestFullfillment> {
const comparableString = this.comparisonFunc(objectArg);
const interest = this.interestObjectMap.find(interest => {
return interest.comparisonString === comparableString;
});
return interest; // if an interest is found, the interest is returned, otherwise interest is null
}
}

View File

@ -26,7 +26,7 @@ export class Objectmap<T> {
* 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
*/ */
add(objectArg: T): boolean { public add(objectArg: T): boolean {
if (this.checkForObject(objectArg)) { if (this.checkForObject(objectArg)) {
// the object is already in the objectmap // the object is already in the objectmap
return false; return false;
@ -40,7 +40,7 @@ export class Objectmap<T> {
/** /**
* like .add but adds an whole array of objects * like .add but adds an whole array of objects
*/ */
addArray(objectArrayArg: T[]) { public addArray(objectArrayArg: T[]) {
for (let item of objectArrayArg) { for (let item of objectArrayArg) {
this.add(item); this.add(item);
} }
@ -49,15 +49,15 @@ export class Objectmap<T> {
/** /**
* check if object is in Objectmap * check if object is in Objectmap
*/ */
checkForObject(objectArg: T) { public checkForObject(objectArg: T) {
return this.objectArray.indexOf(objectArg) !== -1; return this.objectArray.indexOf(objectArg) !== -1;
} }
/** /**
* find object * find object
*/ */
find(findFunction: IObjectmapFindFunction<T>) { public find(findFunction: IObjectmapFindFunction<T>) {
let resultArray = this.objectArray.filter(findFunction); const resultArray = this.objectArray.filter(findFunction);
if (resultArray.length > 0) { if (resultArray.length > 0) {
return resultArray[0]; return resultArray[0];
} else { } else {
@ -68,8 +68,8 @@ export class Objectmap<T> {
/** /**
* finds a specific element and then removes it * finds a specific element and then removes it
*/ */
findOneAndRemove(findFunction: IObjectmapFindFunction<T>): T { public findOneAndRemove(findFunction: IObjectmapFindFunction<T>): T {
let foundElement = this.find(findFunction); const foundElement = this.find(findFunction);
if (foundElement) { if (foundElement) {
this.remove(foundElement); this.remove(foundElement);
} }
@ -79,7 +79,7 @@ export class Objectmap<T> {
/** /**
* run function for each item in Objectmap * run function for each item in Objectmap
*/ */
async forEach(functionArg: IObjectmapForEachFunction<T>) { public async forEach(functionArg: IObjectmapForEachFunction<T>) {
for (let object of this.objectArray) { for (let object of this.objectArray) {
await functionArg(object); await functionArg(object);
} }
@ -88,21 +88,25 @@ 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
*/ */
getOneAndRemove(): T { public getOneAndRemove(): T {
return this.objectArray.shift(); return this.objectArray.shift();
} }
/** /**
* returns a cloned array of all the objects currently in the Objectmap * returns a cloned array of all the objects currently in the Objectmap
*/ */
getArray() { public getArray() {
return plugins.lodash.cloneDeep(this.objectArray); const returnArray: any[] = [];
for (const objectItem of this.objectArray) {
returnArray.push(objectItem);
}
return returnArray;
} }
/** /**
* check if Objectmap ist empty * check if Objectmap ist empty
*/ */
isEmpty(): boolean { public isEmpty(): boolean {
if (this.objectArray.length === 0) { if (this.objectArray.length === 0) {
return true; return true;
} else { } else {
@ -113,7 +117,7 @@ export class Objectmap<T> {
/** /**
* remove object from Objectmap * remove object from Objectmap
*/ */
remove(objectArg: T) { public remove(objectArg: T) {
let replacementArray = []; let replacementArray = [];
for (let item of this.objectArray) { for (let item of this.objectArray) {
if (item !== objectArg) { if (item !== objectArg) {
@ -126,7 +130,7 @@ export class Objectmap<T> {
/** /**
* wipe Objectmap * wipe Objectmap
*/ */
wipe() { public wipe() {
this.objectArray = []; this.objectArray = [];
} }
} }

View File

@ -1,7 +1,30 @@
// ==============
// native
// ==============
import * as events from 'events'; import * as events from 'events';
import * as lodash from 'lodash';
import * as minimatch from 'minimatch'; export { events };
// ==============
// @pushrocks
// ==============
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 smarttime from '@pushrocks/smarttime';
export {
smartdelay,
smartpromise,
smartrx,
smarttime
};
// ==============
// third party
// ==============
import * as minimatch from 'minimatch';
const symbolTree = require('symbol-tree'); const symbolTree = require('symbol-tree');
export { events, lodash, minimatch, smartpromise, symbolTree }; export { minimatch, symbolTree };

View File

@ -52,14 +52,14 @@ export class Stringmap {
/** /**
* check if string is in Stringmap * check if string is in Stringmap
*/ */
checkString(stringArg: string): boolean { public checkString(stringArg: string): boolean {
return this._stringArray.indexOf(stringArg) !== -1; return this._stringArray.indexOf(stringArg) !== -1;
} }
/** /**
* checks stringPresence with minimatch * checks stringPresence with minimatch
*/ */
checkMinimatch(miniMatchStringArg: string): boolean { public checkMinimatch(miniMatchStringArg: string): boolean {
let foundMatch: boolean = false; let foundMatch: boolean = false;
for (let stringItem of this._stringArray) { for (let stringItem of this._stringArray) {
if (plugins.minimatch(stringItem, miniMatchStringArg)) { if (plugins.minimatch(stringItem, miniMatchStringArg)) {
@ -72,15 +72,19 @@ export class Stringmap {
/** /**
* checks if the Stringmap is empty * checks if the Stringmap is empty
*/ */
checkIsEmpty() { public checkIsEmpty() {
return this._stringArray.length === 0; return this._stringArray.length === 0;
} }
/** /**
* gets a cloned copy of the current string Array * gets a cloned copy of the current string Array
*/ */
getStringArray() { public getStringArray() {
return plugins.lodash.cloneDeep(this._stringArray); const returnArray: string[] = [];
for (const stringItem of this._stringArray) {
returnArray.push(stringItem);
}
return returnArray;
} }
// trigger registering // trigger registering
@ -88,7 +92,7 @@ export class Stringmap {
/** /**
* register a new trigger * register a new trigger
*/ */
registerUntilTrue(functionArg: ITriggerFunction, doFunctionArg) { public registerUntilTrue(functionArg: ITriggerFunction, doFunctionArg) {
this._triggerUntilTrueFunctionArray.push(() => { this._triggerUntilTrueFunctionArray.push(() => {
let result = functionArg(); let result = functionArg();
if (result === true) { if (result === true) {

View File

@ -6,6 +6,10 @@ export class Tree<T> {
this.symbolTree = new plugins.symbolTree(); this.symbolTree = new plugins.symbolTree();
} }
// =======================================
// Functions that map to the functionality of symbol-tree
// =======================================
/** /**
* *
* @param objectArg * @param objectArg
@ -78,7 +82,7 @@ export class Tree<T> {
this.symbolTree.ancestorsIterator(); this.symbolTree.ancestorsIterator();
} }
treeIterator(rootArg: T, optionsArg): T { treeIterator(rootArg: T, optionsArg): Iterable<T> {
return this.symbolTree.treeIterator(rootArg); return this.symbolTree.treeIterator(rootArg);
} }
@ -113,4 +117,25 @@ export class Tree<T> {
appendChild(referenceObjectArg, newObjectArg) { appendChild(referenceObjectArg, newObjectArg) {
return this.symbolTree.appendChild(referenceObjectArg, newObjectArg); return this.symbolTree.appendChild(referenceObjectArg, newObjectArg);
} }
// ===========================================
// Functionionality that extends symbol-tree
// ===========================================
/**
* returns a branch of the tree as JSON
* can be user
*/
toJsonWithHierachy(rootElement) {
const treeIterable = this.treeIterator(rootElement, {});
for (const treeItem of treeIterable) {
console.log(treeItem);
}
}
/**
* builds a tree from a JSON with hierachy
* @param rootElement
*/
fromJsonWithHierachy(rootElement) {}
} }

View File

@ -1,3 +1,17 @@
{ {
"extends": "tslint-config-standard" "extends": ["tslint:latest", "tslint-config-prettier"],
"rules": {
"semicolon": [true, "always"],
"no-console": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"member-ordering": {
"options":{
"order": [
"static-method"
]
}
}
},
"defaultSeverity": "warning"
} }