djinn-state
Advanced tools
Comparing version
@@ -20,3 +20,3 @@ import { DjinnService } from './DjinnService'; | ||
*/ | ||
register: <T extends DjinnService>(service: new () => T, scoped?: boolean) => void; | ||
register: <T extends DjinnService<{}>>(service: new () => T, scoped?: boolean) => void; | ||
/** | ||
@@ -33,3 +33,3 @@ * Returns a copy of the registered services. | ||
*/ | ||
getService: <T extends DjinnService>(service: new () => T) => T; | ||
getService: <T extends DjinnService<{}>>(service: new () => T) => T; | ||
/** | ||
@@ -39,3 +39,3 @@ * Remove a registered service | ||
*/ | ||
remove: <T extends DjinnService>(service: new () => T) => void; | ||
remove: <T extends DjinnService<{}>>(service: new () => T) => void; | ||
/** | ||
@@ -42,0 +42,0 @@ * Instantiates the singletons after all services were registered |
@@ -1,5 +0,9 @@ | ||
export declare class DjinnService { | ||
state: IState; | ||
import Immutable from 'seamless-immutable'; | ||
export declare class DjinnService<TState = {}> { | ||
private __initialized; | ||
private __state; | ||
private readonly __listeners; | ||
patch: (newState: IState) => void; | ||
getState(): Immutable.ImmutableObject<TState>; | ||
state: TState | Immutable.ImmutableObject<TState>; | ||
protected patch: (newState: Partial<TState>) => void; | ||
subscribe: (listener: ListenerFunction) => () => void; | ||
@@ -10,5 +14,2 @@ initService(): void; | ||
} | ||
interface IState { | ||
[k: string]: any; | ||
} | ||
interface IStateUpdate { | ||
@@ -15,0 +16,0 @@ [k: string]: { |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var seamless_immutable_1 = __importDefault(require("seamless-immutable")); | ||
var DjinnService = /** @class */ (function () { | ||
function DjinnService() { | ||
var _this = this; | ||
this.state = {}; | ||
this.__initialized = false; | ||
this.__state = seamless_immutable_1.default({}); | ||
this.__listeners = []; | ||
this.patch = function (newState) { | ||
var update = {}; | ||
_this.state = _this.state || {}; | ||
var keys = Object.keys(newState); | ||
@@ -17,6 +21,6 @@ var length = keys.length; | ||
current: newState[key], | ||
previous: _this.state[key], | ||
previous: _this.__state[key], | ||
}; | ||
_this.state[key] = newState[key]; | ||
} | ||
_this.__state = _this.__state.merge(newState); | ||
_this.__callListeners(update); | ||
@@ -33,2 +37,15 @@ }; | ||
} | ||
DjinnService.prototype.getState = function () { | ||
return this.__state; | ||
}; | ||
Object.defineProperty(DjinnService.prototype, "state", { | ||
set: function (state) { | ||
if (!this.__initialized) { | ||
this.__initialized = true; | ||
this.__state = seamless_immutable_1.default(state); | ||
} | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
DjinnService.prototype.initService = function () { }; | ||
@@ -35,0 +52,0 @@ DjinnService.prototype.__callListeners = function (update) { |
{ | ||
"name": "djinn-state", | ||
"version": "1.3.1", | ||
"version": "2.0.0", | ||
"description": "Powerful yet simple state machine", | ||
@@ -35,2 +35,3 @@ "main": "dist/index.js", | ||
"@types/node": "^10.12.18", | ||
"@types/seamless-immutable": "^7.1.9", | ||
"codacy-coverage": "^3.3.0", | ||
@@ -45,3 +46,6 @@ "jest": "^23.6.0", | ||
"definition": "dist/index.d.ts" | ||
}, | ||
"dependencies": { | ||
"seamless-immutable": "^7.1.4" | ||
} | ||
} |
@@ -17,2 +17,4 @@ # Djinn-state | ||
More information read the [docs](https://djinn-state.js.org). | ||
## Features | ||
@@ -67,3 +69,3 @@ | ||
get(url) { | ||
const token = this.authService.state.token; | ||
const token = this.authService.getState().token; | ||
const headers = { | ||
@@ -94,5 +96,5 @@ 'Authorize': `Bearer ${token}`, | ||
console.log(authService.state); // { token: 'someNewTokenHere' } | ||
console.log(authService.getState()); // { token: 'someNewTokenHere' } | ||
unsubscribe(); // Don't listen to changes anymore | ||
``` |
import { DjinnService } from '../DjinnService'; | ||
class MyService extends DjinnService { | ||
interface IMyServiceState { | ||
value: string; | ||
array: any[]; | ||
} | ||
class MyService extends DjinnService<IMyServiceState> { | ||
state = { | ||
value: '', | ||
array: [{ prop: 'a' }], | ||
}; | ||
doSomething(value: string) { | ||
this.patch({value}); | ||
this.patch({ value }); | ||
} | ||
manipulateWithoutPatching(): IMyServiceState { | ||
const newState = this.getState().asMutable({ deep: true }); | ||
newState.array.push({ prop: 'b' }); | ||
return newState; | ||
} | ||
} | ||
@@ -20,3 +33,3 @@ | ||
expect(service.state.value).toBe(value); | ||
expect(service.getState().value).toBe(value); | ||
}); | ||
@@ -34,3 +47,3 @@ | ||
expect(listener).toBeCalledTimes(1); | ||
expect(listener).toBeCalledWith({value: {current: value, previous: ''}}); | ||
expect(listener).toBeCalledWith({ value: { current: value, previous: '' } }); | ||
}); | ||
@@ -58,2 +71,10 @@ | ||
}); | ||
it('should allow to manipulate data inside state without propagate it', () => { | ||
const service = new MyService(); | ||
const newState = service.manipulateWithoutPatching(); | ||
expect(newState.array).toHaveLength(2); | ||
expect(service.getState().array).toHaveLength(1); | ||
}); | ||
}); |
@@ -1,9 +0,22 @@ | ||
export class DjinnService { | ||
state: IState = {}; | ||
import Immutable from 'seamless-immutable'; | ||
export class DjinnService<TState = {}> { | ||
private __initialized = false; | ||
private __state = Immutable({}) as Immutable.ImmutableObject<TState>; | ||
private readonly __listeners: ListenerFunction[] = []; | ||
patch = (newState: IState) => { | ||
public getState(): Immutable.ImmutableObject<TState> { | ||
return this.__state; | ||
} | ||
public set state(state: TState | Immutable.ImmutableObject<TState>) { | ||
if (!this.__initialized) { | ||
this.__initialized = true; | ||
this.__state = Immutable(state) as Immutable.ImmutableObject<TState>; | ||
} | ||
} | ||
protected patch = (newState: Partial<TState>) => { | ||
const update: IStateUpdate = {}; | ||
this.state = this.state || {}; | ||
const keys = Object.keys(newState); | ||
@@ -16,13 +29,13 @@ const length = keys.length; | ||
update[key] = { | ||
current: newState[key], | ||
previous: this.state[key], | ||
current: (newState as any)[key], | ||
previous: (this.__state as any)[key], | ||
}; | ||
this.state[key] = newState[key]; | ||
} | ||
this.__state = this.__state.merge(newState as any) as Immutable.ImmutableObject<TState>; | ||
this.__callListeners(update); | ||
}; | ||
subscribe = (listener: ListenerFunction): () => void => { | ||
public subscribe = (listener: ListenerFunction): () => void => { | ||
if (typeof listener !== 'function') { | ||
@@ -37,3 +50,3 @@ console.error(`Tried listen to "${(<any>this).constructor.name}" state updates with invalid listener callback.`); | ||
initService() {} | ||
public initService() { } | ||
@@ -55,6 +68,2 @@ private __callListeners(update: IStateUpdate) { | ||
interface IState { | ||
[k: string]: any | ||
} | ||
interface IStateUpdate { | ||
@@ -61,0 +70,0 @@ [k: string]: { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
26931
8.98%566
7.81%98
2.08%1
Infinity%8
14.29%+ Added
+ Added