Skip to content

Commit 85e0a34

Browse files
Lonli-Loklisergeysova
authored andcommitted
feat: add cut operator
1 parent 4a262d8 commit 85e0a34

File tree

5 files changed

+576
-0
lines changed

5 files changed

+576
-0
lines changed

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,48 @@ reset({
771771

772772
[Try it](https://share.effector.dev/06hpVftG)
773773

774+
## Cut
775+
776+
[Method documentation & API](/src/cut)
777+
778+
```ts
779+
import { createEvent } from 'effector';
780+
import { cut } from 'patronum/cut';
781+
782+
type WSInitEvent = { type: 'init'; key: string };
783+
type WSIncrementEvent = { type: 'increment'; count: number; name: string };
784+
type WSResetEvent = { type: 'reset'; name: string };
785+
type WSEvent =
786+
| WSInitEvent
787+
| WSIncrementEvent
788+
| WSResetEvent
789+
790+
export const websocketEventReceived = createEvent<WSEvent[]>();
791+
792+
const { init, increment, reset, __ } = cut({
793+
source: websocketEventReceived,
794+
cases: {
795+
init: (events) => events.filter((wsEvent: WSEvent): wsEvent is WSInitEvent => wsEvent.type === 'init'),
796+
increment: (events) => events.filter((wsEvent: WSEvent): wsEvent is WSIncrementEvent => wsEvent.type === 'increment'),
797+
reset: (events) => events.filter((wsEvent: WSEvent): wsEvent is WSResetEvent => wsEvent.type === 'reset'),
798+
},
799+
});
800+
801+
init.watch(initEvents => {
802+
console.info(`inited for ${initEvents.length}`);
803+
});
804+
805+
increment.watch(incrementEvents => {
806+
console.info('should be incremented', incrementEvents.map(wsEvent => wsEvent.count).reduce((a, b) => a + b));
807+
});
808+
809+
websocketEventReceived([{ type: 'increment', name: 'demo', count: 5 }, { type: 'increment', name: 'demo', count: 15 }]);
810+
// => inited for 0
811+
// => should be incremented 20
812+
```
813+
814+
[Try it]()
815+
774816
# Development
775817

776818
You can review [CONTRIBUTING.md](./CONTRIBUTING.md)

src/cut/cut.fork.test.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import 'regenerator-runtime/runtime';
2+
import { createDomain, fork, serialize, allSettled } from 'effector';
3+
4+
import { cut } from './index';
5+
6+
test('works in forked scope', async () => {
7+
const app = createDomain();
8+
const source = app.createEvent<{ first?: number; another?: boolean }>();
9+
const out = cut({
10+
source,
11+
cases: {
12+
first: (payload) => payload.first,
13+
},
14+
});
15+
16+
const $data = app.createStore(0);
17+
18+
$data
19+
.on(out.first, (state, payload) => state + payload)
20+
.on(out.__, (state, payload) => (payload ? -state : 0));
21+
22+
const scope = fork(app);
23+
24+
await allSettled(source, {
25+
scope,
26+
params: { first: 15 },
27+
});
28+
expect(serialize(scope)).toMatchInlineSnapshot(`
29+
Object {
30+
"-4r0u7g": 15,
31+
}
32+
`);
33+
34+
await allSettled(source, {
35+
scope,
36+
params: { another: true },
37+
});
38+
expect(serialize(scope)).toMatchInlineSnapshot(`
39+
Object {
40+
"-4r0u7g": -15,
41+
}
42+
`);
43+
});
44+
45+
test('do not affect another fork', async () => {
46+
const app = createDomain();
47+
const source = app.createEvent<{ first?: number; another?: boolean }>();
48+
const out = cut({
49+
source,
50+
cases: {
51+
first: (payload) => payload.first,
52+
},
53+
});
54+
55+
const $data = app.createStore(0);
56+
57+
$data
58+
.on(out.first, (state, payload) => state + payload)
59+
.on(out.__, (state, payload) => (payload ? -state : 0));
60+
61+
const scopeA = fork(app);
62+
const scopeB = fork(app);
63+
64+
await allSettled(source, {
65+
scope: scopeA,
66+
params: { first: 200 },
67+
});
68+
expect(serialize(scopeA)).toMatchInlineSnapshot(`
69+
Object {
70+
"-hjldon": 200,
71+
}
72+
`);
73+
74+
await allSettled(source, {
75+
scope: scopeB,
76+
params: { first: -5 },
77+
});
78+
expect(serialize(scopeB)).toMatchInlineSnapshot(`
79+
Object {
80+
"-hjldon": -5,
81+
}
82+
`);
83+
});
84+
85+
test('do not affect original store value', async () => {
86+
const app = createDomain();
87+
const source = app.createEvent<{ first?: number; another?: boolean }>();
88+
const out = cut({
89+
source,
90+
cases: {
91+
first: (payload) => payload.first,
92+
},
93+
});
94+
95+
const $data = app.createStore(0);
96+
97+
$data
98+
.on(out.first, (state, payload) => state + payload)
99+
.on(out.__, (state, payload) => (payload ? -state : 0));
100+
101+
const scope = fork(app);
102+
103+
await allSettled(source, {
104+
scope,
105+
params: { first: 15 },
106+
});
107+
expect(serialize(scope)).toMatchInlineSnapshot(`
108+
Object {
109+
"-tv4arn": 15,
110+
}
111+
`);
112+
expect($data.getState()).toBe($data.defaultState);
113+
});

0 commit comments

Comments
 (0)