@vanyamate/sec 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/index.d.ts +7 -5
- package/index.ts +52 -32
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# SEC (Store, Effect, Combine)
|
|
2
|
+
|
|
3
|
+
Tiny state manager
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
import { store, effect, combine } from './index';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const sum = async (a, b) => a + b;
|
|
10
|
+
|
|
11
|
+
// Create effect
|
|
12
|
+
const sumEffect = effect(sum);
|
|
13
|
+
|
|
14
|
+
// Create stores
|
|
15
|
+
const allSums = store(0).on(sumEffect, 'onSuccess', (state, { result }) => state + result);
|
|
16
|
+
const lastSum = store(0).on(sumEffect, 'onSuccess', (_, { result }) => result);
|
|
17
|
+
|
|
18
|
+
// Create combine
|
|
19
|
+
const bothSum = combine([ allSums, lastSum ], (...args) => args.reduce((acc, item) => acc + item.get(), 0));
|
|
20
|
+
```
|
package/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export type EffectEvent = 'onBefore' | 'onSuccess' | 'onError' | 'onFinally';
|
|
|
3
3
|
export type Effect<Args extends any[], Result> = {
|
|
4
4
|
(...args: Args): Promise<Result>;
|
|
5
5
|
onSuccess: (callback: (result: Result, ...args: Args) => void) => void;
|
|
6
|
-
onError: (callback: (error:
|
|
6
|
+
onError: (callback: (error: unknown, ...args: Args) => void) => void;
|
|
7
7
|
onFinally: (callback: (...args: Args) => void) => void;
|
|
8
8
|
onBefore: (callback: (...args: Args) => void) => void;
|
|
9
9
|
};
|
|
@@ -14,12 +14,14 @@ export type Store<State> = {
|
|
|
14
14
|
set: (newState: State) => void;
|
|
15
15
|
on: <Args extends any[], Result>(effect: Effect<Args, Result>, event: EffectEvent, handler: (state: State, payload: {
|
|
16
16
|
result?: Result;
|
|
17
|
-
error?:
|
|
18
|
-
|
|
17
|
+
error?: unknown;
|
|
18
|
+
args: Args;
|
|
19
19
|
}) => State) => Store<State>;
|
|
20
20
|
subscribe: (listener: Listener<State>) => () => void;
|
|
21
21
|
};
|
|
22
22
|
export declare function store<State>(initialState: State): Store<State>;
|
|
23
|
-
export declare function combine<States extends any[]>(
|
|
23
|
+
export declare function combine<States extends any[], Result>(stores: {
|
|
24
24
|
[K in keyof States]: Store<States[K]>;
|
|
25
|
-
}
|
|
25
|
+
}, callback: (...stores: {
|
|
26
|
+
[K in keyof States]: Store<States[K]>;
|
|
27
|
+
}) => Result): Store<Result>;
|
package/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ export type EffectEvent = 'onBefore' | 'onSuccess' | 'onError' | 'onFinally';
|
|
|
4
4
|
export type Effect<Args extends any[], Result> = {
|
|
5
5
|
(...args: Args): Promise<Result>;
|
|
6
6
|
onSuccess: (callback: (result: Result, ...args: Args) => void) => void;
|
|
7
|
-
onError: (callback: (error:
|
|
7
|
+
onError: (callback: (error: unknown, ...args: Args) => void) => void;
|
|
8
8
|
onFinally: (callback: (...args: Args) => void) => void;
|
|
9
9
|
onBefore: (callback: (...args: Args) => void) => void;
|
|
10
10
|
};
|
|
@@ -14,10 +14,10 @@ export type Listener<State> = (state: State) => void;
|
|
|
14
14
|
export function effect<Args extends any[], Result> (fn: EffectFunction<Args, Result>): Effect<Args, Result> {
|
|
15
15
|
let beforeListeners: ((...args: Args) => void)[] = [];
|
|
16
16
|
let successListeners: ((result: Result, ...args: Args) => void)[] = [];
|
|
17
|
-
let errorListeners: ((error:
|
|
17
|
+
let errorListeners: ((error: unknown, ...args: Args) => void)[] = [];
|
|
18
18
|
let finallyListeners: ((...args: Args) => void)[] = [];
|
|
19
19
|
|
|
20
|
-
const wrappedEffect:
|
|
20
|
+
const wrappedEffect: Effect<Args, Result> = async (...args: Args) => {
|
|
21
21
|
beforeListeners.forEach(listener => listener(...args));
|
|
22
22
|
try {
|
|
23
23
|
const result = await fn(...args);
|
|
@@ -39,7 +39,7 @@ export function effect<Args extends any[], Result> (fn: EffectFunction<Args, Res
|
|
|
39
39
|
successListeners.push(callback);
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
wrappedEffect.onError = (callback: (error:
|
|
42
|
+
wrappedEffect.onError = (callback: (error: unknown, ...args: Args) => void) => {
|
|
43
43
|
errorListeners.push(callback);
|
|
44
44
|
};
|
|
45
45
|
|
|
@@ -47,7 +47,7 @@ export function effect<Args extends any[], Result> (fn: EffectFunction<Args, Res
|
|
|
47
47
|
finallyListeners.push(callback);
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
return wrappedEffect
|
|
50
|
+
return wrappedEffect;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export type Store<State> = {
|
|
@@ -58,8 +58,8 @@ export type Store<State> = {
|
|
|
58
58
|
event: EffectEvent,
|
|
59
59
|
handler: (state: State, payload: {
|
|
60
60
|
result?: Result;
|
|
61
|
-
error?:
|
|
62
|
-
|
|
61
|
+
error?: unknown;
|
|
62
|
+
args: Args
|
|
63
63
|
}) => State,
|
|
64
64
|
) => Store<State>;
|
|
65
65
|
subscribe: (listener: Listener<State>) => () => void;
|
|
@@ -80,27 +80,27 @@ export function store<State> (initialState: State): Store<State> {
|
|
|
80
80
|
event: EffectEvent,
|
|
81
81
|
handler: (state: State, payload: {
|
|
82
82
|
result?: Result;
|
|
83
|
-
error?:
|
|
84
|
-
|
|
83
|
+
error?: unknown;
|
|
84
|
+
args: Args
|
|
85
85
|
}) => State,
|
|
86
86
|
): Store<State> => {
|
|
87
87
|
const callback = (payload: {
|
|
88
88
|
result?: Result;
|
|
89
|
-
error?:
|
|
90
|
-
|
|
89
|
+
error?: unknown;
|
|
90
|
+
args: Args
|
|
91
91
|
}) => set(handler(state, payload));
|
|
92
92
|
|
|
93
93
|
if (event === 'onBefore') {
|
|
94
|
-
effect.onBefore((...args) => callback({
|
|
94
|
+
effect.onBefore((...args) => callback({ args }));
|
|
95
95
|
} else if (event === 'onSuccess') {
|
|
96
96
|
effect.onSuccess((result, ...args) => callback({
|
|
97
97
|
result,
|
|
98
|
-
|
|
98
|
+
args,
|
|
99
99
|
}));
|
|
100
100
|
} else if (event === 'onError') {
|
|
101
|
-
effect.onError((error, ...args) => callback({ error,
|
|
101
|
+
effect.onError((error, ...args) => callback({ error, args }));
|
|
102
102
|
} else if (event === 'onFinally') {
|
|
103
|
-
effect.onFinally((...args) => callback({
|
|
103
|
+
effect.onFinally((...args) => callback({ args }));
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
return storeApi;
|
|
@@ -108,7 +108,12 @@ export function store<State> (initialState: State): Store<State> {
|
|
|
108
108
|
|
|
109
109
|
const subscribe = (listener: Listener<State>) => {
|
|
110
110
|
listeners.push(listener);
|
|
111
|
-
return () =>
|
|
111
|
+
return () => {
|
|
112
|
+
const index = listeners.indexOf(listener);
|
|
113
|
+
if (index !== -1) {
|
|
114
|
+
listeners.splice(index, 1);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
112
117
|
};
|
|
113
118
|
|
|
114
119
|
const storeApi = {
|
|
@@ -121,28 +126,43 @@ export function store<State> (initialState: State): Store<State> {
|
|
|
121
126
|
return storeApi;
|
|
122
127
|
}
|
|
123
128
|
|
|
124
|
-
export function combine<States extends any[]> (
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
export function combine<States extends any[], Result> (
|
|
130
|
+
stores: { [K in keyof States]: Store<States[K]> },
|
|
131
|
+
callback: (...stores: { [K in keyof States]: Store<States[K]> }) => Result,
|
|
132
|
+
): Store<Result> {
|
|
133
|
+
let combinedState: Result = callback(...stores);
|
|
127
134
|
|
|
128
|
-
stores.forEach((store
|
|
129
|
-
store.subscribe((
|
|
130
|
-
combinedState
|
|
131
|
-
|
|
135
|
+
stores.forEach((store) => {
|
|
136
|
+
store.subscribe(() => {
|
|
137
|
+
combinedState = callback(...stores);
|
|
138
|
+
listeners.forEach(listener => listener(combinedState));
|
|
132
139
|
});
|
|
133
140
|
});
|
|
134
141
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
142
|
+
const listeners: Listener<Result>[] = [];
|
|
143
|
+
|
|
144
|
+
const get = () => combinedState;
|
|
145
|
+
|
|
146
|
+
const subscribe = (listener: Listener<Result>) => {
|
|
147
|
+
listeners.push(listener);
|
|
148
|
+
return () => {
|
|
149
|
+
const index = listeners.indexOf(listener);
|
|
150
|
+
if (index !== -1) {
|
|
151
|
+
listeners.splice(index, 1);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const storeApi: Store<Result> = {
|
|
157
|
+
get,
|
|
158
|
+
set: () => {
|
|
159
|
+
throw new Error('Cannot call \'set\' on combined store');
|
|
139
160
|
},
|
|
140
|
-
on
|
|
161
|
+
on : () => {
|
|
141
162
|
throw new Error('Cannot call \'on\' on combined store');
|
|
142
163
|
},
|
|
143
|
-
subscribe
|
|
144
|
-
combinedListeners.push(listener);
|
|
145
|
-
return () => combinedListeners = combinedListeners.filter((l) => l !== listener);
|
|
146
|
-
},
|
|
164
|
+
subscribe,
|
|
147
165
|
};
|
|
166
|
+
|
|
167
|
+
return storeApi;
|
|
148
168
|
}
|