Skip to content

Commit 58294d5

Browse files
feat(overmind): improve serializing to devtools approach and allow any class instance in state
1 parent 0270e2b commit 58294d5

File tree

10 files changed

+58
-124
lines changed

10 files changed

+58
-124
lines changed

packages/node_modules/overmind/src/Devtools.ts

Lines changed: 14 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import isPlainObject from 'is-plain-obj'
2-
import { IS_PROXY, StateModel } from 'proxy-state-tree'
3-
41
export type Message = {
52
type: string
63
data?: object
@@ -12,54 +9,6 @@ export type DevtoolsMessage = {
129
data: any
1310
}
1411

15-
export function safeTree(tree) {
16-
return Object.keys(tree).reduce((aggr, key) => {
17-
if (typeof tree[key] === 'function') {
18-
aggr[key] = '[Function]'
19-
} else if (isPlainObject(tree[key])) {
20-
aggr[key] = safeTree(tree[key])
21-
} else if (
22-
typeof tree[key] === 'object' &&
23-
!Array.isArray(tree[key]) &&
24-
tree[key] !== null &&
25-
!(tree[key] instanceof StateModel)
26-
) {
27-
aggr[key] = `[${tree[key].constructor.name || 'NOT SERIALIZABLE'}]`
28-
} else {
29-
aggr[key] = tree[key]
30-
}
31-
32-
return aggr
33-
}, {})
34-
}
35-
36-
export function safeValue(value) {
37-
if (typeof value === 'function') {
38-
return '[Function]'
39-
}
40-
41-
if (
42-
typeof value === 'object' &&
43-
!Array.isArray(value) &&
44-
value !== null &&
45-
!isPlainObject(value)
46-
) {
47-
return `[${value.constructor.name || 'NOT SERIALIZABLE'}]`
48-
}
49-
50-
return value && !value[IS_PROXY] && isPlainObject(value)
51-
? Object.keys(value).reduce((aggr, key) => {
52-
aggr[key] = safeValue(value[key])
53-
54-
return aggr
55-
}, {})
56-
: value
57-
}
58-
59-
export function safeValues(values) {
60-
return values.map(safeValue)
61-
}
62-
6312
export class Devtools {
6413
private buffer: string[] = []
6514
private ws: WebSocket
@@ -116,7 +65,20 @@ export class Devtools {
11665
)
11766
}
11867
send(message: Message) {
119-
const stringifiedMessage = JSON.stringify(message)
68+
const stringifiedMessage = JSON.stringify(message, (_, value) => {
69+
if (typeof value === 'function') {
70+
return '[Function]'
71+
}
72+
if (typeof value === 'object' && value !== null && !Array.isArray(value) && value.constructor && value.constructor.name !== 'Object') {
73+
try {
74+
JSON.stringify(value)
75+
} catch {
76+
return `[${value.constructor.name || 'NOT SERIALIZABLE'}]`
77+
}
78+
}
79+
80+
return value
81+
})
12082
this.buffer.push(stringifiedMessage)
12183
this.sendBuffer()
12284
}

packages/node_modules/overmind/src/index.ts

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
VALUE,
1414
} from 'proxy-state-tree'
1515

16-
import { Devtools, DevtoolsMessage, safeTree, safeValue, safeValues } from './Devtools'
16+
import { Devtools, DevtoolsMessage } from './Devtools'
1717
import {
1818
DefaultMode,
1919
EventType,
@@ -58,15 +58,11 @@ import {
5858
getActionPaths,
5959
getFunctionName,
6060
isPromise,
61-
makeStringifySafeMutations,
6261
mergeState,
6362
processState,
6463
rehydrateState
6564
} from './utils'
6665

67-
export { StateModel } from 'proxy-state-tree'
68-
69-
7066
export * from './types'
7167

7268
export { createOperator, createMutationOperator }
@@ -399,7 +395,7 @@ export class Overmind<ThisConfig extends IConfiguration>
399395
? (path, value) => {
400396
this.eventHub.emitAsync(EventType.GETTER, {
401397
path,
402-
value: safeValue(value),
398+
value
403399
})
404400
}
405401
: undefined,
@@ -530,7 +526,7 @@ export class Overmind<ThisConfig extends IConfiguration>
530526
const execution = this.createExecution(name, action, boundExecution)
531527
this.eventHub.emit(EventType.ACTION_START, {
532528
...execution,
533-
value: safeValue(value),
529+
value
534530
})
535531

536532
if (action[IS_OPERATOR]) {
@@ -577,7 +573,7 @@ export class Overmind<ThisConfig extends IConfiguration>
577573
}
578574
this.eventHub.emit(EventType.ACTION_START, {
579575
...execution,
580-
value: safeValue(value),
576+
value
581577
})
582578
this.eventHub.emit(EventType.OPERATOR_START, execution)
583579

@@ -586,7 +582,7 @@ export class Overmind<ThisConfig extends IConfiguration>
586582
mutationTree.onMutation((mutation) => {
587583
this.eventHub.emit(EventType.MUTATIONS, {
588584
...execution,
589-
mutations: makeStringifySafeMutations([mutation]),
585+
mutations: [mutation],
590586
})
591587
})
592588

@@ -659,7 +655,7 @@ export class Overmind<ThisConfig extends IConfiguration>
659655
data: {
660656
...execution,
661657
...flushData,
662-
mutations: makeStringifySafeMutations(flushData.mutations),
658+
mutations: flushData.mutations,
663659
},
664660
})
665661
}
@@ -697,7 +693,7 @@ export class Overmind<ThisConfig extends IConfiguration>
697693
this.eventHub.emit(EventType.EFFECT, {
698694
...execution,
699695
...effect,
700-
args: safeValues(effect.args),
696+
args: effect.args,
701697
isPending: true,
702698
error: false,
703699
})
@@ -708,7 +704,7 @@ export class Overmind<ThisConfig extends IConfiguration>
708704
this.eventHub.emit(EventType.EFFECT, {
709705
...execution,
710706
...effect,
711-
args: safeValues(effect.args),
707+
args: effect.args,
712708
isPending: false,
713709
error: error.message,
714710
})
@@ -720,7 +716,7 @@ export class Overmind<ThisConfig extends IConfiguration>
720716
this.eventHub.emit(EventType.EFFECT, {
721717
...execution,
722718
...effect,
723-
args: safeValues(effect.args),
719+
args: effect.args,
724720
isPending: true,
725721
error: false,
726722
})
@@ -731,8 +727,8 @@ export class Overmind<ThisConfig extends IConfiguration>
731727
this.eventHub.emit(EventType.EFFECT, {
732728
...execution,
733729
...effect,
734-
args: safeValues(effect.args),
735-
result: safeValue(promisedResult),
730+
args: effect.args,
731+
result: promisedResult,
736732
isPending: false,
737733
error: false,
738734
})
@@ -743,7 +739,7 @@ export class Overmind<ThisConfig extends IConfiguration>
743739
this.eventHub.emit(EventType.EFFECT, {
744740
...execution,
745741
...effect,
746-
args: safeValues(effect.args),
742+
args: effect.args,
747743
isPending: false,
748744
error: error && error.message,
749745
})
@@ -755,8 +751,8 @@ export class Overmind<ThisConfig extends IConfiguration>
755751
this.eventHub.emit(EventType.EFFECT, {
756752
...execution,
757753
...effect,
758-
args: safeValues(effect.args),
759-
result: safeValue(result),
754+
args: effect.args,
755+
result: result,
760756
isPending: false,
761757
error: false,
762758
})
@@ -827,7 +823,7 @@ export class Overmind<ThisConfig extends IConfiguration>
827823
devtools.send({
828824
type: 'init',
829825
data: {
830-
state: safeTree(this.proxyStateTree.state[VALUE]),
826+
state: this.proxyStateTree.state[VALUE],
831827
actions: getActionPaths(actions),
832828
},
833829
})

packages/node_modules/overmind/src/operator.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
import { safeValue } from './Devtools'
21
import { EventType, Execution } from './internalTypes'
32
import { IConfiguration, IContext, IOperator } from './types'
43
import {
54
IS_OPERATOR,
65
MODE_TEST,
76
ORIGINAL_ACTIONS,
87
createActionsProxy,
9-
makeStringifySafeMutations,
108
} from './utils'
119

1210
export function operatorStarted(type, arg, context) {
@@ -55,7 +53,7 @@ export function operatorStopped(
5553
context.execution.isRunning = false
5654
context.execution.emit(EventType.OPERATOR_END, {
5755
...context.execution,
58-
result: safeValue(promiseValue),
56+
result: promiseValue,
5957
isAsync: true,
6058
...evaluatedDetails,
6159
})
@@ -67,7 +65,7 @@ export function operatorStopped(
6765
context.execution.isRunning = false
6866
context.execution.emit(EventType.OPERATOR_END, {
6967
...context.execution,
70-
result: safeValue(value),
68+
result: value,
7169
isAsync: false,
7270
...evaluatedDetails,
7371
})
@@ -262,7 +260,7 @@ export function createMutationOperator<ThisConfig extends IConfiguration>(
262260
mutationTree.onMutation((mutation) => {
263261
context.execution.emit(EventType.MUTATIONS, {
264262
...context.execution,
265-
mutations: makeStringifySafeMutations([mutation]),
263+
mutations: [mutation],
266264
})
267265
})
268266
}
@@ -323,7 +321,7 @@ export function createMutationOperator<ThisConfig extends IConfiguration>(
323321
data: {
324322
...context.execution,
325323
...flushData,
326-
mutations: makeStringifySafeMutations(flushData.mutations),
324+
mutations: flushData.mutations,
327325
},
328326
})
329327
}

packages/node_modules/overmind/src/utils.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import isPlainObject from 'is-plain-obj'
2-
import { IMutation } from 'proxy-state-tree'
32

43
import { Derived } from './derived'
5-
import { safeValues } from './Devtools'
64
import { IState } from './types'
75

86
export const IS_TEST = process.env.NODE_ENV === 'test'
@@ -66,13 +64,6 @@ export function getFunctionName(func: Function) {
6664
return func.name || (func as any).displayName || ''
6765
}
6866

69-
export const makeStringifySafeMutations = (mutations: IMutation[]) => {
70-
return mutations.map((mutation) => ({
71-
...mutation,
72-
args: safeValues(mutation.args),
73-
}))
74-
}
75-
7667
export function deepCopy(obj) {
7768
if (isPlainObject(obj)) {
7869
return Object.keys(obj).reduce((aggr: any, key) => {

packages/node_modules/proxy-state-tree/src/Proxyfier.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ export const PATH = Symbol('PATH')
77
export const VALUE = Symbol('VALUE')
88
export const PROXY_TREE = Symbol('PROXY_TREE')
99

10-
export class StateModel {}
11-
1210
const arrayMutations = new Set([
1311
'push',
1412
'shift',
@@ -23,6 +21,8 @@ const arrayMutations = new Set([
2321
const getValue = (proxyOrValue) =>
2422
proxyOrValue && proxyOrValue[IS_PROXY] ? proxyOrValue[VALUE] : proxyOrValue
2523

24+
const isClass = (value) => typeof value === 'object' && value !== null && !Array.isArray(value) && value.constructor.name !== 'Object'
25+
2626
const getArrayMutationRevert = (method: string, target: any[], args: any[]) => {
2727
switch (method) {
2828
case 'push': {
@@ -297,7 +297,7 @@ export class Proxifier {
297297
const nestedPath = proxifier.concat(path, prop)
298298
const currentTree = trackingTree || proxifier.tree
299299

300-
if (typeof targetValue === 'function' && target instanceof StateModel) {
300+
if (typeof targetValue === 'function' && isClass(target)) {
301301
return (...args) => targetValue.call(proxy, ...args)
302302
} else if (typeof targetValue === 'function') {
303303
return proxifier.tree.master.options.dynamicWrapper
@@ -408,10 +408,10 @@ export class Proxifier {
408408
return this.proxify(value[VALUE], path)
409409
} else if (value[IS_PROXY]) {
410410
return value
411-
} else if (isPlainObject(value) || value instanceof StateModel) {
412-
return this.createObjectProxy(value, path)
413411
} else if (Array.isArray(value)) {
414412
return this.createArrayProxy(value, path)
413+
} else if (isPlainObject(value) || isClass(value)) {
414+
return this.createObjectProxy(value, path)
415415
}
416416
}
417417

0 commit comments

Comments
 (0)