@vanyamate/sec 0.0.6

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.
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/sec.iml" filepath="$PROJECT_DIR$/.idea/sec.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
package/.idea/sec.iml ADDED
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="WEB_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$">
5
+ <excludeFolder url="file://$MODULE_DIR$/.tmp" />
6
+ <excludeFolder url="file://$MODULE_DIR$/temp" />
7
+ <excludeFolder url="file://$MODULE_DIR$/tmp" />
8
+ </content>
9
+ <orderEntry type="inheritedJdk" />
10
+ <orderEntry type="sourceFolder" forTests="false" />
11
+ </component>
12
+ </module>
package/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
+ </component>
6
+ </project>
package/index.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ export type EffectFunction<Args extends any[], Result> = (...args: Args) => Promise<Result>;
2
+ export type Effect<Args extends any[], Result> = {
3
+ (...args: Args): Promise<Result>;
4
+ onSuccess: (callback: (result: Result, ...args: Args) => void) => void;
5
+ onError: (callback: (error: any, ...args: Args) => void) => void;
6
+ onFinally: (callback: (...args: Args) => void) => void;
7
+ onBefore: (callback: (...args: Args) => void) => void;
8
+ };
9
+ export type Listener<State> = (state: State) => void;
10
+ export declare function effect<Args extends any[], Result>(fn: EffectFunction<Args, Result>): Effect<Args, Result>;
11
+ export type Store<State> = {
12
+ get: () => State;
13
+ set: (newState: State) => void;
14
+ on: <Args extends any[], Result>(effect: Effect<Args, Result>, event: 'onBefore' | 'onSuccess' | 'onError' | 'onFinally', handler: (state: State, payload: {
15
+ result?: Result;
16
+ error?: any;
17
+ meta: Args;
18
+ }) => State) => Store<State>;
19
+ subscribe: (listener: Listener<State>) => () => void;
20
+ };
21
+ export declare function store<State>(initialState: State): Store<State>;
22
+ export declare function combine<States extends any[]>(...stores: {
23
+ [K in keyof States]: Store<States[K]>;
24
+ }): Store<States>;
package/index.ts ADDED
@@ -0,0 +1,147 @@
1
+ export type EffectFunction<Args extends any[], Result> = (...args: Args) => Promise<Result>;
2
+
3
+ export type Effect<Args extends any[], Result> = {
4
+ (...args: Args): Promise<Result>;
5
+ onSuccess: (callback: (result: Result, ...args: Args) => void) => void;
6
+ onError: (callback: (error: any, ...args: Args) => void) => void;
7
+ onFinally: (callback: (...args: Args) => void) => void;
8
+ onBefore: (callback: (...args: Args) => void) => void;
9
+ };
10
+
11
+ export type Listener<State> = (state: State) => void;
12
+
13
+ export function effect<Args extends any[], Result> (fn: EffectFunction<Args, Result>): Effect<Args, Result> {
14
+ let beforeListeners: ((...args: Args) => void)[] = [];
15
+ let successListeners: ((result: Result, ...args: Args) => void)[] = [];
16
+ let errorListeners: ((error: any, ...args: Args) => void)[] = [];
17
+ let finallyListeners: ((...args: Args) => void)[] = [];
18
+
19
+ const wrappedEffect: any = async (...args: Args) => {
20
+ beforeListeners.forEach(listener => listener(...args));
21
+ try {
22
+ const result = await fn(...args);
23
+ successListeners.forEach(listener => listener(result, ...args));
24
+ return result;
25
+ } catch (error) {
26
+ errorListeners.forEach(listener => listener(error, ...args));
27
+ throw error;
28
+ } finally {
29
+ finallyListeners.forEach(listener => listener(...args));
30
+ }
31
+ };
32
+
33
+ wrappedEffect.onBefore = (callback: (...args: Args) => void) => {
34
+ beforeListeners.push(callback);
35
+ };
36
+
37
+ wrappedEffect.onSuccess = (callback: (result: Result, ...args: Args) => void) => {
38
+ successListeners.push(callback);
39
+ };
40
+
41
+ wrappedEffect.onError = (callback: (error: any, ...args: Args) => void) => {
42
+ errorListeners.push(callback);
43
+ };
44
+
45
+ wrappedEffect.onFinally = (callback: (...args: Args) => void) => {
46
+ finallyListeners.push(callback);
47
+ };
48
+
49
+ return wrappedEffect as Effect<Args, Result>;
50
+ }
51
+
52
+ export type Store<State> = {
53
+ get: () => State;
54
+ set: (newState: State) => void;
55
+ on: <Args extends any[], Result>(
56
+ effect: Effect<Args, Result>,
57
+ event: 'onBefore' | 'onSuccess' | 'onError' | 'onFinally',
58
+ handler: (state: State, payload: {
59
+ result?: Result;
60
+ error?: any;
61
+ meta: Args
62
+ }) => State,
63
+ ) => Store<State>;
64
+ subscribe: (listener: Listener<State>) => () => void;
65
+ };
66
+
67
+ export function store<State> (initialState: State): Store<State> {
68
+ let state = initialState;
69
+ let listeners: Listener<State>[] = [];
70
+
71
+ const get = () => state;
72
+ const set = (newState: State) => {
73
+ state = newState;
74
+ listeners.forEach(listener => listener(state));
75
+ };
76
+
77
+ const on = <Args extends any[], Result> (
78
+ effect: Effect<Args, Result>,
79
+ event: 'onBefore' | 'onSuccess' | 'onError' | 'onFinally',
80
+ handler: (state: State, payload: {
81
+ result?: Result;
82
+ error?: any;
83
+ meta: Args
84
+ }) => State,
85
+ ): Store<State> => {
86
+ const callback = (payload: {
87
+ result?: Result;
88
+ error?: any;
89
+ meta: Args
90
+ }) => set(handler(state, payload));
91
+
92
+ if (event === 'onBefore') {
93
+ effect.onBefore((...args) => callback({ meta: args }));
94
+ } else if (event === 'onSuccess') {
95
+ effect.onSuccess((result, ...args) => callback({
96
+ result,
97
+ meta: args,
98
+ }));
99
+ } else if (event === 'onError') {
100
+ effect.onError((error, ...args) => callback({ error, meta: args }));
101
+ } else if (event === 'onFinally') {
102
+ effect.onFinally((...args) => callback({ meta: args }));
103
+ }
104
+
105
+ return storeApi;
106
+ };
107
+
108
+ const subscribe = (listener: Listener<State>) => {
109
+ listeners.push(listener);
110
+ return () => listeners = listeners.filter((l) => l !== listener);
111
+ };
112
+
113
+ const storeApi = {
114
+ get,
115
+ set,
116
+ on,
117
+ subscribe,
118
+ };
119
+
120
+ return storeApi;
121
+ }
122
+
123
+ export function combine<States extends any[]> (...stores: { [K in keyof States]: Store<States[K]> }): Store<States> {
124
+ let combinedState = stores.map(store => store.get()) as States;
125
+ let combinedListeners: Listener<States>[] = [];
126
+
127
+ stores.forEach((store, index) => {
128
+ store.subscribe((state) => {
129
+ combinedState[index] = state;
130
+ combinedListeners.forEach(listener => listener(combinedState));
131
+ });
132
+ });
133
+
134
+ return {
135
+ get : () => combinedState,
136
+ set : (newState) => {
137
+ newState.forEach((state, index) => stores[index].set(state));
138
+ },
139
+ on : () => {
140
+ throw new Error('Cannot call \'on\' on combined store');
141
+ },
142
+ subscribe: (listener) => {
143
+ combinedListeners.push(listener);
144
+ return () => combinedListeners = combinedListeners.filter((l) => l !== listener);
145
+ },
146
+ };
147
+ }
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@vanyamate/sec",
3
+ "version": "0.0.6",
4
+ "description": "SEC. Store, Effect, Combine. Tiny state manager",
5
+ "scripts": {
6
+ "g:type": "tsc index.ts --declaration --emitDeclarationOnly"
7
+ },
8
+ "types": "index.d.ts",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/VanyaMate/sec.git"
12
+ },
13
+ "keywords": [
14
+ "state",
15
+ "manager"
16
+ ],
17
+ "author": "Vanya Mate",
18
+ "license": "ISC",
19
+ "bugs": {
20
+ "url": "https://github.com/VanyaMate/sec/issues"
21
+ },
22
+ "homepage": "https://github.com/VanyaMate/sec#readme"
23
+ }