reactive-di
Advanced tools
Comparing version 2.0.0 to 2.0.1
@@ -25,7 +25,9 @@ 'use strict'; | ||
Atom, | ||
Derivable, | ||
Derivable | ||
} from '../interfaces/atom'*/ | ||
/*:: import type { | ||
CreateWidget, | ||
SrcComponent, | ||
CreateComponentReactor | ||
} from '../interfaces'*/ | ||
} from '../interfaces/component'*/ | ||
/*:: type ReactComponent<Props, State> = React$Component<*, Props, State>*/ | ||
@@ -111,3 +113,3 @@ /*:: type CreateReactWidget<Props, State> = CreateWidget<Props, State, Class<ReactComponent<Props, State>>>*/ | ||
target.state = this.state; | ||
return target.render(); | ||
return target.render(this.props, this.state); | ||
}; | ||
@@ -122,6 +124,6 @@ | ||
return function (Target /*: Class<SrcComponent<Props, State>>*/, atom /*: Derivable<[State]>*/, CreateComponentReactor /*: CreateComponentReactor*/) { | ||
return createReactWidget(ReactComponent, findDOMElement, adapter, Target, atom, CreateComponentReactor); | ||
return function (Target /*: Class<SrcComponent<Props, State>>*/, atom /*: Derivable<[State]>*/, createComponentReactor /*: CreateComponentReactor*/) { | ||
return createReactWidget(ReactComponent, findDOMElement, adapter, Target, atom, createComponentReactor); | ||
}; | ||
} | ||
//# sourceMappingURL=createReactWidgetFactory.js.map |
'use strict'; | ||
exports.__esModule = true; | ||
exports.promiseToObservable = promiseToObservable; | ||
var _derivable = require('derivable'); | ||
var _promiseToObservable = require('../utils/promiseToObservable'); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _promiseToObservable2 = _interopRequireDefault(_promiseToObservable); | ||
/*:: import type {Atom, Adapter} from '../interfaces'*/ | ||
var _derivable = require('derivable'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function noop() {} | ||
function promiseToObservable /*:: <V, E>*/(promise /*: Promise<V>*/) /*: Observable<V, E>*/ { | ||
if (typeof promise.then !== 'function') { | ||
throw new TypeError('promise argument is not a Promise'); | ||
} | ||
function promiseToObservableSubscriber(observer /*: SubscriptionObserver<V, E>*/) /*: () => void*/ { | ||
var isSubscribed /*: boolean*/ = true; | ||
function promiseToObservableUnsubscribe() /*: void*/ { | ||
// todo: memory leak | ||
isSubscribed = false; | ||
if (typeof promise.cancel === 'function') { | ||
promise.cancel(); | ||
} | ||
} | ||
function success(data /*: V*/) /*: void*/ { | ||
if (isSubscribed) { | ||
observer.complete(data); | ||
} | ||
} | ||
function error(e /*: E*/) /*: void*/ { | ||
if (isSubscribed) { | ||
observer.error(e); | ||
} | ||
} | ||
promise.then(success).catch(error); | ||
return promiseToObservableUnsubscribe; | ||
} | ||
return new Observable(promiseToObservableSubscriber); | ||
} | ||
var AtomObserver = function () { | ||
function AtomObserver /*:: <V>*/(setValue /*: (val: V) => void*/, stop /*: () => void*/) { | ||
_classCallCheck(this, AtomObserver); | ||
this._setValue = setValue; | ||
this._stop = stop; | ||
} | ||
AtomObserver.prototype.next = function next(v /*: V*/) { | ||
this._setValue(v); | ||
}; | ||
AtomObserver.prototype.complete = function complete(v /*: ?V*/) { | ||
if (v) { | ||
this._setValue(v); | ||
} | ||
this._stop(); | ||
}; | ||
AtomObserver.prototype.error = function error(err /*: Error*/) { | ||
// @todo: handle errors in derivable | ||
throw err; | ||
}; | ||
return AtomObserver; | ||
}(); | ||
function atomFromObservable /*:: <V>*/(v /*: V*/, raw /*: Promise<V> | Observable<V, Error>*/) /*: Atom<V>*/ { | ||
var va /*: Atom<V>*/ = (0, _derivable.atom)(v); | ||
if (raw) { | ||
var observable /*: Observable<V, Error>*/ = typeof (raw /*: any*/).then === 'function' ? promiseToObservable(((raw /*: any*/) /*: Promise<V>*/)) : ((raw /*: any*/) /*: Observable<V, Error>*/); | ||
var setValue = function setValue(val /*: V*/) { | ||
va.set(val); | ||
}; | ||
var stop = function stop() {}; | ||
var sub = observable.subscribe(new AtomObserver(setValue, stop)); | ||
} | ||
return va; | ||
} | ||
/*:: import type {Atom, Adapter} from '../interfaces/atom'*/ | ||
exports.default = ({ | ||
atom: _derivable.atom, | ||
isAtom: _derivable.isAtom, | ||
atomFromObservable: atomFromObservable, | ||
transact: _derivable.transact, | ||
struct: _derivable.struct | ||
} /*: Adapter*/); | ||
//# sourceMappingURL=derivableAtomAdapter.js.map |
@@ -7,6 +7,6 @@ 'use strict'; | ||
exports.deps = deps; | ||
exports.klass = klass; | ||
exports.factory = factory; | ||
exports.theme = theme; | ||
exports.source = source; | ||
exports.updaters = updaters; | ||
exports.service = service; | ||
@@ -16,3 +16,3 @@ | ||
/*:: import type {DepFn, DepDict, ArgDep, DepAlias, RegisterDepItem, InitData, Initializer} from './interfaces'*/ | ||
/*:: import type {DepFn, Key, DepDict, ArgDep, DepAlias, RegisterDepItem} from './interfaces/deps'*/ | ||
var paramTypesKey /*: Symbol*/ = exports.paramTypesKey = Symbol.for('design:paramtypes'); | ||
@@ -27,7 +27,9 @@ var metaKey /*: Symbol*/ = exports.metaKey = Symbol.for('rdi:meta'); | ||
this.isTheme = false; | ||
this.isService = false; | ||
this.writable = false; | ||
this.initializer = null; | ||
this.isComponent = false; | ||
this.isUpdater = false; | ||
this.localDeps = null; | ||
this.isFactory = false; | ||
this.updaters = null; | ||
}; | ||
@@ -67,7 +69,2 @@ | ||
function klass /*:: <V, R: Class<V>>*/(target /*: R*/) /*: R*/ { | ||
getMeta(target); | ||
return target; | ||
} | ||
function factory /*:: <V: Function>*/(target /*: V*/) /*: V*/ { | ||
@@ -85,3 +82,3 @@ getMeta(target).isFactory = true; | ||
key: string, | ||
init?: ?Initializer<R>, | ||
init?: ?Key, | ||
construct?: boolean | ||
@@ -92,3 +89,3 @@ }*/) /*: (target: V) => V*/ { | ||
meta.key = rec.key; | ||
meta.isService = true; | ||
meta.writable = true; | ||
meta.initializer = rec.init || null; | ||
@@ -100,6 +97,18 @@ meta.construct = rec.construct || false; | ||
function updaters /*:: <V: Function>*/() /*: (target: V) => V*/ { | ||
for (var _len2 = arguments.length, updaters = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
updaters[_key2] = arguments[_key2]; | ||
} | ||
return function (target /*: V*/) { | ||
var meta = getMeta(target); | ||
meta.updaters = updaters; | ||
return target; | ||
}; | ||
} | ||
function service /*:: <V: Function>*/(target /*: V*/) /*: V*/ { | ||
getMeta(target).isService = true; | ||
getMeta(target).writable = true; | ||
return target; | ||
} | ||
//# sourceMappingURL=annotations.js.map |
@@ -5,3 +5,4 @@ 'use strict'; | ||
exports.default = CreateComponentReactorFactory; | ||
/*:: import type {CreateComponentReactor, StyleSheet, RawStyleSheet, Derivable} from './interfaces'*/ | ||
/*:: import type {CreateComponentReactor, StyleSheet, RawStyleSheet} from './interfaces/component'*/ | ||
/*:: import type {Derivable} from './interfaces/atom'*/ | ||
@@ -8,0 +9,0 @@ |
119
dist/Di.js
@@ -23,2 +23,6 @@ 'use strict'; | ||
var _UpdaterStatus = require('./UpdaterStatus'); | ||
var _UpdaterStatus2 = _interopRequireDefault(_UpdaterStatus); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -28,9 +32,6 @@ | ||
/*:: import type { | ||
DepFn, | ||
Key, | ||
Initializer, RegisterDepItem, DepAlias, ArgDep, InitData, | ||
Adapter, Atom, Derivable, DerivableArg, DerivableDict, CreateWidget, | ||
StyleSheet, CreateStyleSheet, RawStyleSheet | ||
} from './interfaces'*/ | ||
/*:: import type {IUpdater, IUpdaterStatus} from './interfaces/updater'*/ | ||
/*:: import type {DepFn, Key, RegisterDepItem, DepAlias, ArgDep} from './interfaces/deps'*/ | ||
/*:: import type {CreateWidget, StyleSheet, CreateStyleSheet, RawStyleSheet} from './interfaces/component'*/ | ||
/*:: import type {Adapter, Atom, Derivable, DerivableArg, DerivableDict} from './interfaces/atom'*/ | ||
@@ -50,4 +51,6 @@ | ||
var defaultMeta /*: RdiMeta<*>*/ = new _annotations.RdiMeta(); | ||
function metaFromTarget(target /*: Function*/) /*: Meta*/ { | ||
return [target, target[_annotations.paramTypesKey] || [], target[_annotations.metaKey]]; | ||
return [target, target[_annotations.paramTypesKey] || [], target[_annotations.metaKey] || defaultMeta]; | ||
} | ||
@@ -57,2 +60,11 @@ | ||
function mapToStatus(upd /*: IUpdater*/) /*: Derivable<IUpdaterStatus>*/ { | ||
return upd.status; | ||
} | ||
function mergeStatuses(statuses /*: IUpdaterStatus[]*/) /*: IUpdaterStatus*/ { | ||
return new _UpdaterStatus2.default().merge(statuses); | ||
} | ||
var Di = function () { | ||
@@ -74,3 +86,3 @@ function Di() { | ||
this._paths = []; | ||
this._path = []; | ||
@@ -165,3 +177,3 @@ this.__createSheet = function (theme /*: any*/) { | ||
Di.prototype._debugStr = function _debugStr(sub /*: ?mixed*/) { | ||
return (0, _debugName2.default)(sub) + ' [' + this._paths.join('.') + ']'; | ||
return (0, _debugName2.default)(sub) + ' [' + this._path.join('.') + ']'; | ||
}; | ||
@@ -173,2 +185,16 @@ | ||
Di.prototype.getMeta = function getMeta(key /*: Key*/) { | ||
var rec /*: ?Meta*/ = this._metaMap.get(key); | ||
if (!rec) { | ||
if (typeof key === 'function') { | ||
rec = metaFromTarget(key); | ||
} else { | ||
throw new Error('Can\'t read annotation from ' + this._debugStr(key)); | ||
} | ||
this._metaMap.set(key, rec); | ||
} | ||
return rec; | ||
}; | ||
Di.prototype.val = function val(key /*: Key*/, _themes /*: ?Derivable<RawStyleSheet>[]*/) { | ||
@@ -181,2 +207,7 @@ var _this2 = this; | ||
} | ||
if (key === this.constructor) { | ||
atom = this._adapter.atom((this /*: any*/)); | ||
this._cache.set(key, atom); | ||
return atom; | ||
} | ||
var parentDi /*: ?Di*/ = this._scopeMap.get(key); | ||
@@ -187,19 +218,9 @@ if (parentDi) { | ||
var rec /*: ?Meta*/ = this._metaMap.get(key); | ||
if (!rec) { | ||
if (typeof key === 'function') { | ||
rec = metaFromTarget(key); | ||
} else { | ||
throw new Error('Can\'t read annotation from ' + this._debugStr(key)); | ||
} | ||
this._metaMap.set(key, rec); | ||
} | ||
var _rec = rec; | ||
var target = _rec[0]; | ||
var deps = _rec[1]; | ||
var meta = _rec[2]; | ||
var _getMeta = this.getMeta(key); | ||
if (!meta) { | ||
throw new Error('RdiMeta not found: "' + this._debugStr(target) + '"'); | ||
} | ||
var target = _getMeta[0]; | ||
var deps = _getMeta[1]; | ||
var meta = _getMeta[2]; | ||
this._path.push((0, _debugName2.default)(key)); | ||
var adapter /*: Adapter*/ = this._adapter; | ||
@@ -225,2 +246,3 @@ | ||
_this2._path.pop(); | ||
return { | ||
@@ -235,17 +257,2 @@ v: atom | ||
if (meta.initializer) { | ||
var initData = this.val(meta.initializer); | ||
var _initData$get = initData.get(); | ||
var data = _initData$get[0]; | ||
var obs = _initData$get[1]; | ||
atom = adapter.atomFromObservable(data, obs); | ||
this._cache.set(key, atom); | ||
return atom; | ||
} | ||
if (meta.isComponent) { | ||
@@ -262,2 +269,3 @@ atom = this._componentCache.get(key); | ||
this._path.pop(); | ||
return atom; | ||
@@ -269,4 +277,4 @@ } | ||
if (meta.isFactory) { | ||
if (meta.isService) { | ||
atom = adapter.atom(this._createFactory(target, depsAtom)); | ||
if (meta.writable) { | ||
atom = adapter.atom((this._createFactory(target, depsAtom) /*: any*/)); | ||
} else { | ||
@@ -278,3 +286,3 @@ atom = depsAtom.derive(function (deps /*: mixed[]*/) { | ||
} else { | ||
if (meta.isService) { | ||
if (meta.writable) { | ||
atom = adapter.atom(this._createObject(target, depsAtom)); | ||
@@ -288,3 +296,3 @@ } else { | ||
if (meta.isTheme) { | ||
if (meta.isService) { | ||
if (meta.writable) { | ||
throw new Error('Them can\'t be an @service annotated: ' + this._debugStr(key)); | ||
@@ -298,7 +306,28 @@ } | ||
if (meta.updaters) { | ||
atom = (this._updaterStatus(meta.updaters) /*: any*/); | ||
} | ||
this._cache.set(key, atom); | ||
// Place after cache.set to avoid curcular deps | ||
// initializer can use model, resolved above. | ||
if (meta.initializer) { | ||
this.val(meta.initializer).get(); | ||
} | ||
this._path.pop(); | ||
return atom; | ||
}; | ||
Di.prototype._updaterStatus = function _updaterStatus(updaterKeys /*: Key[]*/) { | ||
var statuses /*: Derivable<IUpdaterStatus>[]*/ = []; | ||
for (var i = 0; i < updaterKeys.length; i++) { | ||
// @todo: remove .get() after https://github.com/ds300/derivablejs/issues/45 | ||
statuses.push(this.val(updaterKeys[i]).get().status); | ||
} | ||
return this._adapter.struct(statuses).derive(mergeStatuses); | ||
}; | ||
Di.prototype._createObject = function _createObject(target /*: Class<V>*/, depsAtom /*: Derivable<mixed[]>*/) { | ||
@@ -305,0 +334,0 @@ var value /*: V*/ = (0, _fastCall.fastCreateObject)(target, depsAtom.get()); |
'use strict'; | ||
exports.__esModule = true; | ||
exports.createReactWidgetFactory = exports.derivableAtomAdapter = exports.BaseModel = exports.Di = undefined; | ||
exports.createReactWidgetFactory = exports.derivableAtomAdapter = exports.BaseModel = exports.UpdaterStatus = exports.Updater = exports.Di = undefined; | ||
@@ -22,5 +22,15 @@ var _Di = require('./Di'); | ||
var _Updater = require('./Updater'); | ||
var _Updater2 = _interopRequireDefault(_Updater); | ||
var _UpdaterStatus = require('./UpdaterStatus'); | ||
var _UpdaterStatus2 = _interopRequireDefault(_UpdaterStatus); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
exports.Di = _Di2.default; | ||
exports.Updater = _Updater2.default; | ||
exports.UpdaterStatus = _UpdaterStatus2.default; | ||
exports.BaseModel = _BaseModel2.default; | ||
@@ -27,0 +37,0 @@ exports.derivableAtomAdapter = _derivableAtomAdapter2.default; |
@@ -21,3 +21,3 @@ 'use strict'; | ||
if (func === null || (typeof func === 'undefined' ? 'undefined' : _typeof(func)) !== 'object' && typeof func !== 'function') { | ||
return (typeof func === 'undefined' ? 'undefined' : _typeof(func)) + ' ' + JSON.stringify(func); | ||
return String(func); | ||
} | ||
@@ -24,0 +24,0 @@ |
{ | ||
"name": "reactive-di", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"description": "Reactive dependency injection", | ||
@@ -21,3 +21,3 @@ "publishConfig": { | ||
"clean": "rm -rf $npm_package_config_builddir/dist", | ||
"build": "npm run clean && babel src --source-maps --out-dir $npm_package_config_builddir/dist", | ||
"build": "npm run clean && babel src --ignore=__tests__ --source-maps --out-dir $npm_package_config_builddir/dist", | ||
"build.dev": "babel src --source-maps --out-dir $npm_package_config_builddir/dist --watch", | ||
@@ -24,0 +24,0 @@ "lint": "exit 0 && eslint src", |
@@ -14,10 +14,6 @@ // @flow | ||
source, | ||
deps, | ||
klass | ||
deps | ||
} from '../annotations' | ||
import type { | ||
StyleSheet, | ||
Derivable | ||
} from '../interfaces' | ||
import type {StyleSheet} from '../interfaces/component' | ||
@@ -43,3 +39,2 @@ import {Component} from 'fake-react' | ||
} | ||
klass(ModelA) | ||
source({key: 'ModelA'})(ModelA) | ||
@@ -95,3 +90,2 @@ | ||
} | ||
klass(ModelA) | ||
source({key: 'ModelA'})(ModelA) | ||
@@ -110,3 +104,2 @@ | ||
} | ||
klass(TestComponentTheme) | ||
theme(TestComponentTheme) | ||
@@ -113,0 +106,0 @@ |
@@ -12,8 +12,4 @@ // @flow | ||
source, | ||
klass, | ||
factory | ||
} from '../annotations' | ||
import type { | ||
ArgDep, | ||
} from '../interfaces' | ||
@@ -35,3 +31,2 @@ import Di from '../Di' | ||
} | ||
klass(ModelA) | ||
source({key: 'ModelA'})(ModelA) | ||
@@ -46,3 +41,2 @@ | ||
deps(ModelA)(Facet) | ||
klass(Facet) | ||
@@ -57,3 +51,2 @@ it('catch model changes in service throught facet', () => { | ||
service(Service) | ||
klass(Service) | ||
deps(Facet)(Service) | ||
@@ -60,0 +53,0 @@ |
@@ -10,9 +10,5 @@ // @flow | ||
deps, | ||
klass, | ||
source, | ||
factory | ||
} from '../annotations' | ||
import type { | ||
ArgDep, | ||
} from '../interfaces' | ||
@@ -35,3 +31,3 @@ import Di from '../Di' | ||
describe('Di.Base - class with one dependency', () => { | ||
describe('DiBase - class with one dependency', () => { | ||
type ModelARec = { | ||
@@ -48,3 +44,2 @@ val?: string; | ||
} | ||
klass(ModelA) | ||
source({key: 'ModelA'})(ModelA) | ||
@@ -65,3 +60,2 @@ | ||
service(Service) | ||
klass(Service) | ||
deps(ModelA)(Service) | ||
@@ -90,3 +84,2 @@ | ||
service(Service) | ||
klass(Service) | ||
deps(ModelA)(Service) | ||
@@ -93,0 +86,0 @@ |
@@ -11,10 +11,7 @@ // @flow | ||
deps, | ||
source, | ||
klass | ||
source | ||
} from '../annotations' | ||
import type { | ||
InitData | ||
} from '../interfaces' | ||
import Di from '../Di' | ||
import Updater from '../Updater' | ||
import BaseModel from '../BaseModel' | ||
@@ -30,3 +27,2 @@ | ||
} | ||
klass(Dep) | ||
@@ -42,12 +38,11 @@ it('catch sync model changes in service throught facet', () => { | ||
function initA(dep: Dep): InitData<ModelA> { | ||
return [ | ||
function initA(dep: Dep, updater: Updater): void { | ||
updater.set([ | ||
new ModelA({val: dep.val}) | ||
] | ||
]) | ||
} | ||
deps(Dep)(initA) | ||
deps(Dep, Updater)(initA) | ||
factory(initA) | ||
source({key: 'ModelA', init: initA})(ModelA) | ||
klass(ModelA) | ||
@@ -61,3 +56,2 @@ const Service = spy(class { | ||
service(Service) | ||
klass(Service) | ||
deps(ModelA)(Service) | ||
@@ -78,16 +72,15 @@ | ||
} | ||
const pmodelA = Promise.resolve(new ModelA({val: 'from promise'})) | ||
function initA(dep: Dep): InitData<ModelA> { | ||
return [ | ||
let resolve: () => void | ||
const pmodelA = Promise.resolve([new ModelA({val: 'from promise'})]) | ||
const resolved = new Promise(r => {resolve = r}) | ||
function initA(dep: Dep, updater: Updater): void { | ||
updater.set([ | ||
new ModelA({val: dep.val}), | ||
pmodelA | ||
] | ||
() => pmodelA | ||
]) | ||
} | ||
deps(Dep)(initA) | ||
deps(Dep, Updater)(initA) | ||
factory(initA) | ||
source({key: 'ModelA', init: initA})(ModelA) | ||
klass(ModelA) | ||
@@ -101,3 +94,2 @@ const Service = spy(class { | ||
service(Service) | ||
klass(Service) | ||
deps(ModelA)(Service) | ||
@@ -108,2 +100,3 @@ | ||
assert(s.val === 'test') | ||
return pmodelA | ||
@@ -110,0 +103,0 @@ .then(() => { |
@@ -9,8 +9,4 @@ // @flow | ||
source, | ||
deps, | ||
klass | ||
deps | ||
} from '../annotations' | ||
import type { | ||
InitData | ||
} from '../interfaces' | ||
@@ -36,3 +32,2 @@ import Di from '../Di' | ||
source({key: 'modelA'})(ModelA) | ||
klass(ModelA) | ||
@@ -45,3 +40,2 @@ const Service = spy(class { | ||
}) | ||
klass(Service) | ||
deps(ModelA)(Service) | ||
@@ -68,3 +62,2 @@ | ||
source({key: 'modelA', construct: true})(ModelA) | ||
klass(ModelA) | ||
@@ -77,3 +70,2 @@ const Service = spy(class { | ||
}) | ||
klass(Service) | ||
deps(ModelA)(Service) | ||
@@ -100,3 +92,2 @@ | ||
source({key: 'modelA'})(ModelA) | ||
klass(ModelA) | ||
@@ -109,3 +100,2 @@ const Service = spy(class { | ||
}) | ||
klass(Service) | ||
deps(ModelA)(Service) | ||
@@ -136,3 +126,2 @@ | ||
source({key: 'modelA', construct: true})(ModelA) | ||
klass(ModelA) | ||
@@ -145,3 +134,2 @@ const Service = spy(class { | ||
}) | ||
klass(Service) | ||
deps(ModelA)(Service) | ||
@@ -148,0 +136,0 @@ |
@@ -10,8 +10,4 @@ // @flow | ||
service, | ||
deps, | ||
klass | ||
deps | ||
} from '../annotations' | ||
import type { | ||
InitData | ||
} from '../interfaces' | ||
@@ -35,3 +31,2 @@ import Di from '../Di' | ||
source({key: 'ModelA'})(ModelA) | ||
klass(ModelA) | ||
@@ -45,3 +40,2 @@ const Service = spy(class { | ||
service(Service) | ||
klass(Service) | ||
deps(ModelA)(Service) | ||
@@ -65,3 +59,2 @@ | ||
source({key: 'ModelA'})(ModelA) | ||
klass(ModelA) | ||
@@ -74,3 +67,2 @@ const Service = spy(class { | ||
}) | ||
klass(Service) | ||
service(Service) | ||
@@ -99,3 +91,2 @@ deps(ModelA)(Service) | ||
source({key: 'ModelA'})(ModelA) | ||
klass(ModelA) | ||
@@ -108,3 +99,2 @@ const Service = spy(class { | ||
}) | ||
klass(Service) | ||
service(Service) | ||
@@ -111,0 +101,0 @@ deps(ModelA)(Service) |
// @flow | ||
import type { | ||
Adapter, | ||
Atom, | ||
Derivable, | ||
Derivable | ||
} from '../interfaces/atom' | ||
import type { | ||
CreateWidget, | ||
SrcComponent, | ||
CreateComponentReactor | ||
} from '../interfaces' | ||
} from '../interfaces/component' | ||
@@ -85,3 +86,3 @@ import derivableAtomAdapter from './derivableAtomAdapter' | ||
target.state = this.state | ||
return target.render() | ||
return target.render(this.props, this.state) | ||
} | ||
@@ -99,4 +100,4 @@ } | ||
atom: Derivable<[State]>, | ||
CreateComponentReactor: CreateComponentReactor | ||
) => createReactWidget(ReactComponent, findDOMElement, adapter, Target, atom, CreateComponentReactor) | ||
createComponentReactor: CreateComponentReactor | ||
) => createReactWidget(ReactComponent, findDOMElement, adapter, Target, atom, createComponentReactor) | ||
} |
// @flow | ||
import type {Atom, Adapter} from '../interfaces' | ||
import type {Atom, Adapter} from '../interfaces/atom' | ||
import promiseToObservable from '../utils/promiseToObservable' | ||
@@ -12,93 +13,7 @@ import { | ||
function noop() {} | ||
export function promiseToObservable<V, E>( | ||
promise: Promise<V> | ||
): Observable<V, E> { | ||
if (typeof promise.then !== 'function') { | ||
throw new TypeError('promise argument is not a Promise') | ||
} | ||
function promiseToObservableSubscriber(observer: SubscriptionObserver<V, E>): () => void { | ||
let isSubscribed: boolean = true | ||
function promiseToObservableUnsubscribe(): void { | ||
// todo: memory leak | ||
isSubscribed = false | ||
if (typeof promise.cancel === 'function') { | ||
promise.cancel() | ||
} | ||
} | ||
function success(data: V): void { | ||
if (isSubscribed) { | ||
observer.complete(data) | ||
} | ||
} | ||
function error(e: E): void { | ||
if (isSubscribed) { | ||
observer.error(e) | ||
} | ||
} | ||
promise.then(success).catch(error) | ||
return promiseToObservableUnsubscribe | ||
} | ||
return new Observable(promiseToObservableSubscriber) | ||
} | ||
class AtomObserver<V> { | ||
_setValue: (val: V) => void; | ||
_stop: () => void; | ||
constructor( | ||
setValue: (val: V) => void, | ||
stop: () => void | ||
) { | ||
this._setValue = setValue | ||
this._stop = stop | ||
} | ||
next(v: V): void { | ||
this._setValue(v) | ||
} | ||
complete(v?: ?V): void { | ||
if (v) { | ||
this._setValue(v) | ||
} | ||
this._stop() | ||
} | ||
error(err: Error): void { | ||
// @todo: handle errors in derivable | ||
throw err | ||
} | ||
} | ||
function atomFromObservable<V>( | ||
v: V, | ||
raw: Promise<V> | Observable<V, Error> | ||
): Atom<V> { | ||
const va: Atom<V> = atom(v) | ||
if (raw) { | ||
const observable: Observable<V, Error> = typeof (raw: any).then === 'function' | ||
? promiseToObservable(((raw: any): Promise<V>)) | ||
: ((raw: any): Observable<V, Error>) | ||
const setValue = (val: V) => { | ||
va.set(val) | ||
} | ||
const stop = () => {} | ||
const sub = observable.subscribe(new AtomObserver(setValue, stop)) | ||
} | ||
return va | ||
} | ||
export default ({ | ||
atom, | ||
isAtom, | ||
atomFromObservable, | ||
transact, | ||
struct | ||
}: Adapter) |
// @flow | ||
import type {DepFn, DepDict, ArgDep, DepAlias, RegisterDepItem, InitData, Initializer} from './interfaces' | ||
import type {DepFn, Key, DepDict, ArgDep, DepAlias, RegisterDepItem} from './interfaces/deps' | ||
@@ -11,7 +11,10 @@ export const paramTypesKey: Symbol = Symbol.for('design:paramtypes') | ||
isTheme: boolean = false; | ||
isService: boolean = false; | ||
initializer: ?Initializer<V> = null; | ||
writable: boolean = false; | ||
initializer: ?Key = null; | ||
isComponent: boolean = false; | ||
isUpdater: boolean = false; | ||
localDeps: ?RegisterDepItem[] = null; | ||
isFactory: boolean = false; | ||
updaters: ?Key[] = null; | ||
} | ||
@@ -47,7 +50,2 @@ | ||
export function klass<V, R: Class<V>>(target: R): R { | ||
getMeta(target) | ||
return target | ||
} | ||
export function factory<V: Function>(target: V): V { | ||
@@ -65,3 +63,3 @@ getMeta(target).isFactory = true | ||
key: string, | ||
init?: ?Initializer<R>, | ||
init?: ?Key, | ||
construct?: boolean | ||
@@ -72,3 +70,3 @@ }): (target: V) => V { | ||
meta.key = rec.key | ||
meta.isService = true | ||
meta.writable = true | ||
meta.initializer = rec.init || null | ||
@@ -80,5 +78,13 @@ meta.construct = rec.construct || false | ||
export function updaters<V: Function>(...updaters: Key[]): (target: V) => V { | ||
return (target: V) => { | ||
const meta = getMeta(target) | ||
meta.updaters = updaters | ||
return target | ||
} | ||
} | ||
export function service<V: Function>(target: V): V { | ||
getMeta(target).isService = true | ||
getMeta(target).writable = true | ||
return target | ||
} |
// @flow | ||
import type {CreateComponentReactor, StyleSheet, RawStyleSheet, Derivable} from './interfaces' | ||
import type {CreateComponentReactor, StyleSheet, RawStyleSheet} from './interfaces/component' | ||
import type {Derivable} from './interfaces/atom' | ||
@@ -4,0 +5,0 @@ function themesReact(themes: Derivable<RawStyleSheet[]>, unmounted: Derivable<boolean>): void { |
103
src/Di.js
// @flow | ||
import {paramTypesKey, metaKey, RdiMeta} from './annotations' | ||
import type { | ||
DepFn, | ||
Key, | ||
Initializer, RegisterDepItem, DepAlias, ArgDep, InitData, | ||
Adapter, Atom, Derivable, DerivableArg, DerivableDict, CreateWidget, | ||
StyleSheet, CreateStyleSheet, RawStyleSheet | ||
} from './interfaces' | ||
import type {IUpdater, IUpdaterStatus} from './interfaces/updater' | ||
import type {DepFn, Key, RegisterDepItem, DepAlias, ArgDep} from './interfaces/deps' | ||
import type {CreateWidget, StyleSheet, CreateStyleSheet, RawStyleSheet} from './interfaces/component' | ||
import type {Adapter, Atom, Derivable, DerivableArg, DerivableDict} from './interfaces/atom' | ||
import debugName from './utils/debugName' | ||
@@ -15,2 +12,3 @@ import {fastCallMethod, fastCall, fastCreateObject} from './utils/fastCall' | ||
import createThemesReactor from './createThemesReactor' | ||
import UpdaterStatus from './UpdaterStatus' | ||
@@ -29,2 +27,4 @@ function passAny<V>(v: V): V { | ||
const defaultMeta: RdiMeta<*> = new RdiMeta() | ||
function metaFromTarget(target: Function): Meta { | ||
@@ -34,3 +34,3 @@ return [ | ||
target[paramTypesKey] || [], | ||
target[metaKey] | ||
target[metaKey] || defaultMeta | ||
] | ||
@@ -41,2 +41,10 @@ } | ||
function mapToStatus(upd: IUpdater): Derivable<IUpdaterStatus> { | ||
return upd.status | ||
} | ||
function mergeStatuses(statuses: IUpdaterStatus[]): IUpdaterStatus { | ||
return (new UpdaterStatus()).merge(statuses) | ||
} | ||
export default class Di { | ||
@@ -151,6 +159,6 @@ _cache: CacheMap; | ||
_paths: string[] = []; | ||
_path: string[] = []; | ||
_debugStr(sub: ?mixed): string { | ||
return `${debugName(sub)} [${this._paths.join('.')}]` | ||
return `${debugName(sub)} [${this._path.join('.')}]` | ||
} | ||
@@ -162,2 +170,16 @@ | ||
getMeta(key: Key): Meta { | ||
let rec: ?Meta = this._metaMap.get(key) | ||
if (!rec) { | ||
if (typeof key === 'function') { | ||
rec = metaFromTarget(key) | ||
} else { | ||
throw new Error(`Can't read annotation from ${this._debugStr(key)}`) | ||
} | ||
this._metaMap.set(key, rec) | ||
} | ||
return rec | ||
} | ||
val<V>(key: Key, _themes?: ?Derivable<RawStyleSheet>[]): Result<V> { | ||
@@ -168,2 +190,7 @@ let atom: ?Result<V> = this._cache.get(key) | ||
} | ||
if (key === this.constructor) { | ||
atom = this._adapter.atom((this: any)) | ||
this._cache.set(key, atom) | ||
return atom | ||
} | ||
const parentDi: ?Di = this._scopeMap.get(key) | ||
@@ -174,15 +201,4 @@ if (parentDi) { | ||
let rec: ?Meta = this._metaMap.get(key) | ||
if (!rec) { | ||
if (typeof key === 'function') { | ||
rec = metaFromTarget(key) | ||
} else { | ||
throw new Error(`Can't read annotation from ${this._debugStr(key)}`) | ||
} | ||
this._metaMap.set(key, rec) | ||
} | ||
const [target, deps, meta] = rec | ||
if (!meta) { | ||
throw new Error(`RdiMeta not found: "${this._debugStr(target)}"`) | ||
} | ||
const [target, deps, meta] = this.getMeta(key) | ||
this._path.push(debugName(key)) | ||
const adapter: Adapter = this._adapter | ||
@@ -209,2 +225,3 @@ | ||
this._path.pop() | ||
return atom | ||
@@ -214,12 +231,2 @@ } | ||
if (meta.initializer) { | ||
const initData = this.val(meta.initializer) | ||
const [data, obs] = initData.get() | ||
atom = adapter.atomFromObservable(data, obs) | ||
this._cache.set(key, atom) | ||
return atom | ||
} | ||
if (meta.isComponent) { | ||
@@ -242,2 +249,3 @@ atom = this._componentCache.get(key) | ||
this._path.pop() | ||
return atom | ||
@@ -249,4 +257,4 @@ } | ||
if (meta.isFactory) { | ||
if (meta.isService) { | ||
atom = adapter.atom(this._createFactory(target, depsAtom)) | ||
if (meta.writable) { | ||
atom = adapter.atom((this._createFactory(target, depsAtom): any)) | ||
} else { | ||
@@ -256,3 +264,3 @@ atom = depsAtom.derive((deps: mixed[]) => preprocess(fastCall(target, deps))) | ||
} else { | ||
if (meta.isService) { | ||
if (meta.writable) { | ||
atom = adapter.atom(this._createObject(target, depsAtom)) | ||
@@ -264,3 +272,3 @@ } else { | ||
if (meta.isTheme) { | ||
if (meta.isService) { | ||
if (meta.writable) { | ||
throw new Error(`Them can't be an @service annotated: ${this._debugStr(key)}`) | ||
@@ -274,7 +282,28 @@ } | ||
if (meta.updaters) { | ||
atom = (this._updaterStatus(meta.updaters): any) | ||
} | ||
this._cache.set(key, atom) | ||
// Place after cache.set to avoid curcular deps | ||
// initializer can use model, resolved above. | ||
if (meta.initializer) { | ||
this.val(meta.initializer).get() | ||
} | ||
this._path.pop() | ||
return atom | ||
} | ||
_updaterStatus(updaterKeys: Key[]): Derivable<IUpdaterStatus> { | ||
const statuses: Derivable<IUpdaterStatus>[] = [] | ||
for (let i = 0; i < updaterKeys.length; i++) { | ||
// @todo: remove .get() after https://github.com/ds300/derivablejs/issues/45 | ||
statuses.push(this.val(updaterKeys[i]).get().status) | ||
} | ||
return this._adapter.struct(statuses).derive(mergeStatuses) | ||
} | ||
__createSheet: (theme: any) => RawStyleSheet = (theme: any) => { | ||
@@ -281,0 +310,0 @@ if (!theme || typeof theme !== 'object' || !theme.__css) { |
@@ -7,4 +7,11 @@ // @flow | ||
import BaseModel from './BaseModel' | ||
import Updater from './Updater' | ||
import UpdaterStatus from './UpdaterStatus' | ||
export type { | ||
RegisterDepItem, | ||
Key | ||
} from './interfaces/deps' | ||
export type { | ||
SrcComponent, | ||
@@ -15,15 +22,24 @@ StyleSheet, | ||
CreateComponentReactor, | ||
CreateWidget, | ||
CreateWidget | ||
} from './interfaces/component' | ||
export type { | ||
Adapter, | ||
Derivable, | ||
Atom, | ||
Adapter, | ||
LifeCycle, | ||
Key, | ||
Initializer, | ||
InitData | ||
} from './interfaces' | ||
LifeCycle | ||
} from './interfaces/atom' | ||
export type { | ||
KeyValueSyncUpdate, | ||
SyncUpdate, | ||
AsyncUpdate, | ||
AsyncUpdateThunk, | ||
Transaction | ||
} from './interfaces/updater' | ||
export { | ||
Di, | ||
Updater, | ||
UpdaterStatus, | ||
BaseModel, | ||
@@ -30,0 +46,0 @@ derivableAtomAdapter, |
@@ -22,3 +22,3 @@ /* @flow */ | ||
) { | ||
return (typeof func) + ' ' + JSON.stringify(func) | ||
return String(func) | ||
} | ||
@@ -25,0 +25,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
66
0
175891
3002