Skip to content

Commit 2af6b0f

Browse files
Lonli-Loklisergeysova
authored andcommitted
feat: add cut operator
1 parent b298405 commit 2af6b0f

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
@@ -52,6 +52,48 @@ Patronum had 3 breaking changes: 1) from `0.14` to `0.100`, 2) from `0.100` to `
5252

5353
We have [migration guide](https://patronum.effector.dev/docs/migration-guide).
5454

55+
## Cut
56+
57+
[Method documentation & API](/src/cut)
58+
59+
```ts
60+
import { createEvent } from 'effector';
61+
import { cut } from 'patronum/cut';
62+
63+
type WSInitEvent = { type: 'init'; key: string };
64+
type WSIncrementEvent = { type: 'increment'; count: number; name: string };
65+
type WSResetEvent = { type: 'reset'; name: string };
66+
type WSEvent =
67+
| WSInitEvent
68+
| WSIncrementEvent
69+
| WSResetEvent
70+
71+
export const websocketEventReceived = createEvent<WSEvent[]>();
72+
73+
const { init, increment, reset, __ } = cut({
74+
source: websocketEventReceived,
75+
cases: {
76+
init: (events) => events.filter((wsEvent: WSEvent): wsEvent is WSInitEvent => wsEvent.type === 'init'),
77+
increment: (events) => events.filter((wsEvent: WSEvent): wsEvent is WSIncrementEvent => wsEvent.type === 'increment'),
78+
reset: (events) => events.filter((wsEvent: WSEvent): wsEvent is WSResetEvent => wsEvent.type === 'reset'),
79+
},
80+
});
81+
82+
init.watch(initEvents => {
83+
console.info(`inited for ${initEvents.length}`);
84+
});
85+
86+
increment.watch(incrementEvents => {
87+
console.info('should be incremented', incrementEvents.map(wsEvent => wsEvent.count).reduce((a, b) => a + b));
88+
});
89+
90+
websocketEventReceived([{ type: 'increment', name: 'demo', count: 5 }, { type: 'increment', name: 'demo', count: 15 }]);
91+
// => inited for 0
92+
// => should be incremented 20
93+
```
94+
95+
[Try it]()
96+
5597
# Development
5698

5799
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)