Skip to content

Commit

Permalink
fix(overmind): allow class instances to add derived
Browse files Browse the repository at this point in the history
  • Loading branch information
christianalfoni committed Aug 25, 2020
1 parent f80e493 commit 3336da0
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 29 deletions.
19 changes: 19 additions & 0 deletions packages/node_modules/overmind/src/derived.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,4 +338,23 @@ describe('Derived', () => {

expect(runCount).toBe(2)
})
test('should be able to add derived to class instances', () => {
class SomeClass {
foo = derived((state: SomeClass) => state.bar + '!')
bar = 'foo'
}
type State = {
class: SomeClass
}
const state: State = {
class: new SomeClass()
}
const config = {
state,
}

const app = new Overmind(config)

expect(app.state.class.foo).toEqual('foo!')
})
})
34 changes: 24 additions & 10 deletions packages/node_modules/overmind/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
import {
EXECUTION,
IS_OPERATOR,
IS_PROXY_BOUND_FUNCTION,
IS_TEST,
MODE_DEFAULT,
MODE_SSR,
Expand All @@ -72,7 +73,7 @@ export { SERIALIZE, rehydrate } from './rehydrate'

export { Statemachine, statemachine } from './statemachine'

export const derived = <S extends IState, R extends IState, O>(cb: (state: S, rootState: R) => O): O => {
export const derived = <S extends object, R extends object, O>(cb: (state: S, rootState: R) => O): O => {
cb[IS_DERIVED_CONSTRUCTOR] = true
return cb as any
}
Expand Down Expand Up @@ -393,24 +394,37 @@ export class Overmind<ThisConfig extends IConfiguration>
{
devmode,
delimiter: this.delimiter,
onFunction: (tree, path, func) => {
onSetFunction: (proxy, tree, path, target, prop, func) => {
if (func[IS_DERIVED_CONSTRUCTOR]) {
return new Derived(func) as any
}

func = func.bind(proxy)
func[IS_PROXY_BOUND_FUNCTION] = true
return func
},
onGetFunction: (proxy, tree, path, target, prop) => {
let func = target[prop]

if (func[IS_DERIVED]) {
return { func, value: func(eventHub, tree, proxyStateTree, path.split(this.delimiter)) }
return func(eventHub, tree, proxyStateTree, path.split(this.delimiter))
}

if (func[IS_DERIVED_CONSTRUCTOR]) {
const derived = new Derived(func) as any
target[prop] = derived

return {
func: derived,
value: derived(eventHub, tree, proxyStateTree, path.split(this.delimiter))
}
return derived(eventHub, tree, proxyStateTree, path.split(this.delimiter))
}

return {
func,
value: func
if (func[IS_PROXY_BOUND_FUNCTION]) {
return func
}

func = func.bind(proxy)
func[IS_PROXY_BOUND_FUNCTION] = true
target[prop] = func
return func
},
onGetter: devmode
? (path, value) => {
Expand Down
1 change: 1 addition & 0 deletions packages/node_modules/overmind/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const IS_TEST = process.env.NODE_ENV === 'test'
export const IS_OPERATOR = Symbol('operator')
export const ORIGINAL_ACTIONS = Symbol('origina_actions')
export const EXECUTION = Symbol('execution')
export const IS_PROXY_BOUND_FUNCTION = Symbol('is_proxy_bound_function')

export const MODE_DEFAULT = Symbol('MODE_DEFAULT')
export const MODE_TEST = Symbol('MODE_TEST')
Expand Down
29 changes: 13 additions & 16 deletions packages/node_modules/proxy-state-tree/src/Proxyfier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,21 +258,17 @@ export class Proxifier {
const nestedPath = proxifier.concat(path, prop)
const currentTree = trackingTree || proxifier.tree

if (typeof targetValue === 'function' && isClass(target)) {
return (...args) => targetValue.call(proxy, ...args)
} else if (typeof targetValue === 'function') {
if (proxifier.tree.master.options.onFunction) {
const { func, value } = proxifier.tree.master.options.onFunction(
if (typeof targetValue === 'function') {
if (proxifier.tree.master.options.onGetFunction) {
return proxifier.tree.master.options.onGetFunction(
proxy,
trackingTree || proxifier.tree,
nestedPath,
targetValue
target,
prop
)

target[prop] = func

return value
}
return targetValue.call(target, proxifier.tree, nestedPath)
return isClass(target) ? (...args) => targetValue.call(proxy, ...args) : targetValue.call(target, proxifier.tree, nestedPath)
} else {
currentTree.trackPathListeners.forEach((cb) => cb(nestedPath))
trackingTree && trackingTree.proxifier.trackPath(nestedPath)
Expand Down Expand Up @@ -301,17 +297,18 @@ export class Proxifier {
const mutationTree = proxifier.getMutationTree()
const existingValue = target[prop]

if (typeof value === 'function' && proxifier.tree.master.options.onFunction) {
const result = proxifier.tree.master.options.onFunction(
if (typeof value === 'function' && proxifier.tree.master.options.onSetFunction) {
value = proxifier.tree.master.options.onSetFunction(
proxy,
proxifier.getTrackingTree() || proxifier.tree,
nestedPath,
target,
prop,
value
)

value = result.func
}

const hasChangedValue = value !== target[prop]
const hasChangedValue = existingValue !== value
const result = Reflect.set(target, prop, value)

mutationTree.addMutation(
Expand Down
4 changes: 2 additions & 2 deletions packages/node_modules/proxy-state-tree/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -755,8 +755,8 @@ describe('FUNCTIONS', () => {
},
}
const tree = new ProxyStateTree(state, {
onFunction: (proxyStateTree, path, func) =>
({ func, value: func('foo', proxyStateTree, path)}),
onGetFunction: (proxy, proxyStateTree, path, target, prop) =>
target[prop]('foo', proxyStateTree, path),
})

const accessTree = tree.getTrackStateTree().track(() => {})
Expand Down
3 changes: 2 additions & 1 deletion packages/node_modules/proxy-state-tree/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ export interface ITrackStateTree<T extends object> {
export interface IOptions {
delimiter?: string
devmode?: boolean
onFunction?: (...args: any[]) => { func: Function, value: any }
onSetFunction?: (...args: any[]) => any
onGetFunction?: (...args: any[]) => any
onGetter?: Function
}

Expand Down

0 comments on commit 3336da0

Please sign in to comment.