redux-sacala 0.1.0 → 0.2.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/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/jsLinters/eslint.xml +6 -0
- package/.idea/modules.xml +7 -7
- package/.idea/prettier.xml +7 -0
- package/.idea/redux-sacala.iml +12 -12
- package/.idea/vcs.xml +5 -5
- package/.idea/webResources.xml +13 -13
- package/.prettierignore +5 -0
- package/.prettierrc +8 -0
- package/README.md +134 -0
- package/build/redux-sacala.cjs +1 -0
- package/build/redux-sacala.d.ts +49 -34
- package/build/redux-sacala.js +53 -72
- package/eslint.config.js +23 -0
- package/package.json +28 -9
- package/src/redux-sacala.spec.ts +16 -24
- package/src/redux-sacala.ts +132 -124
- package/tsconfig.json +14 -15
- package/vite.config.ts +29 -0
- package/build/redux-sacala.js.map +0 -1
- package/build/redux-sacala.spec.d.ts +0 -1
- package/build/redux-sacala.spec.js +0 -42
- package/build/redux-sacala.spec.js.map +0 -1
- package/jest.config.js +0 -7
package/.idea/modules.xml
CHANGED
|
@@ -1,8 +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/redux-sacala.iml" filepath="$PROJECT_DIR$/.idea/redux-sacala.iml" />
|
|
6
|
-
</modules>
|
|
7
|
-
</component>
|
|
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/redux-sacala.iml" filepath="$PROJECT_DIR$/.idea/redux-sacala.iml" />
|
|
6
|
+
</modules>
|
|
7
|
+
</component>
|
|
8
8
|
</project>
|
package/.idea/redux-sacala.iml
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
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$/temp" />
|
|
6
|
-
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
7
|
-
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
8
|
-
<excludeFolder url="file://$MODULE_DIR$/build" />
|
|
9
|
-
</content>
|
|
10
|
-
<orderEntry type="inheritedJdk" />
|
|
11
|
-
<orderEntry type="sourceFolder" forTests="false" />
|
|
12
|
-
</component>
|
|
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$/temp" />
|
|
6
|
+
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
7
|
+
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
8
|
+
<excludeFolder url="file://$MODULE_DIR$/build" />
|
|
9
|
+
</content>
|
|
10
|
+
<orderEntry type="inheritedJdk" />
|
|
11
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
12
|
+
</component>
|
|
13
13
|
</module>
|
package/.idea/vcs.xml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<project version="4">
|
|
3
|
-
<component name="VcsDirectoryMappings">
|
|
4
|
-
<mapping directory="" vcs="Git" />
|
|
5
|
-
</component>
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="VcsDirectoryMappings">
|
|
4
|
+
<mapping directory="" vcs="Git" />
|
|
5
|
+
</component>
|
|
6
6
|
</project>
|
package/.idea/webResources.xml
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<project version="4">
|
|
3
|
-
<component name="WebResourcesPaths">
|
|
4
|
-
<contentEntries>
|
|
5
|
-
<entry url="file://$PROJECT_DIR$">
|
|
6
|
-
<entryData>
|
|
7
|
-
<resourceRoots>
|
|
8
|
-
<path value="file://$PROJECT_DIR$/src" />
|
|
9
|
-
</resourceRoots>
|
|
10
|
-
</entryData>
|
|
11
|
-
</entry>
|
|
12
|
-
</contentEntries>
|
|
13
|
-
</component>
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="WebResourcesPaths">
|
|
4
|
+
<contentEntries>
|
|
5
|
+
<entry url="file://$PROJECT_DIR$">
|
|
6
|
+
<entryData>
|
|
7
|
+
<resourceRoots>
|
|
8
|
+
<path value="file://$PROJECT_DIR$/src" />
|
|
9
|
+
</resourceRoots>
|
|
10
|
+
</entryData>
|
|
11
|
+
</entry>
|
|
12
|
+
</contentEntries>
|
|
13
|
+
</component>
|
|
14
14
|
</project>
|
package/.prettierignore
ADDED
package/.prettierrc
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# redux-sacala
|
|
2
|
+
|
|
3
|
+
A lightweight utility to create Redux blocks with minimal boilerplate, featuring type-safe actions, reducers, and side effects.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Minimal Boilerplate**: Define actions and reducers in one place.
|
|
8
|
+
- **Type Safety**: Full TypeScript support for state and action payloads.
|
|
9
|
+
- **Integrated Side Effects**: Middleware-based effects that have access to `dispatch` and `getState`.
|
|
10
|
+
- **Ducks Pattern**: Encourages grouping related logic together.
|
|
11
|
+
- **Extra Arguments**: Inject dependencies into your effects via middleware.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install redux-sacala
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
*Note: `redux` is a peer dependency.*
|
|
20
|
+
|
|
21
|
+
## Usage Example
|
|
22
|
+
|
|
23
|
+
### 1. Create a Redux Block
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { createReduxBlock } from 'redux-sacala';
|
|
27
|
+
|
|
28
|
+
interface CounterState {
|
|
29
|
+
count: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface RootState {
|
|
33
|
+
counter: CounterState;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Define the block
|
|
37
|
+
const {
|
|
38
|
+
actions,
|
|
39
|
+
reducer,
|
|
40
|
+
createMiddleware
|
|
41
|
+
} = createReduxBlock<RootState, { logger: (msg: string) => void }>()({
|
|
42
|
+
name: 'counter',
|
|
43
|
+
initial: { count: 0 },
|
|
44
|
+
actions: {
|
|
45
|
+
increment(state) {
|
|
46
|
+
return { count: state.count + 1 };
|
|
47
|
+
},
|
|
48
|
+
setCount(state, payload: number) {
|
|
49
|
+
return { count: payload };
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
effects: (dispatch, getState) => ({
|
|
53
|
+
asyncIncrement(payload: number, { logger }) {
|
|
54
|
+
logger('Starting async increment');
|
|
55
|
+
setTimeout(() => {
|
|
56
|
+
dispatch(actions.increment());
|
|
57
|
+
logger('Incremented');
|
|
58
|
+
}, payload);
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export { actions, reducer, createMiddleware };
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2. Configure the Store
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { createStore, combineReducers, applyMiddleware } from 'redux';
|
|
70
|
+
import { reducer, createMiddleware } from './counterBlock';
|
|
71
|
+
|
|
72
|
+
const rootReducer = combineReducers({
|
|
73
|
+
counter: reducer
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Create middleware with extra argument
|
|
77
|
+
const counterMiddleware = createMiddleware({
|
|
78
|
+
logger: (msg) => console.log(msg)
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const store = createStore(
|
|
82
|
+
rootReducer,
|
|
83
|
+
applyMiddleware(counterMiddleware)
|
|
84
|
+
);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 3. Dispatch Actions
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// These are type-safe
|
|
91
|
+
store.dispatch(actions.increment());
|
|
92
|
+
store.dispatch(actions.setCount(10));
|
|
93
|
+
store.dispatch(actions.asyncIncrement(1000)); // Delay of 1000ms
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## API
|
|
97
|
+
|
|
98
|
+
### `createReduxBlock<GlobalState, ExtraArgument = undefined>()(options)`
|
|
99
|
+
|
|
100
|
+
Creates a Redux block. The double-call pattern is used for better TypeScript type inference.
|
|
101
|
+
|
|
102
|
+
#### Options
|
|
103
|
+
- `name`: `string`. The key under which the state is stored in the global state. Must match a key in `GlobalState`.
|
|
104
|
+
- `initial`: `GlobalState[name]`. The initial state of the block.
|
|
105
|
+
- `actions`: An object where each key is an action name and each value is a state handler: `(state: BlockState, payload: any) => BlockState`.
|
|
106
|
+
- `effects`: (Optional) A function `(dispatch, getState) => effectsMap`.
|
|
107
|
+
- `effectsMap` keys are action types.
|
|
108
|
+
- `effectsMap` values are effect handlers: `(payload: any, extraArgument: ExtraArgument) => void`.
|
|
109
|
+
|
|
110
|
+
#### Returns
|
|
111
|
+
- `name`: The name of the block.
|
|
112
|
+
- `reducer`: The Redux reducer for this block.
|
|
113
|
+
- `actions`: An object containing action creators for both `actions` and `effects`.
|
|
114
|
+
- `createMiddleware`: A function `(extraArgument: ExtraArgument) => Middleware` to create the Redux middleware for handling the effects.
|
|
115
|
+
|
|
116
|
+
## Development
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Install dependencies
|
|
120
|
+
npm install
|
|
121
|
+
|
|
122
|
+
# Run tests
|
|
123
|
+
npm test
|
|
124
|
+
|
|
125
|
+
# Build the project
|
|
126
|
+
npm run build
|
|
127
|
+
|
|
128
|
+
# Lint the code
|
|
129
|
+
npm run lint
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
Author: Andrey Monkin (monkin.andrey@gmail.com)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function a(r){const e={};for(const t in r)e[t]=r[t].bind(r);return e}function f(r,e){const t={};for(const c in e)t[r+c]=e[c];return t}function l(r){return e=>e===void 0?{type:r}:{type:r,payload:e}}function p(r){return e=>({type:r,payload:e})}function y(r,e,t){const c=f(r+"/",a(t));return(n=e,u)=>{if(u&&u.type){const o=c[u.type];return o?o(n,u.payload):n}else return n}}function C(r,e){return(t=>c=>{const n=f(r+"/",a(e(c.dispatch,c.getState)));return u=>o=>{o&&n.hasOwnProperty(o.type)?n[o.type](o.payload,t):u(o)}})}function s(){throw new Error("Can't have access to 'dispatch' and 'getState' during initialization")}function b(){return function({name:e,initial:t,actions:c,effects:n}){const u=Object.keys(c).reduce((d,i)=>(d[i]=l(`${e}/${i}`),d),{}),o=Object.keys(n?n(s,s):{}).reduce((d,i)=>(d[i]=p(`${e}/${i}`),d),{});return{name:e,reducer:y(e,t,c),createMiddleware:n?C(e,n):(()=>(d=>i=>i)),actions:{...u,...o}}}}exports.createReduxBlock=b;
|
package/build/redux-sacala.d.ts
CHANGED
|
@@ -1,34 +1,49 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type
|
|
7
|
-
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
1
|
+
import { Action } from 'redux';
|
|
2
|
+
import { Dispatch } from 'redux';
|
|
3
|
+
import { Middleware } from 'redux';
|
|
4
|
+
import { Reducer } from 'redux';
|
|
5
|
+
|
|
6
|
+
declare type ActionCreator<Handler extends ActionHandler<any, any>> = undefined extends SecondArgument<Handler> ? () => Action<string> : (payload: SecondArgument<Handler>) => (Action<string> & {
|
|
7
|
+
payload: SecondArgument<Handler>;
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
declare type ActionCreatorMap<Actions extends ActionMap<any>> = {
|
|
11
|
+
[name in keyof Actions]: ActionCreator<Actions[name]>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
declare type ActionHandler<BlockState, Payload> = (state: BlockState, payload: Payload) => BlockState;
|
|
15
|
+
|
|
16
|
+
declare type ActionMap<BlockState> = {
|
|
17
|
+
[action: string]: ActionHandler<BlockState, any>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export declare function createReduxBlock<GlobalState, ExtraArgument = undefined>(): <Name extends (keyof GlobalState) & string, Actions extends ActionMap<GlobalState[Name]>, Effects extends EffectsMap<GlobalState, ExtraArgument>>({ name, initial, actions, effects }: {
|
|
21
|
+
name: Name;
|
|
22
|
+
initial: GlobalState[Name];
|
|
23
|
+
actions: Actions;
|
|
24
|
+
effects?: Effects;
|
|
25
|
+
}) => {
|
|
26
|
+
name: Name;
|
|
27
|
+
reducer: Reducer<GlobalState[Name]>;
|
|
28
|
+
actions: ActionCreatorMap<Actions> & EffectsCreatorMap<GlobalState, ExtraArgument, Effects>;
|
|
29
|
+
} & ({} extends ReturnType<Effects> ? {} : {
|
|
30
|
+
createMiddleware: MiddlewareCreator<ExtraArgument>;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
declare type EffectsCreatorMap<GlobalState, ExtraArgument, Map extends EffectsMap<GlobalState, ExtraArgument>> = {
|
|
34
|
+
[key in keyof ReturnType<Map>]: (undefined extends FirstArgument<ReturnType<Map>[key]> ? () => Action : (payload: FirstArgument<ReturnType<Map>[key]>) => Action);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
declare type EffectsMap<GlobalState, ExtraArgument> = (dispatch: Dispatch, getState: () => GlobalState) => {
|
|
38
|
+
[effect: string]: (payload: any, extraArgument: ExtraArgument) => any;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
declare type FirstArgument<F> = F extends (arg1: infer U, ...args: any[]) => any ? UnknownToUndefined<U> : undefined;
|
|
42
|
+
|
|
43
|
+
declare type MiddlewareCreator<T> = T extends undefined ? () => Middleware : (argument: T) => Middleware;
|
|
44
|
+
|
|
45
|
+
declare type SecondArgument<F> = F extends (arg1: any, arg2: infer U, ...args: any[]) => any ? UnknownToUndefined<U> : undefined;
|
|
46
|
+
|
|
47
|
+
declare type UnknownToUndefined<T> = unknown extends T ? undefined : T;
|
|
48
|
+
|
|
49
|
+
export { }
|
package/build/redux-sacala.js
CHANGED
|
@@ -1,75 +1,56 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
else {
|
|
35
|
-
return state;
|
|
36
|
-
}
|
|
1
|
+
function f(e) {
|
|
2
|
+
const r = {};
|
|
3
|
+
for (const t in e)
|
|
4
|
+
r[t] = e[t].bind(e);
|
|
5
|
+
return r;
|
|
6
|
+
}
|
|
7
|
+
function a(e, r) {
|
|
8
|
+
const t = {};
|
|
9
|
+
for (const c in r)
|
|
10
|
+
t[e + c] = r[c];
|
|
11
|
+
return t;
|
|
12
|
+
}
|
|
13
|
+
function l(e) {
|
|
14
|
+
return (r) => r === void 0 ? { type: e } : { type: e, payload: r };
|
|
15
|
+
}
|
|
16
|
+
function p(e) {
|
|
17
|
+
return (r) => ({ type: e, payload: r });
|
|
18
|
+
}
|
|
19
|
+
function C(e, r, t) {
|
|
20
|
+
const c = a(e + "/", f(t));
|
|
21
|
+
return (n = r, u) => {
|
|
22
|
+
if (u && u.type) {
|
|
23
|
+
const o = c[u.type];
|
|
24
|
+
return o ? o(n, u.payload) : n;
|
|
25
|
+
} else
|
|
26
|
+
return n;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function h(e, r) {
|
|
30
|
+
return ((t) => (c) => {
|
|
31
|
+
const n = a(e + "/", f(r(c.dispatch, c.getState)));
|
|
32
|
+
return (u) => (o) => {
|
|
33
|
+
o && n.hasOwnProperty(o.type) ? n[o.type](o.payload, t) : u(o);
|
|
37
34
|
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
export function createReduxBlock() {
|
|
56
|
-
return function applyConfig({ name, initial, actions, effects }) {
|
|
57
|
-
const actionCreators = Object.keys(actions).reduce((r, key) => {
|
|
58
|
-
r[key] = createActionCreator(`${name}/${key}`);
|
|
59
|
-
return r;
|
|
60
|
-
}, {});
|
|
61
|
-
const effectCreators = Object.keys(effects ? effects(fail, fail) : {}).reduce((r, key) => {
|
|
62
|
-
r[key] = createEffectCreator(`${name}/${key}`);
|
|
63
|
-
return r;
|
|
64
|
-
}, {});
|
|
65
|
-
return {
|
|
66
|
-
name,
|
|
67
|
-
reducer: createReducer(name, initial, actions),
|
|
68
|
-
createMiddleware: effects
|
|
69
|
-
? createMiddlewareCreator(name, effects)
|
|
70
|
-
: (() => ((_) => (next) => next)),
|
|
71
|
-
actions: Object.assign(Object.assign({}, actionCreators), effectCreators)
|
|
72
|
-
};
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function s() {
|
|
38
|
+
throw new Error("Can't have access to 'dispatch' and 'getState' during initialization");
|
|
39
|
+
}
|
|
40
|
+
function y() {
|
|
41
|
+
return function({ name: r, initial: t, actions: c, effects: n }) {
|
|
42
|
+
const u = Object.keys(c).reduce((d, i) => (d[i] = l(`${r}/${i}`), d), {}), o = Object.keys(n ? n(s, s) : {}).reduce((d, i) => (d[i] = p(`${r}/${i}`), d), {});
|
|
43
|
+
return {
|
|
44
|
+
name: r,
|
|
45
|
+
reducer: C(r, t, c),
|
|
46
|
+
createMiddleware: n ? h(r, n) : (() => ((d) => (i) => i)),
|
|
47
|
+
actions: {
|
|
48
|
+
...u,
|
|
49
|
+
...o
|
|
50
|
+
}
|
|
73
51
|
};
|
|
52
|
+
};
|
|
74
53
|
}
|
|
75
|
-
|
|
54
|
+
export {
|
|
55
|
+
y as createReduxBlock
|
|
56
|
+
};
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import eslint from "@eslint/js";
|
|
2
|
+
import tseslint from "typescript-eslint";
|
|
3
|
+
import prettierConfig from "eslint-config-prettier";
|
|
4
|
+
|
|
5
|
+
export default tseslint.config(
|
|
6
|
+
eslint.configs.recommended,
|
|
7
|
+
...tseslint.configs.recommended,
|
|
8
|
+
prettierConfig,
|
|
9
|
+
{
|
|
10
|
+
rules: {
|
|
11
|
+
"prefer-arrow-callback": "error",
|
|
12
|
+
"arrow-body-style": ["error", "as-needed"],
|
|
13
|
+
"func-style": ["error", "expression", { allowArrowFunctions: true }],
|
|
14
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
15
|
+
"@typescript-eslint/no-unsafe-function-type": "off",
|
|
16
|
+
"@typescript-eslint/no-empty-object-type": "off",
|
|
17
|
+
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
ignores: ["build/", "node_modules/", "coverage/"],
|
|
22
|
+
},
|
|
23
|
+
);
|
package/package.json
CHANGED
|
@@ -1,24 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redux-sacala",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"author": {
|
|
5
6
|
"name": "Andrey Monkin",
|
|
6
7
|
"email": "monkin.andrey@gmail.com"
|
|
7
8
|
},
|
|
8
9
|
"module": "build/redux-sacala.js",
|
|
9
|
-
"main": "build/redux-sacala.
|
|
10
|
+
"main": "build/redux-sacala.cjs",
|
|
10
11
|
"types": "build/redux-sacala.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./build/redux-sacala.d.ts",
|
|
15
|
+
"import": "./build/redux-sacala.js",
|
|
16
|
+
"require": "./build/redux-sacala.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
11
19
|
"peerDependencies": {
|
|
12
|
-
"redux": "^
|
|
20
|
+
"redux": "^5.0.1"
|
|
13
21
|
},
|
|
14
22
|
"devDependencies": {
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"@
|
|
18
|
-
"
|
|
23
|
+
"@eslint/js": "9.39.2",
|
|
24
|
+
"@types/node": "25.0.3",
|
|
25
|
+
"@typescript-eslint/eslint-plugin": "8.51.0",
|
|
26
|
+
"@typescript-eslint/parser": "8.51.0",
|
|
27
|
+
"eslint": "9.39.2",
|
|
28
|
+
"eslint-config-prettier": "10.1.8",
|
|
29
|
+
"prettier": "3.7.4",
|
|
30
|
+
"typescript": "5.9.3",
|
|
31
|
+
"typescript-eslint": "8.51.0",
|
|
32
|
+
"vite": "7.3.0",
|
|
33
|
+
"vite-plugin-dts": "4.5.4",
|
|
34
|
+
"vitest": "4.0.16"
|
|
19
35
|
},
|
|
20
36
|
"scripts": {
|
|
21
|
-
"
|
|
22
|
-
"
|
|
37
|
+
"build": "vite build",
|
|
38
|
+
"prepublishOnly": "npm test && npm run build",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"lint": "eslint .",
|
|
41
|
+
"format": "prettier --write ."
|
|
23
42
|
}
|
|
24
43
|
}
|
package/src/redux-sacala.spec.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createStore,
|
|
3
|
-
combineReducers,
|
|
4
|
-
applyMiddleware,
|
|
5
|
-
} from "redux";
|
|
1
|
+
import { applyMiddleware, combineReducers, createStore } from "redux";
|
|
6
2
|
import { createReduxBlock } from "./redux-sacala";
|
|
7
3
|
|
|
8
4
|
interface LocalState {
|
|
@@ -26,37 +22,33 @@ const {
|
|
|
26
22
|
},
|
|
27
23
|
set(_, count: number) {
|
|
28
24
|
return { count };
|
|
29
|
-
}
|
|
25
|
+
},
|
|
30
26
|
},
|
|
31
|
-
effects: (dispatch
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
};
|
|
37
|
-
}
|
|
27
|
+
effects: (dispatch) => ({
|
|
28
|
+
incEffect() {
|
|
29
|
+
dispatch(local.inc());
|
|
30
|
+
},
|
|
31
|
+
}),
|
|
38
32
|
});
|
|
39
33
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
beforeEach(() => {
|
|
49
|
-
store = createMyStore();
|
|
50
|
-
});
|
|
34
|
+
const createMyStore = () =>
|
|
35
|
+
createStore(
|
|
36
|
+
combineReducers({
|
|
37
|
+
local: localReducer,
|
|
38
|
+
}),
|
|
39
|
+
applyMiddleware(createLocalMiddleware(100)),
|
|
40
|
+
);
|
|
51
41
|
|
|
52
42
|
describe("Store with reducer and middleware", () => {
|
|
53
43
|
it("Should be updated on action without payload", () => {
|
|
44
|
+
const store = createMyStore();
|
|
54
45
|
store.dispatch(local.inc());
|
|
55
46
|
store.dispatch(local.inc());
|
|
56
47
|
expect(store.getState()).toEqual({ local: { count: 2 } });
|
|
57
48
|
});
|
|
58
49
|
|
|
59
50
|
it("Should be updated on action with payload", () => {
|
|
51
|
+
const store = createMyStore();
|
|
60
52
|
store.dispatch(local.set(12));
|
|
61
53
|
expect(store.getState()).toEqual({ local: { count: 12 } });
|
|
62
54
|
});
|
package/src/redux-sacala.ts
CHANGED
|
@@ -1,124 +1,132 @@
|
|
|
1
|
-
import { Dispatch, Action, Reducer, Middleware, AnyAction, MiddlewareAPI } from "redux";
|
|
2
|
-
|
|
3
|
-
type UnknownToUndefined<T> = unknown extends T ? undefined : T;
|
|
4
|
-
|
|
5
|
-
type FirstArgument<F> = F extends (arg1: infer U, ...args: any[]) => any ? UnknownToUndefined<U> : undefined;
|
|
6
|
-
type SecondArgument<F> = F extends (arg1: any, arg2: infer U, ...args: any[]) => any
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
type
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
name
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
1
|
+
import { Dispatch, Action, Reducer, Middleware, AnyAction, MiddlewareAPI } from "redux";
|
|
2
|
+
|
|
3
|
+
type UnknownToUndefined<T> = unknown extends T ? undefined : T;
|
|
4
|
+
|
|
5
|
+
type FirstArgument<F> = F extends (arg1: infer U, ...args: any[]) => any ? UnknownToUndefined<U> : undefined;
|
|
6
|
+
type SecondArgument<F> = F extends (arg1: any, arg2: infer U, ...args: any[]) => any
|
|
7
|
+
? UnknownToUndefined<U>
|
|
8
|
+
: undefined;
|
|
9
|
+
|
|
10
|
+
const bindAll = <T extends { [key: string]: Function }>(map: T): T => {
|
|
11
|
+
const result = {} as any as T;
|
|
12
|
+
for (const i in map) {
|
|
13
|
+
result[i] = map[i].bind(map);
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const appendPrefix = <T>(prefix: string, map: { [key: string]: T }) => {
|
|
19
|
+
const r: { [key: string]: any } = {};
|
|
20
|
+
for (const i in map) {
|
|
21
|
+
r[prefix + i] = map[i];
|
|
22
|
+
}
|
|
23
|
+
return r;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Input
|
|
27
|
+
type ActionHandler<BlockState, Payload> = (state: BlockState, payload: Payload) => BlockState;
|
|
28
|
+
type ActionMap<BlockState> = { [action: string]: ActionHandler<BlockState, any> };
|
|
29
|
+
type EffectsMap<GlobalState, ExtraArgument> = (
|
|
30
|
+
dispatch: Dispatch,
|
|
31
|
+
getState: () => GlobalState,
|
|
32
|
+
) => { [effect: string]: (payload: any, extraArgument: ExtraArgument) => any };
|
|
33
|
+
|
|
34
|
+
// Output
|
|
35
|
+
type ActionCreator<Handler extends ActionHandler<any, any>> =
|
|
36
|
+
undefined extends SecondArgument<Handler>
|
|
37
|
+
? () => Action<string>
|
|
38
|
+
: (payload: SecondArgument<Handler>) => Action<string> & { payload: SecondArgument<Handler> };
|
|
39
|
+
|
|
40
|
+
type ActionCreatorMap<Actions extends ActionMap<any>> = {
|
|
41
|
+
[name in keyof Actions]: ActionCreator<Actions[name]>;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
type EffectsCreatorMap<GlobalState, ExtraArgument, Map extends EffectsMap<GlobalState, ExtraArgument>> = {
|
|
45
|
+
[key in keyof ReturnType<Map>]: undefined extends FirstArgument<ReturnType<Map>[key]>
|
|
46
|
+
? () => Action
|
|
47
|
+
: (payload: FirstArgument<ReturnType<Map>[key]>) => Action;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Transformation
|
|
51
|
+
const createActionCreator = (type: string) => (payload?: any) => (payload === undefined ? { type } : { type, payload });
|
|
52
|
+
const createEffectCreator = (type: string) => (payload: any) => ({ type, payload });
|
|
53
|
+
|
|
54
|
+
const createReducer = <BlockState>(prefix: string, initial: BlockState, actionMap: ActionMap<BlockState>): Reducer => {
|
|
55
|
+
const actions: ActionMap<BlockState> = appendPrefix(prefix + "/", bindAll(actionMap));
|
|
56
|
+
return (state: BlockState = initial, action?: AnyAction) => {
|
|
57
|
+
if (action && action.type) {
|
|
58
|
+
const handler: (state: BlockState, payload?: any) => BlockState = actions[action.type];
|
|
59
|
+
if (handler) {
|
|
60
|
+
return handler(state, action.payload);
|
|
61
|
+
} else {
|
|
62
|
+
return state;
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
return state;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
type MiddlewareCreator<T> = T extends undefined ? () => Middleware : (argument: T) => Middleware;
|
|
71
|
+
|
|
72
|
+
const createMiddlewareCreator = <GlobalState, ExtraArgument>(
|
|
73
|
+
prefix: string,
|
|
74
|
+
effectsMap: EffectsMap<GlobalState, ExtraArgument>,
|
|
75
|
+
): MiddlewareCreator<ExtraArgument> =>
|
|
76
|
+
((argument: ExtraArgument) => (store: MiddlewareAPI) => {
|
|
77
|
+
const effects = appendPrefix(prefix + "/", bindAll(effectsMap(store.dispatch, store.getState)));
|
|
78
|
+
return (next: Dispatch) => (action: Action<string> & { payload: any[] }) => {
|
|
79
|
+
if (action && Object.prototype.hasOwnProperty.call(effects, action.type)) {
|
|
80
|
+
effects[action.type](action.payload, argument);
|
|
81
|
+
} else {
|
|
82
|
+
next(action);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}) as MiddlewareCreator<ExtraArgument>;
|
|
86
|
+
|
|
87
|
+
const fail = (): never => {
|
|
88
|
+
throw new Error("Can't have access to 'dispatch' and 'getState' during initialization");
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const createReduxBlock =
|
|
92
|
+
<GlobalState, ExtraArgument = undefined>() =>
|
|
93
|
+
<
|
|
94
|
+
Name extends keyof GlobalState & string,
|
|
95
|
+
Actions extends ActionMap<GlobalState[Name]>,
|
|
96
|
+
Effects extends EffectsMap<GlobalState, ExtraArgument>,
|
|
97
|
+
>({
|
|
98
|
+
name,
|
|
99
|
+
initial,
|
|
100
|
+
actions,
|
|
101
|
+
effects,
|
|
102
|
+
}: {
|
|
103
|
+
name: Name;
|
|
104
|
+
initial: GlobalState[Name];
|
|
105
|
+
actions: Actions;
|
|
106
|
+
effects?: Effects;
|
|
107
|
+
}): {
|
|
108
|
+
name: Name;
|
|
109
|
+
reducer: Reducer<GlobalState[Name]>;
|
|
110
|
+
actions: ActionCreatorMap<Actions> & EffectsCreatorMap<GlobalState, ExtraArgument, Effects>;
|
|
111
|
+
} & ({} extends ReturnType<Effects> ? {} : { createMiddleware: MiddlewareCreator<ExtraArgument> }) => {
|
|
112
|
+
const actionCreators = Object.keys(actions).reduce((r, key) => {
|
|
113
|
+
r[key] = createActionCreator(`${name}/${key}`);
|
|
114
|
+
return r;
|
|
115
|
+
}, {} as any);
|
|
116
|
+
const effectCreators = Object.keys(effects ? effects(fail, fail) : {}).reduce((r, key) => {
|
|
117
|
+
r[key] = createEffectCreator(`${name}/${key}`);
|
|
118
|
+
return r;
|
|
119
|
+
}, {} as any);
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
name,
|
|
123
|
+
reducer: createReducer(name as string, initial, actions),
|
|
124
|
+
createMiddleware: effects
|
|
125
|
+
? createMiddlewareCreator<GlobalState, ExtraArgument>(name as string, effects)
|
|
126
|
+
: ((() => (_: MiddlewareAPI) => (next: Dispatch) => next) as MiddlewareCreator<ExtraArgument>),
|
|
127
|
+
actions: {
|
|
128
|
+
...actionCreators,
|
|
129
|
+
...effectCreators,
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
};
|
package/tsconfig.json
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"strict": true,
|
|
4
|
-
"noImplicitAny": true,
|
|
5
|
-
"moduleResolution": "
|
|
6
|
-
"module": "
|
|
7
|
-
"outDir": "build",
|
|
8
|
-
"sourceMap": true,
|
|
9
|
-
"declaration": true,
|
|
10
|
-
"target": "
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"strict": true,
|
|
4
|
+
"noImplicitAny": true,
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"outDir": "build",
|
|
8
|
+
"sourceMap": true,
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"target": "ESNext",
|
|
11
|
+
"types": ["vitest/globals"]
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/*.ts"]
|
|
14
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defineConfig } from "vitest/config";
|
|
2
|
+
import dts from "vite-plugin-dts";
|
|
3
|
+
import { resolve } from "path";
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
build: {
|
|
7
|
+
lib: {
|
|
8
|
+
entry: resolve(__dirname, "src/redux-sacala.ts"),
|
|
9
|
+
name: "ReduxSacala",
|
|
10
|
+
fileName: "redux-sacala",
|
|
11
|
+
formats: ["es", "cjs"],
|
|
12
|
+
},
|
|
13
|
+
outDir: "build",
|
|
14
|
+
rollupOptions: {
|
|
15
|
+
external: ["redux"],
|
|
16
|
+
output: {
|
|
17
|
+
globals: {
|
|
18
|
+
redux: "Redux",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
plugins: [dts({ rollupTypes: true })],
|
|
24
|
+
test: {
|
|
25
|
+
globals: true,
|
|
26
|
+
environment: "node",
|
|
27
|
+
exclude: ["**/node_modules/**", "**/build/**"],
|
|
28
|
+
},
|
|
29
|
+
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"redux-sacala.js","sourceRoot":"","sources":["../src/redux-sacala.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { createStore, combineReducers, applyMiddleware, } from "redux";
|
|
2
|
-
import { createReduxBlock } from "./redux-sacala";
|
|
3
|
-
const { actions: local, reducer: localReducer, createMiddleware: createLocalMiddleware, } = createReduxBlock()({
|
|
4
|
-
name: "local",
|
|
5
|
-
initial: { count: 0 },
|
|
6
|
-
actions: {
|
|
7
|
-
inc(state) {
|
|
8
|
-
return { count: state.count + 1 };
|
|
9
|
-
},
|
|
10
|
-
set(_, count) {
|
|
11
|
-
return { count };
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
effects: (dispatch, getState) => {
|
|
15
|
-
return {
|
|
16
|
-
incEffect() {
|
|
17
|
-
dispatch(local.inc());
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
function createMyStore() {
|
|
23
|
-
return createStore(combineReducers({
|
|
24
|
-
local: localReducer,
|
|
25
|
-
}), applyMiddleware(createLocalMiddleware(100)));
|
|
26
|
-
}
|
|
27
|
-
let store = createMyStore();
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
store = createMyStore();
|
|
30
|
-
});
|
|
31
|
-
describe("Store with reducer and middleware", () => {
|
|
32
|
-
it("Should be updated on action without payload", () => {
|
|
33
|
-
store.dispatch(local.inc());
|
|
34
|
-
store.dispatch(local.inc());
|
|
35
|
-
expect(store.getState()).toEqual({ local: { count: 2 } });
|
|
36
|
-
});
|
|
37
|
-
it("Should be updated on action with payload", () => {
|
|
38
|
-
store.dispatch(local.set(12));
|
|
39
|
-
expect(store.getState()).toEqual({ local: { count: 12 } });
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
//# sourceMappingURL=redux-sacala.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"redux-sacala.spec.js","sourceRoot":"","sources":["../src/redux-sacala.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EACX,eAAe,EACf,eAAe,GAClB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAUlD,MAAM,EACF,OAAO,EAAE,KAAK,EACd,OAAO,EAAE,YAAY,EACrB,gBAAgB,EAAE,qBAAqB,GAC1C,GAAG,gBAAgB,EAAmB,CAAC;IACpC,IAAI,EAAE,OAAO;IACb,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE;IACrB,OAAO,EAAE;QACL,GAAG,CAAC,KAAK;YACL,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;QACtC,CAAC;QACD,GAAG,CAAC,CAAC,EAAE,KAAa;YAChB,OAAO,EAAE,KAAK,EAAE,CAAC;QACrB,CAAC;KACJ;IACD,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE;QAC5B,OAAO;YACH,SAAS;gBACL,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;YAC1B,CAAC;SACJ,CAAC;IACN,CAAC;CACJ,CAAC,CAAC;AAEH,SAAS,aAAa;IAClB,OAAO,WAAW,CAAC,eAAe,CAAC;QAC/B,KAAK,EAAE,YAAY;KACtB,CAAC,EAAE,eAAe,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,IAAI,KAAK,GAAG,aAAa,EAAE,CAAC;AAE5B,UAAU,CAAC,GAAG,EAAE;IACZ,KAAK,GAAG,aAAa,EAAE,CAAC;AAC5B,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACnD,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5B,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5B,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAChD,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|