Skip to content

Commit 6a077b3

Browse files
Merge pull request cerebral#41 from cerebral/stateComputed
State computed
2 parents 8f149a0 + 551c764 commit 6a077b3

File tree

14 files changed

+252
-175
lines changed

14 files changed

+252
-175
lines changed

packages/node_modules/action-chain/src/ActionBase.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ export class ActionBase<Effects> {
113113
executionContextWithPath
114114
)
115115

116-
this.actionChain.emit('operator:start', {
116+
this.actionChain.emitAsync('operator:start', {
117117
type,
118118
name,
119119
path,
@@ -122,15 +122,15 @@ export class ActionBase<Effects> {
122122
const result = cb(effects, currentValue)
123123

124124
if (result instanceof Promise) {
125-
this.actionChain.emit('operator:async', {
125+
this.actionChain.emitAsync('operator:async', {
126126
type,
127127
name,
128128
path,
129129
isAsync: true,
130130
...thisExecution,
131131
})
132132
return result.then((promiseResult) => {
133-
this.actionChain.emit('operator:end', {
133+
this.actionChain.emitAsync('operator:end', {
134134
type,
135135
name,
136136
path,
@@ -142,7 +142,7 @@ export class ActionBase<Effects> {
142142
})
143143
}
144144

145-
this.actionChain.emit('operator:end', {
145+
this.actionChain.emitAsync('operator:end', {
146146
type,
147147
name,
148148
path,

packages/node_modules/action-chain/src/ActionChain.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export class ActionChain<Effects> extends EventEmitter<ActionChainEvents> {
7777
const result = target[prop](...args)
7878
if (result instanceof Promise) {
7979
result.then((promisedResult) => {
80-
instance.emit('provider', {
80+
instance.emitAsync('provider', {
8181
...execution,
8282
name: path,
8383
method: prop,
@@ -86,7 +86,7 @@ export class ActionChain<Effects> extends EventEmitter<ActionChainEvents> {
8686
})
8787
})
8888
} else {
89-
instance.emit('provider', {
89+
instance.emitAsync('provider', {
9090
...execution,
9191
name: path,
9292
method: prop,

packages/node_modules/betsy/src/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ export class EventEmitter<T> {
2424
}
2525
}
2626

27+
emitAsync<K extends keyof T>(event: K, msg: T[K]) {
28+
const listeners = this.events.get(event) || []
29+
30+
setTimeout(() => {
31+
for (let i = listeners.length - 1; i >= 0; i--) {
32+
const listener = listeners[i]
33+
34+
listener.cb(msg)
35+
36+
if (listener.once) {
37+
listeners.splice(i, 1)
38+
}
39+
}
40+
})
41+
}
42+
2743
on<K extends keyof T>(event: K, cb: (msg: T[K]) => void) {
2844
this.addListener(event, cb, false)
2945
}

packages/node_modules/overmind-devtools/src/app/mutations.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,11 @@ export function performMutationsByMessageType(state: State, message: Message) {
178178
const path = clientMessage.data.path.split('.')
179179
const key = path.pop()
180180
const target = path.reduce((aggr, pathKey) => aggr[pathKey], appState)
181-
target[key] = clientMessage.data
181+
target[key] = {
182+
cache: clientMessage.data.cache,
183+
limit: clientMessage.data.limit,
184+
updateCount: clientMessage.data.updateCount,
185+
}
182186

183187
state.apps[message.port].computed[clientMessage.data.path] =
184188
clientMessage.data

packages/node_modules/overmind-devtools/src/components/Inspector/index.tsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,25 @@ class ValueComponent extends React.Component<ValueComponentProps> {
100100
}
101101
}
102102

103+
export type RenderPaths = {
104+
[path: string]: (children: React.ReactChildren) => React.ReactNode
105+
}
106+
103107
type InspectorProps = {
104108
value: object
105109
expandedPaths: string[]
106110
small?: boolean
107111
onToggleExpand: (path: string[]) => void
112+
renderPaths?: RenderPaths
108113
}
109114

110115
class Inspector extends React.Component<InspectorProps> {
111-
renderValue(path: string[], value: any) {
116+
renderValue(path: string[], value: any, renderPaths?: RenderPaths) {
117+
const wrapper = renderPaths && renderPaths[path.join('.')]
118+
let node
119+
112120
if (isObject(value)) {
113-
return (
121+
node = (
114122
<ConnectedNested
115123
key={path.join('.')}
116124
startBracket="{"
@@ -123,13 +131,13 @@ class Inspector extends React.Component<InspectorProps> {
123131
>
124132
{() =>
125133
Object.keys(value).map((key) =>
126-
this.renderValue(path.concat(key), value[key])
134+
this.renderValue(path.concat(key), value[key], renderPaths)
127135
)
128136
}
129137
</ConnectedNested>
130138
)
131139
} else if (isArray(value)) {
132-
return (
140+
node = (
133141
<ConnectedNested
134142
key={path.join('.')}
135143
startBracket="["
@@ -142,19 +150,21 @@ class Inspector extends React.Component<InspectorProps> {
142150
>
143151
{() =>
144152
value.map((_, index) =>
145-
this.renderValue(path.concat(index), value[index])
153+
this.renderValue(path.concat(index), value[index], renderPaths)
146154
)
147155
}
148156
</ConnectedNested>
149157
)
158+
} else {
159+
node = <ValueComponent key={path.join('.')} path={path} value={value} />
150160
}
151161

152-
return <ValueComponent key={path.join('.')} path={path} value={value} />
162+
return wrapper ? wrapper(node) : node
153163
}
154164
render() {
155165
return (
156166
<Wrapper small={this.props.small}>
157-
{this.renderValue([], this.props.value)}
167+
{this.renderValue([], this.props.value, this.props.renderPaths)}
158168
</Wrapper>
159169
)
160170
}

packages/node_modules/overmind-devtools/src/components/State/elements.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,28 @@ export const Wrapper = styled.div`
66
box-sizing: border-box;
77
overflow-y: scroll;
88
`
9+
10+
export const Label = styled.div`
11+
display: flex;
12+
`
13+
14+
export const LabelWrapper = styled.div`
15+
display: flex;
16+
align-items: center;
17+
`
18+
19+
export const ComputedLabel = styled.div`
20+
margin-right: 5px;
21+
background-color: ${({ theme }) => theme.color.primary};
22+
padding: ${({ theme }) => `0 ${theme.padding.smallerer}`};
23+
border-radius: ${({ theme }) => theme.borderRadius.normal};
24+
color: ${({ theme }) => theme.color.white};
25+
`
26+
27+
export const DerivedLabel = styled.div`
28+
margin-right: 5px;
29+
background-color: ${({ theme }) => theme.color.secondary};
30+
padding: ${({ theme }) => `0 ${theme.padding.smallerer}`};
31+
border-radius: ${({ theme }) => theme.borderRadius.normal};
32+
color: ${({ theme }) => theme.color.white};
33+
`

packages/node_modules/overmind-devtools/src/components/State/index.tsx

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,71 @@
11
import * as React from 'react'
22
import { connect, Connect } from '../../app'
3-
import { Wrapper } from './elements'
4-
import Inspector from '../Inspector'
3+
import {
4+
Wrapper,
5+
Label,
6+
LabelWrapper,
7+
ComputedLabel,
8+
DerivedLabel,
9+
} from './elements'
10+
import Inspector, { RenderPaths } from '../Inspector'
11+
import Text from '../common/Text'
12+
13+
const DerivedWrapper = ({ children }) => (
14+
<Label>
15+
<LabelWrapper>
16+
<DerivedLabel>
17+
<Text variant="hint" mono>
18+
derived
19+
</Text>
20+
</DerivedLabel>
21+
</LabelWrapper>
22+
<div>{children}</div>
23+
</Label>
24+
)
25+
26+
const ComputedWrapper = ({ children }) => (
27+
<Label>
28+
<LabelWrapper>
29+
<ComputedLabel>
30+
{' '}
31+
<Text variant="hint" mono>
32+
computed
33+
</Text>
34+
</ComputedLabel>
35+
</LabelWrapper>
36+
<div>{children}</div>
37+
</Label>
38+
)
539

640
const State: React.SFC<Connect> = ({ app }) => (
741
<Wrapper>
842
<Inspector
9-
value={app.state.apps[app.state.currentPort].state}
43+
value={app.state.currentApp.state}
1044
expandedPaths={app.state.expandedStatePaths}
1145
onToggleExpand={app.actions.toggleExpandState}
46+
renderPaths={
47+
Object.assign(
48+
{},
49+
Object.keys(app.state.currentApp.derived).reduce(
50+
(aggr, key) =>
51+
Object.assign(aggr, {
52+
[key]: (children) => (
53+
<DerivedWrapper key={key}>{children}</DerivedWrapper>
54+
),
55+
}),
56+
{}
57+
),
58+
Object.keys(app.state.currentApp.computed).reduce(
59+
(aggr, key) =>
60+
Object.assign(aggr, {
61+
[key]: (children) => (
62+
<ComputedWrapper key={key}>{children}</ComputedWrapper>
63+
),
64+
}),
65+
{}
66+
)
67+
) as RenderPaths
68+
}
1269
/>
1370
</Wrapper>
1471
)

packages/node_modules/overmind/src/Action.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export default class Action<
6868
this.proxyStateTree.startMutationTracking()
6969
cb(effects.state, value)
7070
const mutations = this.proxyStateTree.clearMutationTracking()
71-
this.getActionChain().emit('mutations', {
71+
this.getActionChain().emitAsync('mutations', {
7272
mutations,
7373
...effects.__execution,
7474
})

packages/node_modules/overmind/src/computed.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { EventEmitter } from 'betsy'
22
import ProxyStateTree from 'proxy-state-tree'
3-
import { Events } from './'
3+
import { Events, EventType } from './'
44

55
type ComputedOptions = {
66
cacheLimit?: number
@@ -60,7 +60,7 @@ export class Computed {
6060
cache.proxyStateTreeListener = proxyStateTree.addMutationListener(
6161
cache.paths,
6262
(flushId) => {
63-
eventHub.emit('computed:dirty', {
63+
eventHub.emitAsync(EventType.COMPUTED_DIRTY, {
6464
path,
6565
flushId,
6666
})
@@ -75,14 +75,15 @@ export class Computed {
7575
proxyStateTree.addTrackingPath(path)
7676
}
7777

78-
eventHub.emit('computed', {
78+
eventHub.emitAsync(EventType.COMPUTED, {
7979
path,
80-
paths: Array.from(cache.paths),
8180
updateCount: cache.updateCount,
82-
value: cache.value,
8381
limit: this.cacheLimit,
84-
cacheKeysCount: this.cacheKeys.length,
85-
cacheKeyIndex: this.cacheKeys.indexOf(config),
82+
cache: Array.from(this.cache.values()).map((cache) => ({
83+
value: cache.value,
84+
updateCount: cache.updateCount,
85+
paths: Array.from(cache.paths),
86+
})),
8687
})
8788

8889
return cache.value

packages/node_modules/overmind/src/derived.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { EventEmitter } from 'betsy'
22
import ProxyStateTree from 'proxy-state-tree'
3-
import { Events } from './'
3+
import { Events, EventType } from './'
44

55
class Derived {
66
isDirty: boolean
@@ -33,15 +33,15 @@ class Derived {
3333
this.proxyStateTreeListener = proxyStateTree.addMutationListener(
3434
this.paths,
3535
(flushId) => {
36-
eventHub.emit('derived:dirty', {
36+
eventHub.emitAsync(EventType.DERIVED_DIRTY, {
3737
path,
3838
flushId,
3939
})
4040
this.isDirty = true
4141
}
4242
)
4343
}
44-
eventHub.emit('derived', {
44+
eventHub.emitAsync(EventType.DERIVED, {
4545
path,
4646
paths: Array.from(this.paths),
4747
updateCount: this.updateCount,

0 commit comments

Comments
 (0)