Skip to content

Commit f10818e

Browse files
feat(overmind): bring back effects proxy
1 parent fee814b commit f10818e

File tree

3 files changed

+95
-18
lines changed

3 files changed

+95
-18
lines changed

packages/demos/react-typescript-todomvc/src/app/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as state from './state'
77

88
const config = {
99
actions,
10+
effects,
1011
state,
1112
}
1213

packages/node_modules/overmind/src/index.ts

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
TContext,
2020
TOperator,
2121
} from './types'
22+
import { proxifyEffects } from './proxyfyEffects'
2223

2324
export * from './types'
2425

@@ -272,25 +273,13 @@ export class Overmind<Config extends Configuration> implements BaseApp {
272273
}
273274
}
274275
private trackEffects(effects = {}, execution) {
275-
const that = this
276-
277-
return effects
278-
/*
279-
return new Proxy(effects, {
280-
get(target, prop) {
281-
if (typeof target[prop] === 'function') {
282-
return (...args) => {
283-
const result = target[prop](...args)
284-
return that.trackPromise(result, execution)
285-
}
286-
} else if (isPlainObject(target[prop])) {
287-
return that.trackEffects(target[prop], execution)
288-
}
276+
if (IS_PRODUCTION) {
277+
return effects
278+
}
289279

290-
return target[prop]
291-
},
292-
})
293-
*/
280+
return proxifyEffects(this.effects, (effect) =>
281+
this.eventHub.emitAsync(EventType.EFFECT, { ...execution, ...effect })
282+
)
294283
}
295284
private initializeDevtools(host, eventHub, proxyStateTree) {
296285
const devtools = new Devtools(
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
export const doNotProxy = Symbol('doNotProxy')
2+
3+
function isObject(value) {
4+
return typeof value === 'object' && !Array.isArray(value) && value !== null
5+
}
6+
7+
let hasWarnedConstructor = false
8+
9+
function createProxyGetHandler(
10+
path: string,
11+
cb: (effect) => void
12+
): ProxyHandler<any>['get'] {
13+
return (target, prop) => {
14+
if (typeof target[prop] === 'function') {
15+
const func = function(...args) {
16+
const result = target[prop].apply(this, args)
17+
if (result instanceof Promise) {
18+
result.then((promisedResult) => {
19+
// eslint-disable-next-line standard/no-callback-literal
20+
cb({
21+
name: path,
22+
method: prop,
23+
args,
24+
result: promisedResult,
25+
})
26+
})
27+
} else {
28+
// eslint-disable-next-line standard/no-callback-literal
29+
cb({
30+
name: path,
31+
method: prop,
32+
args,
33+
result,
34+
})
35+
}
36+
return result
37+
}
38+
39+
return new Proxy(func, {
40+
construct(_, args) {
41+
// eslint-disable-next-line
42+
cb({
43+
name: path,
44+
method: prop,
45+
args,
46+
result: `[${prop.toString()}]`,
47+
})
48+
49+
if (!hasWarnedConstructor) {
50+
console.warn(
51+
`EFFECTS - It is highly recommended to create a custom effect, exposing a method that deals with the instantiation of "${path}.${prop.toString()}". It improves readability and debugability of your app`
52+
)
53+
hasWarnedConstructor = true
54+
}
55+
56+
return new target[prop](...args)
57+
},
58+
})
59+
}
60+
if (isObject(target[prop])) {
61+
return new Proxy(target[prop], {
62+
get: createProxyGetHandler(path + '.' + prop.toString(), cb),
63+
})
64+
}
65+
return target[prop]
66+
}
67+
}
68+
69+
export function proxifyEffects<Effects>(
70+
effects: Effects,
71+
cb: (effect) => void
72+
): Effects {
73+
return Object.keys(effects).reduce(
74+
(currentEffects, key) => {
75+
const effect = effects[key]
76+
if (isObject(effect)) {
77+
currentEffects[key] = new Proxy(effect, {
78+
get: createProxyGetHandler(key, cb),
79+
})
80+
} else {
81+
currentEffects[key] = effect
82+
}
83+
return currentEffects
84+
},
85+
{} as Effects
86+
)
87+
}

0 commit comments

Comments
 (0)