Skip to content

Commit f174d1a

Browse files
feat(overmind): send pending and error state of effects, also send flushes correctly
1 parent ed746bb commit f174d1a

File tree

4 files changed

+149
-79
lines changed

4 files changed

+149
-79
lines changed

packages/node_modules/overmind/src/index.ts

Lines changed: 81 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
Options,
1717
ResolveActions,
1818
ResolveState,
19+
Execution,
1920
} from './internalTypes'
2021
import { proxifyEffects } from './proxyfyEffects'
2122
import {
@@ -108,10 +109,6 @@ export class Overmind<Config extends Configuration> implements Configuration {
108109
this.proxyStateTree = proxyStateTree
109110
this.eventHub = eventHub
110111

111-
/*
112-
The action factory function
113-
*/
114-
115112
if (!IS_PRODUCTION && typeof window !== 'undefined') {
116113
let warning = 'OVERMIND: You are running in DEVELOPMENT mode.'
117114
if (options.logProxies !== true) {
@@ -139,32 +136,50 @@ export class Overmind<Config extends Configuration> implements Configuration {
139136
console.warn(warning)
140137
}
141138

142-
eventHub.on(EventType.OPERATOR_ASYNC, (data) => {
143-
const flushData = proxyStateTree.flush(true)
144-
if (this.devtools && flushData.mutations.length) {
145-
this.devtools.send({
146-
type: 'flush',
147-
data: {
148-
...data,
149-
...flushData,
150-
mutations: makeStringifySafeMutations(flushData.mutations),
151-
},
152-
})
153-
}
154-
})
155-
eventHub.on(EventType.ACTION_END, (data) => {
156-
const flushData = proxyStateTree.flush()
157-
if (this.devtools && flushData.mutations.length) {
158-
this.devtools.send({
159-
type: 'flush',
160-
data: {
161-
...data,
162-
...flushData,
163-
mutations: makeStringifySafeMutations(flushData.mutations),
164-
},
165-
})
139+
if (IS_PRODUCTION) {
140+
eventHub.on(EventType.OPERATOR_ASYNC, () => {
141+
proxyStateTree.mutationTree.flush()
142+
})
143+
eventHub.on(EventType.ACTION_END, () => {
144+
proxyStateTree.mutationTree.flush()
145+
})
146+
147+
let nextTick
148+
const flushTree = () => {
149+
proxyStateTree.mutationTree.flush(true)
166150
}
167-
})
151+
152+
this.proxyStateTree.onMutation(() => {
153+
nextTick && clearTimeout(nextTick)
154+
nextTick = setTimeout(flushTree, 0)
155+
})
156+
} else {
157+
eventHub.on(EventType.OPERATOR_ASYNC, (execution) => {
158+
const flushData = execution.flush()
159+
if (this.devtools && flushData) {
160+
this.devtools.send({
161+
type: 'flush',
162+
data: {
163+
...execution,
164+
...flushData,
165+
},
166+
})
167+
}
168+
})
169+
eventHub.on(EventType.ACTION_END, (execution) => {
170+
const flushData = execution.flush()
171+
172+
if (this.devtools && flushData) {
173+
this.devtools.send({
174+
type: 'flush',
175+
data: {
176+
...execution,
177+
...flushData,
178+
},
179+
})
180+
}
181+
})
182+
}
168183

169184
/*
170185
Expose the created actions
@@ -181,21 +196,18 @@ export class Overmind<Config extends Configuration> implements Configuration {
181196
} else {
182197
this.initialized = Promise.resolve(null)
183198
}
184-
185-
if (IS_PRODUCTION) {
186-
let nextTick
187-
const flushTree = () => {
188-
proxyStateTree.flush(true)
189-
}
190-
191-
this.proxyStateTree.onMutation(() => {
192-
nextTick && clearTimeout(nextTick)
193-
nextTick = setTimeout(flushTree, 0)
194-
})
195-
}
196199
}
197200
private createExecution(name, action) {
198-
return {
201+
if (IS_PRODUCTION) {
202+
return {
203+
getMutationTree: () => {
204+
return this.proxyStateTree.mutationTree
205+
},
206+
} as Execution
207+
}
208+
209+
const mutationTrees: any[] = []
210+
const execution = {
199211
actionId: this.actionReferences.indexOf(action),
200212
executionId: this.nextExecutionId++,
201213
actionName: name,
@@ -204,7 +216,19 @@ export class Overmind<Config extends Configuration> implements Configuration {
204216
emit: this.eventHub.emit.bind(this.eventHub),
205217
send: this.devtools ? this.devtools.send.bind(this.devtools) : () => {},
206218
trackEffects: this.trackEffects.bind(this, this.effects),
219+
flush: () => {
220+
return this.proxyStateTree.flush(mutationTrees)
221+
},
222+
getMutationTree: () => {
223+
const mutationTree = this.proxyStateTree.getMutationTree()
224+
225+
mutationTrees.push(mutationTree)
226+
227+
return mutationTree
228+
},
207229
}
230+
231+
return execution
208232
}
209233
private createContext(value, execution, tree) {
210234
return Object.assign(
@@ -250,15 +274,15 @@ export class Overmind<Config extends Configuration> implements Configuration {
250274
value,
251275
state: this.proxyStateTree.state,
252276
execution,
253-
proxyStateTree: this.proxyStateTree,
254277
},
255278
this.trackEffects(this.effects, execution)
256279
),
257280
(err, finalContext) => {
258-
this.eventHub.emit(EventType.ACTION_END, {
259-
...finalContext.execution,
260-
operatorId: finalContext.execution.operatorId - 1,
261-
})
281+
finalContext &&
282+
this.eventHub.emit(EventType.ACTION_END, {
283+
...finalContext.execution,
284+
operatorId: finalContext.execution.operatorId - 1,
285+
})
262286
if (err) reject(err)
263287
else resolve(finalContext.value)
264288
}
@@ -267,7 +291,7 @@ export class Overmind<Config extends Configuration> implements Configuration {
267291
this.createContext(
268292
value,
269293
execution,
270-
this.proxyStateTree.getMutationTree()
294+
execution.getMutationTree()
271295
)
272296
)
273297
})
@@ -280,16 +304,18 @@ export class Overmind<Config extends Configuration> implements Configuration {
280304
this.eventHub.emit(EventType.ACTION_START, execution)
281305
this.eventHub.emit(EventType.OPERATOR_START, execution)
282306

283-
const mutationTree = this.proxyStateTree.getMutationTree()
307+
const mutationTree = execution.getMutationTree()
284308

285309
mutationTree.onMutation((mutation) => {
286310
this.eventHub.emit(EventType.MUTATIONS, {
287311
...execution,
288312
mutations: makeStringifySafeMutations([mutation]),
289313
})
314+
290315
setTimeout(() => {
291-
const flushData = this.proxyStateTree.flush(true)
292-
if (this.devtools && flushData.mutations.length) {
316+
const flushData = mutationTree.flush(true)
317+
318+
if (this.devtools && flushData) {
293319
this.devtools.send({
294320
type: 'flush',
295321
data: {
@@ -316,16 +342,6 @@ export class Overmind<Config extends Configuration> implements Configuration {
316342
})
317343
this.eventHub.emit(EventType.ACTION_END, execution)
318344

319-
const flushData = this.proxyStateTree.flush()
320-
if (this.devtools && flushData.mutations.length) {
321-
this.devtools.send({
322-
type: 'flush',
323-
data: {
324-
...execution,
325-
...flushData,
326-
},
327-
})
328-
}
329345
return Promise.resolve(result)
330346
}
331347
}
@@ -336,7 +352,7 @@ export class Overmind<Config extends Configuration> implements Configuration {
336352
}
337353

338354
return proxifyEffects(this.effects, (effect) =>
339-
this.eventHub.emitAsync(EventType.EFFECT, { ...execution, ...effect })
355+
this.eventHub.emit(EventType.EFFECT, { ...execution, ...effect })
340356
)
341357
}
342358
private initializeDevtools(host, eventHub, proxyStateTree) {
@@ -775,16 +791,16 @@ export function action<Input, Config extends Configuration = TheConfig>(
775791
else {
776792
startDebugOperator('action', operation, context)
777793

778-
const mutationTree = context.proxyStateTree.getMutationTree()
794+
const mutationTree = context.execution.getMutationTree()
779795
if (!IS_PRODUCTION) {
780796
mutationTree.onMutation((mutation) => {
781797
context.execution.emit(EventType.MUTATIONS, {
782798
...context.execution,
783799
mutations: makeStringifySafeMutations([mutation]),
784800
})
785801
setTimeout(() => {
786-
const flushData = context.proxyStateTree.flush(true)
787-
if (flushData.mutations.length) {
802+
const flushData = mutationTree.flush(true)
803+
if (flushData) {
788804
context.execution.send({
789805
type: 'flush',
790806
data: {

packages/node_modules/overmind/src/internalTypes.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { IMutation, ProxyStateTree } from 'proxy-state-tree'
1+
import { IMutation, IMutationTree } from 'proxy-state-tree'
22
import { Configuration, TAction, TOperator, TStateObject } from './types'
33

44
export type SubType<Base, Condition> = Pick<
@@ -36,7 +36,12 @@ export type Execution = {
3636
actionName: string
3737
operatorId: number
3838
path: string[]
39-
emit: (event: EventType, value: any) => void
39+
emit(event: EventType, value: any): void
40+
flush(): {
41+
mutations: IMutation[]
42+
flushId: number
43+
}
44+
getMutationTree(): IMutationTree<any>
4045
}
4146

4247
export interface Events {
@@ -70,7 +75,15 @@ export interface Events {
7075
path: string
7176
flushId: number
7277
}
73-
[EventType.EFFECT]: any
78+
[EventType.EFFECT]: Execution & {
79+
result: any
80+
name: string
81+
method: string
82+
args: any[]
83+
isPending: boolean
84+
error: string
85+
effectId: number
86+
}
7487
[EventType.REACTION_ADD]: {
7588
path: string
7689
statePath: string

packages/node_modules/overmind/src/pipe.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ function createMockAction(pipe) {
2626
emit: () => {},
2727
send: () => {},
2828
trackEffects: () => {},
29-
},
30-
proxyStateTree: {
3129
getMutationTree() {
3230
return {
3331
onMutation() {},

packages/node_modules/overmind/src/proxyfyEffects.ts

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,70 @@ function isObject(value) {
55
}
66

77
let hasWarnedConstructor = false
8+
let currentEffectId = 0
89

910
function wrapEffect(target, prop, path, cb) {
1011
const func = function(...args) {
11-
const result = target[prop].apply(this, args)
12+
const effectId = currentEffectId++
13+
let result
14+
try {
15+
result = target[prop].apply(this, args)
16+
} catch (error) {
17+
// eslint-disable-next-line standard/no-callback-literal
18+
cb({
19+
effectId,
20+
name: path,
21+
method: prop,
22+
args,
23+
isPending: false,
24+
error: error.message,
25+
})
26+
return
27+
}
28+
1229
if (result instanceof Promise) {
13-
result.then((promisedResult) => {
14-
// eslint-disable-next-line standard/no-callback-literal
15-
cb({
16-
name: path,
17-
method: prop,
18-
args,
19-
result: promisedResult,
20-
})
30+
// eslint-disable-next-line standard/no-callback-literal
31+
cb({
32+
effectId,
33+
name: path,
34+
method: prop,
35+
args,
36+
isPending: true,
37+
error: false,
2138
})
39+
result
40+
.then((promisedResult) => {
41+
// eslint-disable-next-line standard/no-callback-literal
42+
cb({
43+
effectId,
44+
name: path,
45+
method: prop,
46+
args,
47+
result: promisedResult,
48+
isPending: false,
49+
error: false,
50+
})
51+
})
52+
.catch((error) => {
53+
cb({
54+
effectId,
55+
name: path,
56+
method: prop,
57+
args,
58+
isPending: false,
59+
error: error.message,
60+
})
61+
})
2262
} else {
2363
// eslint-disable-next-line standard/no-callback-literal
2464
cb({
65+
effectId,
2566
name: path,
2667
method: prop,
2768
args,
2869
result,
70+
isPending: false,
71+
error: false,
2972
})
3073
}
3174
return result

0 commit comments

Comments
 (0)