Skip to content

Commit 97f6a1f

Browse files
Merge pull request cerebral#133 from cerebral/improvements3
Improvements3
2 parents a8a52ef + 37526ba commit 97f6a1f

File tree

12 files changed

+126
-34
lines changed

12 files changed

+126
-34
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from 'react'
22
import { Action } from 'overmind'
3+
import { Todo } from './state'
34

45
type ChangeEvent = React.ChangeEvent<HTMLInputElement>
56

@@ -21,7 +22,6 @@ export const addTodo: Action = ({ state }) => {
2122
state.newTodoTitle = ''
2223
}
2324

24-
export const toggleCompleted: Action<string> = ({ value: todoId, state }) => {
25-
const todo = state.todos.find((todo) => todo.id === todoId)
25+
export const toggleCompleted: Action<Todo> = ({ value: todo }) => {
2626
todo.completed = !todo.completed
2727
}

packages/demos/react-typescript-todomvc/src/components/Todo/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ type Props = {
88
} & Connect
99

1010
const Todo: React.SFC<Props> = ({ todo, app }) => (
11-
<Item onClick={() => app.actions.toggleCompleted(todo.id)}>
11+
<Item onClick={() => app.actions.toggleCompleted(todo)}>
1212
<Completed completed={todo.completed}></Completed> {todo.title}
1313
</Item>
1414
)

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

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ function toJSON(obj) {
88
function createDefaultApp() {
99
const state = {
1010
foo: 'bar',
11+
item: {
12+
isAwesome: true,
13+
},
1114
}
1215
const changeFoo: Action = (context) => {
1316
context.state.foo = 'bar2'
@@ -24,11 +27,15 @@ function createDefaultApp() {
2427
await Promise.resolve()
2528
context.state.foo = 'bar2'
2629
}
30+
const changeValue: Action<{ isAwesome: boolean }> = (context) => {
31+
context.value.isAwesome = !context.value.isAwesome
32+
}
2733
const actions = {
2834
changeFoo,
2935
changeFooWithEffect,
3036
waitAndChangeFoo,
3137
asyncChangeFoo,
38+
changeValue,
3239
}
3340
const effects = {
3441
hello() {
@@ -49,11 +56,7 @@ function createDefaultApp() {
4956
actions: typeof actions
5057
effects: typeof effects
5158
}>
52-
type Action<Value = void, ReturnValue = Value> = TAction<
53-
App,
54-
Value,
55-
ReturnValue
56-
>
59+
type Action<Value = void> = TAction<App, Value>
5760

5861
return new Overmind(config)
5962
}
@@ -296,4 +299,10 @@ describe('Overmind', () => {
296299
expect(result).toEqual(['foo', 'bar'])
297300
})
298301
})
302+
test('should allow mutations on passed values', () => {
303+
expect.assertions(2)
304+
const app = createDefaultApp()
305+
expect(() => app.actions.changeValue(app.state.item)).not.toThrow()
306+
expect(app.state.item.isAwesome).toBe(false)
307+
})
299308
})

packages/node_modules/overmind/src/index.ts

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,7 @@ export interface IApp {}
3131

3232
type App = BaseApp & IApp
3333

34-
export type Action<Value = void, ReturnValue = any> = TAction<
35-
App,
36-
Value,
37-
ReturnValue
38-
>
34+
export type Action<Value = void> = TAction<App, Value>
3935

4036
export type Context<Value> = TContext<App, Value>
4137

@@ -215,7 +211,11 @@ export class Overmind<Config extends Configuration> implements BaseApp {
215211
const scopedTree = this.proxyStateTree.getScopedTree()
216212
scopedTree.startMutationTracking()
217213
const result = action(
218-
this.createContext(value, execution, scopedTree.get())
214+
this.createContext(
215+
scopedTree.scope(value),
216+
execution,
217+
scopedTree.get()
218+
)
219219
)
220220
this.eventHub.emit(EventType.OPERATOR_END, {
221221
...execution,
@@ -559,7 +559,7 @@ function startDebugOperator(type, operationName, execution) {
559559
export function map<Input, Output>(
560560
operation: (input: Context<Input>) => Output
561561
): Operator<Input, Output extends Promise<infer U> ? U : Output> {
562-
return (err, context, next) => {
562+
const instance = (err, context, next) => {
563563
if (err) next(err)
564564
else {
565565
const stopDebugOperator = startDebugOperator(
@@ -572,12 +572,15 @@ export function map<Input, Output>(
572572
next(null, { ...context, value } as any)
573573
}
574574
}
575+
instance[IS_PIPE] = true
576+
577+
return instance
575578
}
576579

577580
export function run<Input>(
578581
operation: (input: Context<Input>) => void
579582
): Operator<Input, Input> {
580-
return (err, context, next) => {
583+
const instance = (err, context, next) => {
581584
if (err) next(err)
582585
else {
583586
const stopDebugOperator = startDebugOperator(
@@ -590,12 +593,15 @@ export function run<Input>(
590593
next(null, context as any)
591594
}
592595
}
596+
instance[IS_PIPE] = true
597+
598+
return instance
593599
}
594600

595601
export function forEach<Input extends any[]>(
596602
forEachItemOperator: Operator<Input[0], any>
597603
): Operator<Input, Input> {
598-
return (err, context, next) => {
604+
const instance = (err, context, next) => {
599605
if (err) next(err)
600606
else {
601607
const stopDebugOperator = startDebugOperator(
@@ -627,22 +633,28 @@ export function forEach<Input extends any[]>(
627633
)
628634
}
629635
}
636+
instance[IS_PIPE] = true
637+
638+
return instance
630639
}
631640

632641
export function filter<Input>(
633642
operation: (input: Context<Input>) => boolean
634643
): Operator<Input, Input> {
635-
return (err, context, next, final) => {
644+
const instance = (err, context, next, final) => {
636645
if (err) next(err)
637646
else if (operation(context)) next(null, context)
638647
else final(null, context)
639648
}
649+
instance[IS_PIPE] = true
650+
651+
return instance
640652
}
641653

642654
export function mutate<Input>(
643655
operation: (input: Context<Input>) => void
644656
): Operator<Input, Input> {
645-
return (err, context, next) => {
657+
const instance = (err, context, next) => {
646658
if (err) next(err)
647659
else {
648660
const operatorId = context.execution.operatorId
@@ -663,6 +675,9 @@ export function mutate<Input>(
663675
next(null, context)
664676
}
665677
}
678+
instance[IS_PIPE] = true
679+
680+
return instance
666681
}
667682

668683
export function fork<
@@ -672,13 +687,16 @@ export function fork<
672687
operation: (input: Context<Input>) => keyof Paths,
673688
paths: Paths
674689
): Operator<Input, Input> {
675-
return (err, context, next) => {
690+
const instance = (err, context, next) => {
676691
if (err) return next(err)
677692
paths[operation(context)](null, context, (err) => {
678693
if (err) next(err)
679694
else next(null, context)
680695
})
681696
}
697+
instance[IS_PIPE] = true
698+
699+
return instance
682700
}
683701

684702
export function when<Input, OutputA, OutputB>(
@@ -688,24 +706,30 @@ export function when<Input, OutputA, OutputB>(
688706
false: Operator<Input, OutputB>
689707
}
690708
): Operator<Input, OutputA | OutputB> {
691-
return (err, context, next) => {
709+
const instance = (err, context, next) => {
692710
if (err) next(err)
693711
else if (operation(context)) paths.true(null, context, next)
694712
else paths.false(null, context, next)
695713
}
714+
instance[IS_PIPE] = true
715+
716+
return instance
696717
}
697718

698719
export function wait<Input>(ms: number): Operator<Input, Input> {
699-
return (err, context, next) => {
720+
const instance = (err, context, next) => {
700721
if (err) next(err)
701722
else setTimeout(() => next(null, context), ms)
702723
}
724+
instance[IS_PIPE] = true
725+
726+
return instance
703727
}
704728

705729
export function debounce<Input>(ms: number): Operator<Input, Input> {
706730
let timeout
707731
let previousFinal
708-
return (err, value, next, final) => {
732+
const instance = (err, value, next, final) => {
709733
if (err) {
710734
return next(err)
711735
}
@@ -719,4 +743,7 @@ export function debounce<Input>(ms: number): Operator<Input, Input> {
719743
next(null, value)
720744
}, ms)
721745
}
746+
instance[IS_PIPE] = true
747+
748+
return instance
722749
}

packages/node_modules/overmind/src/modules.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import { Configuration } from './'
22
import { ResolveState, ResolveActions } from './internalTypes'
33

4-
type SubType<Base, Condition> = Pick<
5-
Base,
6-
{ [Key in keyof Base]: Base[Key] extends Condition ? Key : never }[keyof Base]
7-
>
8-
94
interface ConfigurationWithModules extends Configuration {
105
[namespace: string]: {
116
onInitialize?: any
@@ -43,7 +38,7 @@ export function modules<T extends ConfigurationWithModules>(
4338
onInitialize?: any
4439
state: { [P in keyof T]: ResolveState<T[P]['state']> }
4540
effects: { [P in keyof T]: T[P]['effects'] }
46-
actions: { [P in keyof T]: ResolveActions<T[P]['state']> }
41+
actions: { [P in keyof T]: ResolveActions<T[P]['actions']> }
4742
} {
4843
const result: any = {
4944
initializers: [],

packages/node_modules/overmind/src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ export type TContext<App extends BaseApp, Value> = TBaseContext<App> & {
3131
value: Value
3232
}
3333

34-
export type TAction<App extends BaseApp, Value, ReturnValue = Value> = (
34+
export type TAction<App extends BaseApp, Value> = (
3535
context: TContext<App, Value>
36-
) => ReturnValue
36+
) => any
3737

3838
export type TOperator<C, RC> = (
3939
err: Error,

packages/node_modules/proxy-state-tree/src/index.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,4 +951,30 @@ describe('SCOPED', () => {
951951
expect(tree.get().foo).toBe('bar2')
952952
expect(scoped.get().foo).toBe('bar2')
953953
})
954+
it('should be able to change scope of state', () => {
955+
const tree = new ProxyStateTree({
956+
foo: 'bar',
957+
})
958+
959+
const scoped = tree.getScopedTree()
960+
const changeScope = scoped.scope(tree.get())
961+
962+
scoped.startMutationTracking()
963+
changeScope.foo = 'bar2'
964+
scoped.clearMutationTracking()
965+
expect(tree.get().foo).toBe('bar2')
966+
expect(scoped.get().foo).toBe('bar2')
967+
})
968+
it('should not recreate proxy when exists', () => {
969+
const tree = new ProxyStateTree({
970+
foo: {
971+
bar: 'baz',
972+
},
973+
})
974+
975+
const state = tree.get()
976+
977+
// eslint-disable-next-line
978+
expect(state.foo === state.foo).toBe(true)
979+
})
954980
})

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ export class ProxyStateTree {
7474

7575
return instance
7676
}
77+
scope(value) {
78+
return value && value[IS_PROXY]
79+
? proxify(this, value[VALUE], value[PATH])
80+
: value
81+
}
7782
addTrackingPath(path) {
7883
if (this.status.has(STATUS.TRACKING_PATHS)) {
7984
this.paths[this.paths.length - 1].add(path)

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,16 @@ function getValue(value, tree) {
186186
return value
187187
}
188188

189-
if (value[IS_PROXY]) {
190-
return value[VALUE][tree.PROXY] || value[VALUE]
189+
if (value[tree.PROXY]) {
190+
return value[tree.PROXY]
191191
}
192192

193193
return value
194194
}
195195

196196
export function proxify(tree, value, path?) {
197197
value = getValue(value, tree)
198+
198199
if (value) {
199200
if (value[IS_PROXY] && value[PATH] !== path) {
200201
delete value[VALUE][tree.PROXY]
@@ -210,6 +211,7 @@ export function proxify(tree, value, path?) {
210211
configurable: true,
211212
value: createObjectProxy(tree, value, path),
212213
})
214+
213215
return value[tree.PROXY]
214216
} else if (Array.isArray(value)) {
215217
Object.defineProperty(value, tree.PROXY, {

packages/overmind-website/api/pipe.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ The pipe is an operator in itself. Use it to compose other operators and pipes.
5757
h(Example, { name: "api/pipe_pipe" })
5858
```
5959

60+
## run
61+
This operator is useful to run effects. It will just pass the current value a long.
62+
63+
```marksy
64+
h(Example, { name: "api/pipe_run" })
65+
```
66+
6067
## wait
6168
Hold execution for set time.
6269

0 commit comments

Comments
 (0)