Compare commits

...

11 Commits

Author SHA1 Message Date
b8d0ec55ad 1.0.13 2019-09-25 15:28:39 +02:00
1cf78441e2 fix(core): update 2019-09-25 15:28:39 +02:00
0f34c5de55 1.0.12 2019-04-30 10:46:29 +02:00
1bd8f8371b fix(core): update 2019-04-30 10:46:28 +02:00
ef263a85b4 1.0.11 2019-04-30 10:17:29 +02:00
315156aac5 fix(core): update 2019-04-30 10:17:29 +02:00
f90a61b38b 1.0.10 2019-03-22 12:03:58 +01:00
71af6f08f3 fix(core): update 2019-03-22 12:03:58 +01:00
01e938274d 1.0.9 2019-02-27 02:00:47 +01:00
c5a3eb63ad fix(core): update 2019-02-27 02:00:47 +01:00
a4d43456d7 update action generation 2019-02-26 18:09:38 +01:00
10 changed files with 686 additions and 466 deletions

28
.gitignore vendored
View File

@ -1,6 +1,22 @@
.nogit/ .nogit/
node_modules/
coverage/ # artifacts
public/ coverage/
pages/ public/
.yarn/ pages/
# installs
node_modules/
# caches
.yarn/
.cache/
.rpt2_cache
# builds
dist/
dist_web/
dist_serve/
dist_ts_web/
# custom

View File

@ -1,5 +1,5 @@
# gitzone standard # gitzone ci_default
image: hosttoday/ht-docker-node:npmci image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache: cache:
paths: paths:
@ -34,48 +34,11 @@ snyk:
- docker - docker
- notpriv - notpriv
sast:
stage: security
image: registry.gitlab.com/hosttoday/ht-docker-dbase:npmci
variables:
DOCKER_DRIVER: overlay2
allow_failure: true
services:
- docker:stable-dind
script:
- npmci npm prepare
- npmci npm install
- npmci command npm run build
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- docker run
--env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}"
--volume "$PWD:/code"
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code
artifacts:
reports:
sast: gl-sast-report.json
tags:
- docker
- priv
# ==================== # ====================
# test stage # test stage
# ==================== # ====================
testLTS: testStable:
stage: test
script:
- npmci npm prepare
- npmci node install lts
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
testSTABLE:
stage: test stage: test
script: script:
- npmci npm prepare - npmci npm prepare
@ -85,6 +48,18 @@ testSTABLE:
coverage: /\d+.?\d+?\%\s*coverage/ coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - docker
- priv
testBuild:
stage: test
script:
- npmci npm prepare
- npmci node install stable
- npmci npm install
- npmci command npm run build
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv - notpriv
release: release:
@ -103,19 +78,11 @@ release:
# ==================== # ====================
codequality: codequality:
stage: metadata stage: metadata
image: docker:stable
allow_failure: true allow_failure: true
services:
- docker:stable-dind
script: script:
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') - npmci command npm install -g tslint typescript
- docker run - npmci npm install
--env SOURCE_CODE="$PWD" - npmci command "tslint -c tslint.json ./ts/**/*.ts"
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
paths: [codeclimate.json]
tags: tags:
- docker - docker
- priv - priv
@ -131,13 +98,15 @@ trigger:
- notpriv - notpriv
pages: pages:
image: hosttoday/ht-docker-node:npmci image: hosttoday/ht-docker-dbase:npmci
services:
- docker:stable-dind
stage: metadata stage: metadata
script: script:
- npmci command npm install -g typedoc typescript - npmci command npm install -g @gitzone/tsdoc
- npmci npm prepare - npmci npm prepare
- npmci npm install - npmci npm install
- npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/ - npmci command tsdoc
tags: tags:
- docker - docker
- notpriv - notpriv

910
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "@pushrocks/smartstate", "name": "@pushrocks/smartstate",
"version": "1.0.8", "version": "1.0.13",
"private": false, "private": false,
"description": "a package that handles state in a good way", "description": "a package that handles state in a good way",
"main": "dist/index.js", "main": "dist/index.js",
@ -13,15 +13,27 @@
"format": "(gitzone format)" "format": "(gitzone format)"
}, },
"devDependencies": { "devDependencies": {
"@gitzone/tsbuild": "^2.1.8", "@gitzone/tsbuild": "^2.1.17",
"@gitzone/tstest": "^1.0.15", "@gitzone/tstest": "^1.0.24",
"@pushrocks/tapbundle": "^3.0.7", "@pushrocks/tapbundle": "^3.0.13",
"@types/node": "^11.9.4", "@types/node": "^12.7.7",
"tslint": "^5.12.1", "tslint": "^5.20.0",
"tslint-config-prettier": "^1.18.0" "tslint-config-prettier": "^1.18.0"
}, },
"dependencies": { "dependencies": {
"@pushrocks/lik": "^3.0.4", "@pushrocks/lik": "^3.0.11",
"rxjs": "^6.4.0" "@pushrocks/smartpromise": "^3.0.5",
} "rxjs": "^6.5.3"
},
"files": [
"ts/*",
"ts_web/*",
"dist/*",
"dist_web/*",
"dist_ts_web/*",
"assets/*",
"cli.js",
"npmextra.json",
"readme.md"
]
} }

View File

@ -21,6 +21,6 @@ a package that handles state in a good way
For further information read the linked docs at the top of this readme. For further information read the linked docs at the top of this readme.
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh) > MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html) | By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
[![repo-footer](https://pushrocks.gitlab.io/assets/repo-footer.svg)](https://maintainedby.lossless.com) [![repo-footer](https://lossless.gitlab.io/publicrelations/repofooter.svg)](https://maintainedby.lossless.com)

View File

@ -30,12 +30,20 @@ tap.test('should create a new StatePart', async () => {
tap.test('should select something', async () => { tap.test('should select something', async () => {
testStatePart testStatePart
.select(state => state.deep) .select(state => state.deep.hi)
.subscribe(substate => { .subscribe(substate => {
console.log(substate); expect(substate).to.equal(2);
}); });
}); });
tap.test('should dispatch a state action', async () => {}); tap.test('should dispatch a state action', async () => {
const addFavourite = testStatePart.createAction<string>(async (statePart, payload) => {
const currentState = statePart.getState();
currentState.currentFavorites.push(payload);
return currentState;
});
await testStatePart.dispatchAction(addFavourite, 'my favourite things');
expect(testStatePart.getState().currentFavorites).to.include('my favourite things');
});
tap.start(); tap.start();

View File

@ -5,11 +5,11 @@ import { StatePart } from './smartstate.classes.statepart';
* Smartstate takes care of providing state * Smartstate takes care of providing state
*/ */
export class Smartstate<StatePartNameType> { export class Smartstate<StatePartNameType> {
statePartMap: { [key: string]: StatePart<StatePartNameType, any> } = {}; public statePartMap: { [key: string]: StatePart<StatePartNameType, any> } = {};
constructor() {} constructor() {}
getStatePart<PayloadType>( public getStatePart<PayloadType>(
statePartNameArg: StatePartNameType, statePartNameArg: StatePartNameType,
initialArg?: PayloadType initialArg?: PayloadType
): StatePart<StatePartNameType, PayloadType> { ): StatePart<StatePartNameType, PayloadType> {
@ -30,6 +30,11 @@ export class Smartstate<StatePartNameType> {
} }
} }
/**
* creates a statepart
* @param statePartName
* @param initialPayloadArg
*/
private createStatePart<PayloadType>( private createStatePart<PayloadType>(
statePartName: StatePartNameType, statePartName: StatePartNameType,
initialPayloadArg: PayloadType initialPayloadArg: PayloadType
@ -43,5 +48,5 @@ export class Smartstate<StatePartNameType> {
/** /**
* dispatches an action on the main level * dispatches an action on the main level
*/ */
dispatch() {} public dispatch() {}
} }

View File

@ -1,8 +1,17 @@
import * as plugins from './smartstate.plugins'; import * as plugins from './smartstate.plugins';
import { StatePart } from './smartstate.classes.statepart';
export interface IActionDef<TStateType, TActionPayloadType> {
(stateArg: StatePart<any, TStateType>, actionPayload: TActionPayloadType): Promise<TStateType>;
}
/** /**
* an actionmodifier for the state * an actionmodifier for the state
*/ */
export class StateAction<StatePayload> { export class StateAction<TStateType, TActionPayloadType> {
constructor(public actionDef: (stateArg: StatePayload) => StatePayload) {} constructor(public statePartRef: StatePart<any, any>, public actionDef: IActionDef<TStateType, TActionPayloadType>) {}
public trigger(payload: TActionPayloadType) {
this.statePartRef.dispatchAction(this, payload);
}
} }

View File

@ -3,21 +3,21 @@ import * as plugins from './smartstate.plugins';
import { Observable, Subject } from 'rxjs'; import { Observable, Subject } from 'rxjs';
import { startWith, takeUntil, map } from 'rxjs/operators'; import { startWith, takeUntil, map } from 'rxjs/operators';
import { StateAction } from './smartstate.classes.stateaction'; import { StateAction, IActionDef } from './smartstate.classes.stateaction';
export class StatePart<StatePartNameType, PayloadType> { export class StatePart<TStatePartName, TStatePayload> {
name: StatePartNameType; public name: TStatePartName;
state = new Subject<PayloadType>(); public state = new Subject<TStatePayload>();
stateStore: PayloadType; public stateStore: TStatePayload;
constructor(nameArg: StatePartNameType) { constructor(nameArg: TStatePartName) {
this.name = nameArg; this.name = nameArg;
} }
/** /**
* gets the state from the state store * gets the state from the state store
*/ */
getState(): PayloadType { public getState(): TStatePayload {
return this.stateStore; return this.stateStore;
} }
@ -25,7 +25,7 @@ export class StatePart<StatePartNameType, PayloadType> {
* sets the stateStore to the new state * sets the stateStore to the new state
* @param newStateArg * @param newStateArg
*/ */
setState(newStateArg: PayloadType) { public setState(newStateArg: TStatePayload) {
this.stateStore = newStateArg; this.stateStore = newStateArg;
this.notifyChange(); this.notifyChange();
} }
@ -33,31 +33,62 @@ export class StatePart<StatePartNameType, PayloadType> {
/** /**
* notifies of a change on the state * notifies of a change on the state
*/ */
notifyChange() { public notifyChange() {
this.state.next(this.stateStore); this.state.next(this.stateStore);
} }
/** /**
* selects a state or a substate * selects a state or a substate
*/ */
select<T = PayloadType>(selectorFn?: (state: PayloadType) => T): Observable<T> { public select<T = TStatePayload>(selectorFn?: (state: TStatePayload) => T): Observable<T> {
if (!selectorFn) { if (!selectorFn) {
selectorFn = (state: PayloadType) => <T>(<any>state); selectorFn = (state: TStatePayload) => <T>(<any>state);
} }
const mapped = this.state.pipe( const mapped = this.state.pipe(
startWith(this.getState()), startWith(this.getState()),
map(selectorFn) map((stateArg) => {
try {
return selectorFn(stateArg);
} catch (e) {
// Nothing here
}
})
); );
return mapped; return mapped;
} }
/**
* creates an action capable of modifying the state
*/
public createAction<TActionPayload>(
actionDef: IActionDef<TStatePayload, TActionPayload>
): StateAction<TStatePayload, TActionPayload> {
return new StateAction(this, actionDef);
}
/** /**
* dispatches an action on the statepart level * dispatches an action on the statepart level
*/ */
async dispatch(stateAction: StateAction<PayloadType>) { public async dispatchAction<T>(stateAction: StateAction<TStatePayload, T>, actionPayload: T) {
const newState = stateAction.actionDef(this.getState()); const newState = await stateAction.actionDef(this, actionPayload);
this.setState(newState); this.setState(newState);
} }
/**
* waits until a certain part of the state becomes available
* @param selectorFn
*/
public async waitUntilPresent<T = TStatePayload>(selectorFn?: (state: TStatePayload) => T): Promise<T> {
const done = plugins.smartpromise.defer<T>();
const selectedObservable = this.select(selectorFn);
const subscription = selectedObservable.subscribe(value => {
if (value) {
subscription.unsubscribe();
done.resolve(value);
}
});
return await done.promise;
}
} }

View File

@ -5,3 +5,9 @@ const rxjsPart = {
}; };
export { rxjsPart }; export { rxjsPart };
import * as smartpromise from '@pushrocks/smartpromise';
export {
smartpromise
};