redux-sacala 0.2.2 → 0.3.1

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,30 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Use Node.js
15
+ uses: actions/setup-node@v4
16
+ with:
17
+ node-version: '20'
18
+ cache: 'npm'
19
+
20
+ - name: Install dependencies
21
+ run: npm ci
22
+
23
+ - name: Lint
24
+ run: npm run lint
25
+
26
+ - name: Build
27
+ run: npm run build
28
+
29
+ - name: Test
30
+ run: npm test
package/README.md CHANGED
@@ -1,134 +1,134 @@
1
- # redux-sacala
1
+ # Redux Sacala
2
2
 
3
- A lightweight utility to create Redux blocks with minimal boilerplate, featuring type-safe actions, reducers, and side effects.
3
+ A library for creating composable Redux blocks with state, actions, and effects.
4
4
 
5
- ## Features
5
+ ## Terms Definition
6
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.
7
+ - **ReduxBlock**: A composable unit of Redux logic that encapsulates state, action creators, and effect handlers. It provides a structured way to define how state changes and how side effects are handled.
8
+ - **Action**: A pure function that describes how the state changes in response to an event. In `redux-sacala`, actions are defined using `.action()` and they also serve as action creators.
9
+ - **Effect**: A non-pure handler that can perform side effects such as asynchronous API calls, logging, or dispatching other actions. Effects are defined using `.effects()` and have access to a context object providing necessary dependencies.
12
10
 
13
- ## Installation
11
+ ## Examples
14
12
 
15
- ```bash
16
- npm install redux-sacala
17
- ```
13
+ ### Simple Block with Actions
14
+
15
+ ```typescript
16
+ import { ReduxBlock } from "redux-sacala";
18
17
 
19
- *Note: `redux` is a peer dependency.*
18
+ const counterBlock = ReduxBlock.builder("counter", 0)
19
+ .action("inc", (state: number) => state + 1)
20
+ .action("add", (state: number, value: number) => state + value)
21
+ .build();
20
22
 
21
- ## Usage Example
23
+ // Usage:
24
+ // counterBlock.actions.inc() -> { type: "counter/inc" }
25
+ // counterBlock.actions.add(5) -> { type: "counter/add", payload: [5] }
26
+ ```
22
27
 
23
- ### 1. Create a Redux Block
28
+ ### Block with Effects
24
29
 
25
30
  ```typescript
26
- import { createReduxBlock } from 'redux-sacala';
27
-
28
- interface CounterState {
29
- count: number;
30
- }
31
+ interface User { id: string; name: string; }
31
32
 
32
- interface RootState {
33
- counter: CounterState;
33
+ interface UserContext {
34
+ fetchUser: (id: string) => Promise<User>;
35
+ dispatch: (action: any) => void;
34
36
  }
35
37
 
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 };
38
+ const userBlock = ReduxBlock.builder("user", { data: null as User | null, loading: false })
39
+ .action("setLoading", (state, loading: boolean) => ({ ...state, loading }))
40
+ .action("setData", (state, data: User) => ({ ...state, data, loading: false }))
41
+ .effects((ctx: UserContext) => ({
42
+ loadUser: async (id: string) => {
43
+ ctx.dispatch(userBlock.actions.setLoading(true));
44
+ const data = await ctx.fetchUser(id);
45
+ ctx.dispatch(userBlock.actions.setData(data));
46
+ }
47
+ }))
48
+ .build();
64
49
  ```
65
50
 
66
- ### 2. Configure the Store
51
+ ### Blocks Composition
67
52
 
68
53
  ```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
- });
54
+ const rootBlock = ReduxBlock.composition("root")
55
+ .block("counter", counterBlock)
56
+ .block("user", userBlock)
57
+ .build();
80
58
 
81
- const store = createStore(
82
- rootReducer,
83
- applyMiddleware(counterMiddleware)
84
- );
59
+ // rootBlock.actions.counter.inc()
60
+ // rootBlock.actions.user.loadUser("123")
85
61
  ```
86
62
 
87
- ### 3. Dispatch Actions
63
+ ### Blocks Composition with an Extra Effect
88
64
 
89
65
  ```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
66
+ const rootBlock = ReduxBlock.composition("root")
67
+ .block("counter", counterBlock)
68
+ .effects((ctx: { logger: (msg: string) => void, dispatch: (a: any) => void }) => ({
69
+ logAndIncrement: () => {
70
+ ctx.logger("Incrementing counter");
71
+ ctx.dispatch(rootBlock.actions.counter.inc());
72
+ }
73
+ }))
74
+ .build();
75
+
76
+ // Usage:
77
+ // rootBlock.actions.counter.inc()
78
+ // rootBlock.actions.counter.add(5)
79
+ // rootBlock.actions.logAndIncrement()
94
80
  ```
95
81
 
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.
82
+ ### Context Mapping
101
83
 
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`.
84
+ You can change the context shape of a block using `ReduxBlock.mapContext`. This is useful when you want to adapt a block to a different environment or use a more convenient context structure.
109
85
 
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
86
+ ```typescript
87
+ interface OldContext {
88
+ log: {
89
+ error: (msg: string) => void;
90
+ info: (msg: string) => void;
91
+ };
92
+ }
117
93
 
118
- ```bash
119
- # Install dependencies
120
- npm install
94
+ const block = ReduxBlock.builder("test", { message: "" })
95
+ .effects((ctx: OldContext) => ({
96
+ logError: (msg: string) => ctx.log.error(msg),
97
+ }))
98
+ .build();
121
99
 
122
- # Run tests
123
- npm test
100
+ interface NewContext {
101
+ log: (level: "error" | "info", msg: string) => void;
102
+ }
124
103
 
125
- # Build the project
126
- npm run build
104
+ const mappedBlock = ReduxBlock.mapContext(
105
+ block,
106
+ (ctx: NewContext): OldContext => ({
107
+ log: {
108
+ error: (msg) => ctx.log("error", msg),
109
+ info: (msg) => ctx.log("info", msg),
110
+ },
111
+ }),
112
+ );
127
113
 
128
- # Lint the code
129
- npm run lint
114
+ // Now mappedBlock expects NewContext
130
115
  ```
131
116
 
132
- ## License
117
+ ### Minimal Redux Toolkit Example
133
118
 
134
- Author: Andrey Monkin (monkin.andrey@gmail.com)
119
+ ```typescript
120
+ import { configureStore } from '@reduxjs/toolkit';
121
+ import { ReduxBlock } from "redux-sacala";
122
+
123
+ const store = configureStore({
124
+ reducer: rootBlock.reducer,
125
+ middleware: (getDefaultMiddleware) =>
126
+ getDefaultMiddleware().concat(
127
+ ReduxBlock.middleware(rootBlock, {
128
+ dispatch: (action) => store.dispatch(action),
129
+ logger: console.log,
130
+ fetchUser: async (id) => ({ id, name: "John Doe" })
131
+ })
132
+ ),
133
+ });
134
+ ```
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=e=>{const r={};for(const c in e)r[c]=e[c].bind(e);return r},a=(e,r)=>{const c={};for(const n in r)c[e+n]=r[n];return c},l=e=>r=>r===void 0?{type:e}:{type:e,payload:r},p=e=>r=>({type:e,payload:r}),f=(e,r,c)=>{const n=a(e+"/",u(c));return(o=r,s)=>{if(s&&s.type){const t=n[s.type];return t?t(o,s.payload):o}else return o}},y=(e,r)=>(c=>n=>{const o=a(e+"/",u(r(n.dispatch,n.getState)));return s=>t=>{t&&Object.prototype.hasOwnProperty.call(o,t.type)?o[t.type](t.payload,c):s(t)}}),i=()=>{throw new Error("Can't have access to 'dispatch' and 'getState' during initialization")},b=()=>({name:e,initial:r,actions:c,effects:n})=>{const o=Object.keys(c).reduce((t,d)=>(t[d]=l(`${e}/${d}`),t),{}),s=Object.keys(n?n(i,i):{}).reduce((t,d)=>(t[d]=p(`${e}/${d}`),t),{});return{name:e,reducer:f(e,r,c),createMiddleware:n?y(e,n):(()=>t=>d=>d),actions:{...o,...s}}};exports.createReduxBlock=b;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function d(o,e){return typeof o=="object"&&o!==null&&Object.hasOwn(o,e)}const f=o=>new Proxy({},{get(e,t){return d(e,t)?e[t]:(...r)=>{const s=`${o}/${t}`;return r.length?{type:s,payload:r}:{type:s}}}});class l{constructor(e,t,r,s){this.name=e,this.initial=t,this.reducers=r,this.handlers=s}static init(e,t){return new l(e,t,{},[])}action(e,t){return this.reducers[`${this.name}/${e}`]=t,this}effects(e){return this.handlers.push(e),this}build(){const e=this.initial,t=this.name;return{actions:f(this.name),effects:r=>this.handlers.reduce((s,i)=>Object.assign(s,Object.fromEntries(Object.entries(i(r)).map(([n,u])=>[`${t}/${n}`,u]))),{}),reducer:(r=e,s)=>{const i=this.reducers[s.type];if(!i)return r;const n="payload"in s?s.payload:void 0;return n&&n.length?i(r,...n):i(r)}}}}class a{constructor(e){this.name=e,this.creators=f(e)}blocks={};handlers=[];creators;static init(e){return new a(e)}block(e,t){return this.blocks[e]=t,this.creators[e]=t.actions,this}effects(e){return this.handlers.push(e),this}build(){const e=Object.entries(this.blocks).map(([t,r])=>[t,r.reducer]);return{actions:this.creators,effects:t=>{const r=this.name,s=this.handlers.reduce((i,n)=>Object.assign(i,Object.fromEntries(Object.entries(n(t)).map(([u,c])=>[`${r}/${u}`,c]))),{});return Object.values(this.blocks).forEach(i=>Object.assign(s,i.effects(t))),s},reducer:(t,r)=>{let s=t,i=!1;return e.forEach(([n,u])=>{const c=t?.[n],h=u(c,r);h!==c&&(i||(i=!0,s={...t}),s[n]=h)}),s}}}}exports.ReduxBlock=void 0;(o=>{function e(s,i){return l.init(s,i)}o.builder=e;function t(s){return a.init(s)}o.composition=t;function r(s,i){const n=s.effects(i);return()=>u=>c=>{c&&typeof c=="object"&&"type"in c&&d(n,c.type)&&n[c.type](..."payload"in c?c.payload:[]),u(c)}}o.middleware=r})(exports.ReduxBlock||(exports.ReduxBlock={}));
2
2
  //# sourceMappingURL=redux-sacala.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"redux-sacala.cjs","sources":["../src/redux-sacala.ts"],"sourcesContent":["import { Dispatch, Action, Reducer, Middleware, AnyAction, MiddlewareAPI } from \"redux\";\n\ntype UnknownToUndefined<T> = unknown extends T ? undefined : T;\n\ntype FirstArgument<F> = F extends (arg1: infer U, ...args: any[]) => any ? UnknownToUndefined<U> : undefined;\ntype SecondArgument<F> = F extends (arg1: any, arg2: infer U, ...args: any[]) => any\n ? UnknownToUndefined<U>\n : undefined;\n\nconst bindAll = <T extends { [key: string]: Function }>(map: T): T => {\n const result = {} as any as T;\n for (const i in map) {\n result[i] = map[i].bind(map);\n }\n return result;\n};\n\nconst appendPrefix = <T>(prefix: string, map: { [key: string]: T }) => {\n const r: { [key: string]: any } = {};\n for (const i in map) {\n r[prefix + i] = map[i];\n }\n return r;\n};\n\n// Input\ntype ActionHandler<BlockState, Payload> = (state: BlockState, payload: Payload) => BlockState;\ntype ActionMap<BlockState> = { [action: string]: ActionHandler<BlockState, any> };\ntype EffectsMap<GlobalState, ExtraArgument> = (\n dispatch: Dispatch,\n getState: () => GlobalState,\n) => { [effect: string]: (payload: any, extraArgument: ExtraArgument) => any };\n\n// Output\ntype ActionCreator<Handler extends ActionHandler<any, any>> =\n undefined extends SecondArgument<Handler>\n ? () => Action<string>\n : (payload: SecondArgument<Handler>) => Action<string> & { payload: SecondArgument<Handler> };\n\ntype ActionCreatorMap<Actions extends ActionMap<any>> = {\n [name in keyof Actions]: ActionCreator<Actions[name]>;\n};\n\ntype EffectsCreatorMap<GlobalState, ExtraArgument, Map extends EffectsMap<GlobalState, ExtraArgument>> = {\n [key in keyof ReturnType<Map>]: undefined extends FirstArgument<ReturnType<Map>[key]>\n ? () => Action\n : (payload: FirstArgument<ReturnType<Map>[key]>) => Action;\n};\n\n// Transformation\nconst createActionCreator = (type: string) => (payload?: any) => (payload === undefined ? { type } : { type, payload });\nconst createEffectCreator = (type: string) => (payload: any) => ({ type, payload });\n\nconst createReducer = <BlockState>(prefix: string, initial: BlockState, actionMap: ActionMap<BlockState>): Reducer => {\n const actions: ActionMap<BlockState> = appendPrefix(prefix + \"/\", bindAll(actionMap));\n return (state: BlockState = initial, action?: AnyAction) => {\n if (action && action.type) {\n const handler: (state: BlockState, payload?: any) => BlockState = actions[action.type];\n if (handler) {\n return handler(state, action.payload);\n } else {\n return state;\n }\n } else {\n return state;\n }\n };\n};\n\ntype MiddlewareCreator<T> = T extends undefined ? () => Middleware : (argument: T) => Middleware;\n\nconst createMiddlewareCreator = <GlobalState, ExtraArgument>(\n prefix: string,\n effectsMap: EffectsMap<GlobalState, ExtraArgument>,\n): MiddlewareCreator<ExtraArgument> =>\n ((argument: ExtraArgument) => (store: MiddlewareAPI) => {\n const effects = appendPrefix(prefix + \"/\", bindAll(effectsMap(store.dispatch, store.getState)));\n return (next: Dispatch) => (action: Action<string> & { payload: any[] }) => {\n if (action && Object.prototype.hasOwnProperty.call(effects, action.type)) {\n effects[action.type](action.payload, argument);\n } else {\n next(action);\n }\n };\n }) as MiddlewareCreator<ExtraArgument>;\n\nconst fail = (): never => {\n throw new Error(\"Can't have access to 'dispatch' and 'getState' during initialization\");\n};\n\nexport const createReduxBlock =\n <GlobalState, ExtraArgument = undefined>() =>\n <\n Name extends keyof GlobalState & string,\n Actions extends ActionMap<GlobalState[Name]>,\n Effects extends EffectsMap<GlobalState, ExtraArgument>,\n >({\n name,\n initial,\n actions,\n effects,\n }: {\n name: Name;\n initial: GlobalState[Name];\n actions: Actions;\n effects?: Effects;\n }): {\n name: Name;\n reducer: Reducer<GlobalState[Name]>;\n actions: ActionCreatorMap<Actions> & EffectsCreatorMap<GlobalState, ExtraArgument, Effects>;\n } & ({} extends ReturnType<Effects> ? {} : { createMiddleware: MiddlewareCreator<ExtraArgument> }) => {\n const actionCreators = Object.keys(actions).reduce((r, key) => {\n r[key] = createActionCreator(`${name}/${key}`);\n return r;\n }, {} as any);\n const effectCreators = Object.keys(effects ? effects(fail, fail) : {}).reduce((r, key) => {\n r[key] = createEffectCreator(`${name}/${key}`);\n return r;\n }, {} as any);\n\n return {\n name,\n reducer: createReducer(name as string, initial, actions),\n createMiddleware: effects\n ? createMiddlewareCreator<GlobalState, ExtraArgument>(name as string, effects)\n : ((() => (_: MiddlewareAPI) => (next: Dispatch) => next) as MiddlewareCreator<ExtraArgument>),\n actions: {\n ...actionCreators,\n ...effectCreators,\n },\n };\n };\n"],"names":["bindAll","map","result","i","appendPrefix","prefix","r","createActionCreator","type","payload","createEffectCreator","createReducer","initial","actionMap","actions","state","action","handler","createMiddlewareCreator","effectsMap","argument","store","effects","next","fail","createReduxBlock","name","actionCreators","key","effectCreators","_"],"mappings":"gFASA,MAAMA,EAAkDC,GAAc,CAClE,MAAMC,EAAS,CAAA,EACf,UAAWC,KAAKF,EACZC,EAAOC,CAAC,EAAIF,EAAIE,CAAC,EAAE,KAAKF,CAAG,EAE/B,OAAOC,CACX,EAEME,EAAe,CAAIC,EAAgBJ,IAA8B,CACnE,MAAMK,EAA4B,CAAA,EAClC,UAAWH,KAAKF,EACZK,EAAED,EAASF,CAAC,EAAIF,EAAIE,CAAC,EAEzB,OAAOG,CACX,EA2BMC,EAAuBC,GAAkBC,GAAmBA,IAAY,OAAY,CAAE,KAAAD,CAAA,EAAS,CAAE,KAAAA,EAAM,QAAAC,CAAA,EACvGC,EAAuBF,GAAkBC,IAAkB,CAAE,KAAAD,EAAM,QAAAC,IAEnEE,EAAgB,CAAaN,EAAgBO,EAAqBC,IAA8C,CAClH,MAAMC,EAAiCV,EAAaC,EAAS,IAAKL,EAAQa,CAAS,CAAC,EACpF,MAAO,CAACE,EAAoBH,EAASI,IAAuB,CACxD,GAAIA,GAAUA,EAAO,KAAM,CACvB,MAAMC,EAA4DH,EAAQE,EAAO,IAAI,EACrF,OAAIC,EACOA,EAAQF,EAAOC,EAAO,OAAO,EAE7BD,CAEf,KACI,QAAOA,CAEf,CACJ,EAIMG,EAA0B,CAC5Bb,EACAc,KAEEC,GAA6BC,GAAyB,CACpD,MAAMC,EAAUlB,EAAaC,EAAS,IAAKL,EAAQmB,EAAWE,EAAM,SAAUA,EAAM,QAAQ,CAAC,CAAC,EAC9F,OAAQE,GAAoBP,GAAgD,CACpEA,GAAU,OAAO,UAAU,eAAe,KAAKM,EAASN,EAAO,IAAI,EACnEM,EAAQN,EAAO,IAAI,EAAEA,EAAO,QAASI,CAAQ,EAE7CG,EAAKP,CAAM,CAEnB,CACJ,GAEEQ,EAAO,IAAa,CACtB,MAAM,IAAI,MAAM,sEAAsE,CAC1F,EAEaC,EACT,IACA,CAIE,CACE,KAAAC,EACA,QAAAd,EACA,QAAAE,EACA,QAAAQ,CACJ,IASsG,CAClG,MAAMK,EAAiB,OAAO,KAAKb,CAAO,EAAE,OAAO,CAACR,EAAGsB,KACnDtB,EAAEsB,CAAG,EAAIrB,EAAoB,GAAGmB,CAAI,IAAIE,CAAG,EAAE,EACtCtB,GACR,CAAA,CAAS,EACNuB,EAAiB,OAAO,KAAKP,EAAUA,EAAQE,EAAMA,CAAI,EAAI,CAAA,CAAE,EAAE,OAAO,CAAClB,EAAGsB,KAC9EtB,EAAEsB,CAAG,EAAIlB,EAAoB,GAAGgB,CAAI,IAAIE,CAAG,EAAE,EACtCtB,GACR,CAAA,CAAS,EAEZ,MAAO,CACH,KAAAoB,EACA,QAASf,EAAce,EAAgBd,EAASE,CAAO,EACvD,iBAAkBQ,EACZJ,EAAoDQ,EAAgBJ,CAAO,GACzE,IAAOQ,GAAsBP,GAAmBA,GACxD,QAAS,CACL,GAAGI,EACH,GAAGE,CAAA,CACP,CAER"}
1
+ {"version":3,"file":"redux-sacala.cjs","sources":["../src/redux-sacala.ts"],"sourcesContent":["import { Middleware, Reducer, UnknownAction } from \"redux\";\n\n/**\n * Composable Redux block with state description, action creators, and effects handlers.\n * Use `ReduxBlock.builder` to start building a new block.\n */\nexport interface ReduxBlock<State, Creators, Context> {\n /**\n * Action creators for this block.\n * When composed, action creators can form a folder tree structure.\n */\n actions: Creators;\n /**\n * Reducer that can be used directly in Redux store configuration.\n */\n reducer: Reducer<State, UnknownAction>;\n /**\n * Effects to be called on effects actions.\n * Use `ReduxBlock.middleware` to create middleware for effects processing.\n */\n effects: Effects<Context>;\n}\n\ntype PayloadAction<Type extends string, Payload extends unknown[]> = Payload extends never[]\n ? { type: Type }\n : { type: Type; payload: Payload };\n\n/**\n * Checks if the given key exists directly on the provided object.\n */\nfunction has<K extends string | symbol>(v: unknown, k: K): v is Record<K, unknown> {\n return typeof v === \"object\" && v !== null && Object.hasOwn(v, k);\n}\n\nconst creator = (scope: string) =>\n new Proxy(\n {},\n {\n get(target, property) {\n if (has(target, property)) {\n return target[property];\n }\n\n return (...payload: unknown[]) => {\n const type = `${scope}/${property as string}`;\n return payload.length ? { type, payload } : { type };\n };\n },\n },\n ) as Record<string, (...payload: unknown[]) => UnknownAction>;\n\n/**\n * Effects creator. It receives context with side effect APIs and returns non-pure handlers.\n */\ntype Effects<Context> = (context: Context) => Record<string, (...payload: any[]) => void>;\n\n/**\n * Convert effects type to action creators.\n */\ntype EffectsToCreators<Name extends string, E extends Effects<any>> = {\n [K in keyof ReturnType<E>]: (\n ...parameters: Parameters<ReturnType<E>[K]>\n ) => PayloadAction<`${Name}/${K extends string ? K : never}`, Parameters<ReturnType<E>[K]>>;\n};\n\nclass BlockBuilder<\n Name extends string,\n State,\n Creators extends Record<string, (...parameters: unknown[]) => PayloadAction<any, any>>,\n Context,\n> {\n private constructor(\n readonly name: Name,\n readonly initial: State,\n /**\n * Per-message action reducers for this block.\n */\n private readonly reducers: Record<string, (state: State, ...payload: unknown[]) => State>,\n /**\n * Effects handlers for this block.\n */\n private readonly handlers: Effects<Context>[],\n ) {}\n\n static init<Name extends string, State>(name: Name, initial: State): BlockBuilder<Name, State, {}, {}> {\n return new BlockBuilder(name, initial, {}, []);\n }\n\n /**\n * Append an action handler to the block.\n * Action is a pure function that takes the state + arguments and returns a new state.\n */\n action<Action extends string, Payload extends unknown[] = []>(\n action: Action,\n handler: (state: State, ...payload: Payload) => State,\n ): BlockBuilder<\n Name,\n State,\n Creators & Record<Action, (...payload: Payload) => PayloadAction<`${Name}/${Action}`, Payload>>,\n Context\n > {\n this.reducers[`${this.name}/${action}`] = handler as (state: State, ...payload: unknown[]) => State;\n return this as any;\n }\n\n /**\n * Append effect handlers to the block.\n * Effects can call any side effects provided from the context.\n */\n effects<E extends Effects<any>>(\n effects: E,\n ): BlockBuilder<\n Name,\n State,\n Creators & EffectsToCreators<Name, E>,\n Context & (E extends Effects<infer C> ? C : never)\n > {\n this.handlers.push(effects);\n return this as any;\n }\n\n build(): ReduxBlock<State, Creators, Context> {\n const initialState = this.initial;\n const blockName = this.name;\n return {\n actions: creator(this.name),\n effects: (context: Context) =>\n this.handlers.reduce(\n (acc, effect) =>\n Object.assign(\n acc,\n Object.fromEntries(\n Object.entries(effect(context)).map(([effectName, handler]) => [\n `${blockName}/${effectName}`,\n handler,\n ]),\n ),\n ),\n {} as Record<string, (...payload: unknown[]) => void>,\n ),\n reducer: (state = initialState, action: UnknownAction) => {\n const handler = this.reducers[action.type];\n if (!handler) return state;\n const payload = \"payload\" in action ? (action.payload as unknown[]) : undefined;\n return payload && payload.length ? handler(state, ...payload) : handler(state);\n },\n } as any;\n }\n}\n\nclass CompositionBuilder<\n Name extends string,\n BlockMap extends Record<string, ReduxBlock<any, any, any>>,\n Creators,\n Context,\n> {\n private blocks: BlockMap = {} as BlockMap;\n private handlers: Effects<Context>[] = [];\n private creators: Creators;\n\n private constructor(private name: Name) {\n this.creators = creator(name) as Creators;\n }\n\n static init<Name extends string>(name: Name): CompositionBuilder<Name, {}, {}, {}> {\n return new CompositionBuilder(name);\n }\n\n block<Name extends string, Block extends ReduxBlock<any, any, any>>(\n name: Name,\n block: Block,\n ): CompositionBuilder<\n Name,\n BlockMap & Record<Name, Block>,\n Creators & Record<Name, ReduxBlock.TakeCreators<Block>>,\n Context & ReduxBlock.TakeContext<Block>\n > {\n (this.blocks as Record<string, ReduxBlock<any, any, any>>)[name] = block;\n (this.creators as Record<string, unknown>)[name] = block.actions;\n return this as any;\n }\n\n effects<E extends Effects<any>>(\n effects: E,\n ): CompositionBuilder<\n Name,\n BlockMap,\n Creators & EffectsToCreators<Name, E>,\n Context & (E extends Effects<infer ExtraContext> ? ExtraContext : never)\n > {\n (this.handlers as (Effects<Context> | E)[]).push(effects);\n return this as any;\n }\n\n build(): ReduxBlock<{ [K in keyof BlockMap]: ReduxBlock.TakeState<BlockMap[K]> }, Creators, Context> {\n const reducers = Object.entries(this.blocks).map(([name, block]) => [name, block.reducer] as const);\n return {\n actions: this.creators,\n effects: (context: Context) => {\n const blockName = this.name;\n const result = this.handlers.reduce(\n (acc, effect) =>\n Object.assign(\n acc,\n Object.fromEntries(\n Object.entries(effect(context)).map(([effectName, handler]) => [\n `${blockName}/${effectName}`,\n handler,\n ]),\n ),\n ),\n {} as Record<string, (...payload: unknown[]) => void>,\n );\n Object.values(this.blocks).forEach((block) => Object.assign(result, block.effects(context)));\n return result;\n },\n reducer: (state: any, action: UnknownAction) => {\n let result = state;\n let changed = false;\n reducers.forEach(([name, reducer]) => {\n const original = state?.[name];\n const updated = reducer(original, action);\n if (updated !== original) {\n if (!changed) {\n changed = true;\n result = { ...state };\n }\n result[name] = updated;\n }\n });\n return result;\n },\n } as any;\n }\n}\n\nexport namespace ReduxBlock {\n type AnyBlock = ReduxBlock<any, any, any>;\n\n export type TakeState<Block extends AnyBlock> = Block extends ReduxBlock<infer State, any, any> ? State : never;\n export type TakeCreators<Block extends AnyBlock> =\n Block extends ReduxBlock<any, infer Creators, any> ? Creators : never;\n export type TakeContext<Block extends AnyBlock> =\n Block extends ReduxBlock<any, any, infer Context> ? Context : never;\n\n /**\n * Create a block builder.\n * It's a starting point for creating a block.\n */\n export function builder<Name extends string, State>(name: Name, initial: State): BlockBuilder<Name, State, {}, {}> {\n return BlockBuilder.init(name, initial);\n }\n\n /**\n * Create a composition builder.\n */\n export function composition<Name extends string>(name: Name): CompositionBuilder<Name, {}, {}, {}> {\n return CompositionBuilder.init(name);\n }\n\n /**\n * Create middleware for effects processing.\n * It expects to receive a context object that provides necessary dependencies for effect handlers.\n */\n export function middleware<Block extends AnyBlock>(block: Block, context: TakeContext<Block>): Middleware {\n const effects = block.effects(context);\n return () => (next) => (action) => {\n if (action && typeof action === \"object\" && \"type\" in action && has(effects, action.type as string)) {\n effects[action.type as string](...(\"payload\" in action ? (action.payload as unknown[]) : []));\n }\n next(action);\n };\n }\n}\n"],"names":["has","v","k","creator","scope","target","property","payload","type","BlockBuilder","name","initial","reducers","handlers","action","handler","effects","initialState","blockName","context","acc","effect","effectName","state","CompositionBuilder","block","result","changed","reducer","original","updated","ReduxBlock","builder","composition","middleware","next"],"mappings":"gFA8BA,SAASA,EAA+BC,EAAYC,EAA+B,CAC/E,OAAO,OAAOD,GAAM,UAAYA,IAAM,MAAQ,OAAO,OAAOA,EAAGC,CAAC,CACpE,CAEA,MAAMC,EAAWC,GACb,IAAI,MACA,CAAA,EACA,CACI,IAAIC,EAAQC,EAAU,CAClB,OAAIN,EAAIK,EAAQC,CAAQ,EACbD,EAAOC,CAAQ,EAGnB,IAAIC,IAAuB,CAC9B,MAAMC,EAAO,GAAGJ,CAAK,IAAIE,CAAkB,GAC3C,OAAOC,EAAQ,OAAS,CAAE,KAAAC,EAAM,QAAAD,CAAA,EAAY,CAAE,KAAAC,CAAA,CAClD,CACJ,CAAA,CAER,EAgBJ,MAAMC,CAKJ,CACU,YACKC,EACAC,EAIQC,EAIAC,EACnB,CAVW,KAAA,KAAAH,EACA,KAAA,QAAAC,EAIQ,KAAA,SAAAC,EAIA,KAAA,SAAAC,CAClB,CAEH,OAAO,KAAiCH,EAAYC,EAAmD,CACnG,OAAO,IAAIF,EAAaC,EAAMC,EAAS,CAAA,EAAI,CAAA,CAAE,CACjD,CAMA,OACIG,EACAC,EAMF,CACE,YAAK,SAAS,GAAG,KAAK,IAAI,IAAID,CAAM,EAAE,EAAIC,EACnC,IACX,CAMA,QACIC,EAMF,CACE,YAAK,SAAS,KAAKA,CAAO,EACnB,IACX,CAEA,OAA8C,CAC1C,MAAMC,EAAe,KAAK,QACpBC,EAAY,KAAK,KACvB,MAAO,CACH,QAASf,EAAQ,KAAK,IAAI,EAC1B,QAAUgB,GACN,KAAK,SAAS,OACV,CAACC,EAAKC,IACF,OAAO,OACHD,EACA,OAAO,YACH,OAAO,QAAQC,EAAOF,CAAO,CAAC,EAAE,IAAI,CAAC,CAACG,EAAYP,CAAO,IAAM,CAC3D,GAAGG,CAAS,IAAII,CAAU,GAC1BP,CAAA,CACH,CAAA,CACL,EAER,CAAA,CAAC,EAET,QAAS,CAACQ,EAAQN,EAAcH,IAA0B,CACtD,MAAMC,EAAU,KAAK,SAASD,EAAO,IAAI,EACzC,GAAI,CAACC,EAAS,OAAOQ,EACrB,MAAMhB,EAAU,YAAaO,EAAUA,EAAO,QAAwB,OACtE,OAAOP,GAAWA,EAAQ,OAASQ,EAAQQ,EAAO,GAAGhB,CAAO,EAAIQ,EAAQQ,CAAK,CACjF,CAAA,CAER,CACJ,CAEA,MAAMC,CAKJ,CAKU,YAAoBd,EAAY,CAAZ,KAAA,KAAAA,EACxB,KAAK,SAAWP,EAAQO,CAAI,CAChC,CANQ,OAAmB,CAAA,EACnB,SAA+B,CAAA,EAC/B,SAMR,OAAO,KAA0BA,EAAkD,CAC/E,OAAO,IAAIc,EAAmBd,CAAI,CACtC,CAEA,MACIA,EACAe,EAMF,CACG,YAAK,OAAqDf,CAAI,EAAIe,EAClE,KAAK,SAAqCf,CAAI,EAAIe,EAAM,QAClD,IACX,CAEA,QACIT,EAMF,CACG,YAAK,SAAsC,KAAKA,CAAO,EACjD,IACX,CAEA,OAAqG,CACjG,MAAMJ,EAAW,OAAO,QAAQ,KAAK,MAAM,EAAE,IAAI,CAAC,CAACF,EAAMe,CAAK,IAAM,CAACf,EAAMe,EAAM,OAAO,CAAU,EAClG,MAAO,CACH,QAAS,KAAK,SACd,QAAUN,GAAqB,CAC3B,MAAMD,EAAY,KAAK,KACjBQ,EAAS,KAAK,SAAS,OACzB,CAACN,EAAKC,IACF,OAAO,OACHD,EACA,OAAO,YACH,OAAO,QAAQC,EAAOF,CAAO,CAAC,EAAE,IAAI,CAAC,CAACG,EAAYP,CAAO,IAAM,CAC3D,GAAGG,CAAS,IAAII,CAAU,GAC1BP,CAAA,CACH,CAAA,CACL,EAER,CAAA,CAAC,EAEL,cAAO,OAAO,KAAK,MAAM,EAAE,QAASU,GAAU,OAAO,OAAOC,EAAQD,EAAM,QAAQN,CAAO,CAAC,CAAC,EACpFO,CACX,EACA,QAAS,CAACH,EAAYT,IAA0B,CAC5C,IAAIY,EAASH,EACTI,EAAU,GACd,OAAAf,EAAS,QAAQ,CAAC,CAACF,EAAMkB,CAAO,IAAM,CAClC,MAAMC,EAAWN,IAAQb,CAAI,EACvBoB,EAAUF,EAAQC,EAAUf,CAAM,EACpCgB,IAAYD,IACPF,IACDA,EAAU,GACVD,EAAS,CAAE,GAAGH,CAAA,GAElBG,EAAOhB,CAAI,EAAIoB,EAEvB,CAAC,EACMJ,CACX,CAAA,CAER,CACJ,CAEiBK,QAAAA,WAAAA,QAAAA,GAAV,CAaI,SAASC,EAAoCtB,EAAYC,EAAmD,CAC/G,OAAOF,EAAa,KAAKC,EAAMC,CAAO,CAC1C,CAFOoB,EAAS,QAAAC,EAOT,SAASC,EAAiCvB,EAAkD,CAC/F,OAAOc,EAAmB,KAAKd,CAAI,CACvC,CAFOqB,EAAS,YAAAE,EAQT,SAASC,EAAmCT,EAAcN,EAAyC,CACtG,MAAMH,EAAUS,EAAM,QAAQN,CAAO,EACrC,MAAO,IAAOgB,GAAUrB,GAAW,CAC3BA,GAAU,OAAOA,GAAW,UAAY,SAAUA,GAAUd,EAAIgB,EAASF,EAAO,IAAc,GAC9FE,EAAQF,EAAO,IAAc,EAAE,GAAI,YAAaA,EAAUA,EAAO,QAAwB,EAAG,EAEhGqB,EAAKrB,CAAM,CACf,CACJ,CAROiB,EAAS,WAAAG,CAAA,GA5BHH,QAAAA,aAAAA,mBAAA,CAAA,EAAA"}
@@ -1,49 +1,107 @@
1
- import { Action } from 'redux';
2
- import { Dispatch } from 'redux';
3
1
  import { Middleware } from 'redux';
4
2
  import { Reducer } from 'redux';
3
+ import { UnknownAction } from 'redux';
5
4
 
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
- };
5
+ declare class BlockBuilder<Name extends string, State, Creators extends Record<string, (...parameters: unknown[]) => PayloadAction<any, any>>, Context> {
6
+ readonly name: Name;
7
+ readonly initial: State;
8
+ /**
9
+ * Per-message action reducers for this block.
10
+ */
11
+ private readonly reducers;
12
+ /**
13
+ * Effects handlers for this block.
14
+ */
15
+ private readonly handlers;
16
+ private constructor();
17
+ static init<Name extends string, State>(name: Name, initial: State): BlockBuilder<Name, State, {}, {}>;
18
+ /**
19
+ * Append an action handler to the block.
20
+ * Action is a pure function that takes the state + arguments and returns a new state.
21
+ */
22
+ action<Action extends string, Payload extends unknown[] = []>(action: Action, handler: (state: State, ...payload: Payload) => State): BlockBuilder<Name, State, Creators & Record<Action, (...payload: Payload) => PayloadAction<`${Name}/${Action}`, Payload>>, Context>;
23
+ /**
24
+ * Append effect handlers to the block.
25
+ * Effects can call any side effects provided from the context.
26
+ */
27
+ effects<E extends Effects<any>>(effects: E): BlockBuilder<Name, State, Creators & EffectsToCreators<Name, E>, Context & (E extends Effects<infer C> ? C : never)>;
28
+ build(): ReduxBlock<State, Creators, Context>;
29
+ }
13
30
 
14
- declare type ActionHandler<BlockState, Payload> = (state: BlockState, payload: Payload) => BlockState;
31
+ declare class CompositionBuilder<Name extends string, BlockMap extends Record<string, ReduxBlock<any, any, any>>, Creators, Context> {
32
+ private name;
33
+ private blocks;
34
+ private handlers;
35
+ private creators;
36
+ private constructor();
37
+ static init<Name extends string>(name: Name): CompositionBuilder<Name, {}, {}, {}>;
38
+ block<Name extends string, Block extends ReduxBlock<any, any, any>>(name: Name, block: Block): CompositionBuilder<Name, BlockMap & Record<Name, Block>, Creators & Record<Name, ReduxBlock.TakeCreators<Block>>, Context & ReduxBlock.TakeContext<Block>>;
39
+ effects<E extends Effects<any>>(effects: E): CompositionBuilder<Name, BlockMap, Creators & EffectsToCreators<Name, E>, Context & (E extends Effects<infer ExtraContext> ? ExtraContext : never)>;
40
+ build(): ReduxBlock<{
41
+ [K in keyof BlockMap]: ReduxBlock.TakeState<BlockMap[K]>;
42
+ }, Creators, Context>;
43
+ }
15
44
 
16
- declare type ActionMap<BlockState> = {
17
- [action: string]: ActionHandler<BlockState, any>;
18
- };
45
+ /**
46
+ * Effects creator. It receives context with side effect APIs and returns non-pure handlers.
47
+ */
48
+ declare type Effects<Context> = (context: Context) => Record<string, (...payload: any[]) => void>;
19
49
 
20
- export declare const 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;
50
+ /**
51
+ * Convert effects type to action creators.
52
+ */
53
+ declare type EffectsToCreators<Name extends string, E extends Effects<any>> = {
54
+ [K in keyof ReturnType<E>]: (...parameters: Parameters<ReturnType<E>[K]>) => PayloadAction<`${Name}/${K extends string ? K : never}`, Parameters<ReturnType<E>[K]>>;
35
55
  };
36
56
 
37
- declare type EffectsMap<GlobalState, ExtraArgument> = (dispatch: Dispatch, getState: () => GlobalState) => {
38
- [effect: string]: (payload: any, extraArgument: ExtraArgument) => any;
57
+ declare type PayloadAction<Type extends string, Payload extends unknown[]> = Payload extends never[] ? {
58
+ type: Type;
59
+ } : {
60
+ type: Type;
61
+ payload: Payload;
39
62
  };
40
63
 
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;
64
+ /**
65
+ * Composable Redux block with state description, action creators, and effects handlers.
66
+ * Use `ReduxBlock.builder` to start building a new block.
67
+ */
68
+ export declare interface ReduxBlock<State, Creators, Context> {
69
+ /**
70
+ * Action creators for this block.
71
+ * When composed, action creators can form a folder tree structure.
72
+ */
73
+ actions: Creators;
74
+ /**
75
+ * Reducer that can be used directly in Redux store configuration.
76
+ */
77
+ reducer: Reducer<State, UnknownAction>;
78
+ /**
79
+ * Effects to be called on effects actions.
80
+ * Use `ReduxBlock.middleware` to create middleware for effects processing.
81
+ */
82
+ effects: Effects<Context>;
83
+ }
46
84
 
47
- declare type UnknownToUndefined<T> = unknown extends T ? undefined : T;
85
+ export declare namespace ReduxBlock {
86
+ export type AnyBlock = ReduxBlock<any, any, any>;
87
+ export type TakeState<Block extends AnyBlock> = Block extends ReduxBlock<infer State, any, any> ? State : never;
88
+ export type TakeCreators<Block extends AnyBlock> = Block extends ReduxBlock<any, infer Creators, any> ? Creators : never;
89
+ export type TakeContext<Block extends AnyBlock> = Block extends ReduxBlock<any, any, infer Context> ? Context : never;
90
+ /**
91
+ * Create a block builder.
92
+ * It's a starting point for creating a block.
93
+ */
94
+ export function builder<Name extends string, State>(name: Name, initial: State): BlockBuilder<Name, State, {}, {}>;
95
+ /**
96
+ * Create a composition builder.
97
+ */
98
+ export function composition<Name extends string>(name: Name): CompositionBuilder<Name, {}, {}, {}>;
99
+ /**
100
+ * Create middleware for effects processing.
101
+ * It expects to receive a context object that provides necessary dependencies for effect handlers.
102
+ */
103
+ export function middleware<Block extends AnyBlock>(block: Block, context: TakeContext<Block>): Middleware;
104
+ {};
105
+ }
48
106
 
49
107
  export { }
@@ -1,47 +1,127 @@
1
- const u = (e) => {
2
- const r = {};
3
- for (const c in e)
4
- r[c] = e[c].bind(e);
5
- return r;
6
- }, a = (e, r) => {
7
- const c = {};
8
- for (const n in r)
9
- c[e + n] = r[n];
10
- return c;
11
- }, l = (e) => (r) => r === void 0 ? { type: e } : { type: e, payload: r }, p = (e) => (r) => ({ type: e, payload: r }), f = (e, r, c) => {
12
- const n = a(e + "/", u(c));
13
- return (o = r, s) => {
14
- if (s && s.type) {
15
- const t = n[s.type];
16
- return t ? t(o, s.payload) : o;
17
- } else
18
- return o;
19
- };
20
- }, h = (e, r) => ((c) => (n) => {
21
- const o = a(e + "/", u(r(n.dispatch, n.getState)));
22
- return (s) => (t) => {
23
- t && Object.prototype.hasOwnProperty.call(o, t.type) ? o[t.type](t.payload, c) : s(t);
24
- };
25
- }), i = () => {
26
- throw new Error("Can't have access to 'dispatch' and 'getState' during initialization");
27
- }, y = () => ({
28
- name: e,
29
- initial: r,
30
- actions: c,
31
- effects: n
32
- }) => {
33
- const o = Object.keys(c).reduce((t, d) => (t[d] = l(`${e}/${d}`), t), {}), s = Object.keys(n ? n(i, i) : {}).reduce((t, d) => (t[d] = p(`${e}/${d}`), t), {});
34
- return {
35
- name: e,
36
- reducer: f(e, r, c),
37
- createMiddleware: n ? h(e, n) : (() => (t) => (d) => d),
38
- actions: {
39
- ...o,
40
- ...s
1
+ function f(u, e) {
2
+ return typeof u == "object" && u !== null && Object.hasOwn(u, e);
3
+ }
4
+ const b = (u) => new Proxy(
5
+ {},
6
+ {
7
+ get(e, t) {
8
+ return f(e, t) ? e[t] : (...r) => {
9
+ const s = `${u}/${t}`;
10
+ return r.length ? { type: s, payload: r } : { type: s };
11
+ };
41
12
  }
42
- };
43
- };
13
+ }
14
+ );
15
+ class h {
16
+ constructor(e, t, r, s) {
17
+ this.name = e, this.initial = t, this.reducers = r, this.handlers = s;
18
+ }
19
+ static init(e, t) {
20
+ return new h(e, t, {}, []);
21
+ }
22
+ /**
23
+ * Append an action handler to the block.
24
+ * Action is a pure function that takes the state + arguments and returns a new state.
25
+ */
26
+ action(e, t) {
27
+ return this.reducers[`${this.name}/${e}`] = t, this;
28
+ }
29
+ /**
30
+ * Append effect handlers to the block.
31
+ * Effects can call any side effects provided from the context.
32
+ */
33
+ effects(e) {
34
+ return this.handlers.push(e), this;
35
+ }
36
+ build() {
37
+ const e = this.initial, t = this.name;
38
+ return {
39
+ actions: b(this.name),
40
+ effects: (r) => this.handlers.reduce(
41
+ (s, n) => Object.assign(
42
+ s,
43
+ Object.fromEntries(
44
+ Object.entries(n(r)).map(([i, o]) => [
45
+ `${t}/${i}`,
46
+ o
47
+ ])
48
+ )
49
+ ),
50
+ {}
51
+ ),
52
+ reducer: (r = e, s) => {
53
+ const n = this.reducers[s.type];
54
+ if (!n) return r;
55
+ const i = "payload" in s ? s.payload : void 0;
56
+ return i && i.length ? n(r, ...i) : n(r);
57
+ }
58
+ };
59
+ }
60
+ }
61
+ class a {
62
+ constructor(e) {
63
+ this.name = e, this.creators = b(e);
64
+ }
65
+ blocks = {};
66
+ handlers = [];
67
+ creators;
68
+ static init(e) {
69
+ return new a(e);
70
+ }
71
+ block(e, t) {
72
+ return this.blocks[e] = t, this.creators[e] = t.actions, this;
73
+ }
74
+ effects(e) {
75
+ return this.handlers.push(e), this;
76
+ }
77
+ build() {
78
+ const e = Object.entries(this.blocks).map(([t, r]) => [t, r.reducer]);
79
+ return {
80
+ actions: this.creators,
81
+ effects: (t) => {
82
+ const r = this.name, s = this.handlers.reduce(
83
+ (n, i) => Object.assign(
84
+ n,
85
+ Object.fromEntries(
86
+ Object.entries(i(t)).map(([o, c]) => [
87
+ `${r}/${o}`,
88
+ c
89
+ ])
90
+ )
91
+ ),
92
+ {}
93
+ );
94
+ return Object.values(this.blocks).forEach((n) => Object.assign(s, n.effects(t))), s;
95
+ },
96
+ reducer: (t, r) => {
97
+ let s = t, n = !1;
98
+ return e.forEach(([i, o]) => {
99
+ const c = t?.[i], l = o(c, r);
100
+ l !== c && (n || (n = !0, s = { ...t }), s[i] = l);
101
+ }), s;
102
+ }
103
+ };
104
+ }
105
+ }
106
+ var d;
107
+ ((u) => {
108
+ function e(s, n) {
109
+ return h.init(s, n);
110
+ }
111
+ u.builder = e;
112
+ function t(s) {
113
+ return a.init(s);
114
+ }
115
+ u.composition = t;
116
+ function r(s, n) {
117
+ const i = s.effects(n);
118
+ return () => (o) => (c) => {
119
+ c && typeof c == "object" && "type" in c && f(i, c.type) && i[c.type](..."payload" in c ? c.payload : []), o(c);
120
+ };
121
+ }
122
+ u.middleware = r;
123
+ })(d || (d = {}));
44
124
  export {
45
- y as createReduxBlock
125
+ d as ReduxBlock
46
126
  };
47
127
  //# sourceMappingURL=redux-sacala.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"redux-sacala.js","sources":["../src/redux-sacala.ts"],"sourcesContent":["import { Dispatch, Action, Reducer, Middleware, AnyAction, MiddlewareAPI } from \"redux\";\n\ntype UnknownToUndefined<T> = unknown extends T ? undefined : T;\n\ntype FirstArgument<F> = F extends (arg1: infer U, ...args: any[]) => any ? UnknownToUndefined<U> : undefined;\ntype SecondArgument<F> = F extends (arg1: any, arg2: infer U, ...args: any[]) => any\n ? UnknownToUndefined<U>\n : undefined;\n\nconst bindAll = <T extends { [key: string]: Function }>(map: T): T => {\n const result = {} as any as T;\n for (const i in map) {\n result[i] = map[i].bind(map);\n }\n return result;\n};\n\nconst appendPrefix = <T>(prefix: string, map: { [key: string]: T }) => {\n const r: { [key: string]: any } = {};\n for (const i in map) {\n r[prefix + i] = map[i];\n }\n return r;\n};\n\n// Input\ntype ActionHandler<BlockState, Payload> = (state: BlockState, payload: Payload) => BlockState;\ntype ActionMap<BlockState> = { [action: string]: ActionHandler<BlockState, any> };\ntype EffectsMap<GlobalState, ExtraArgument> = (\n dispatch: Dispatch,\n getState: () => GlobalState,\n) => { [effect: string]: (payload: any, extraArgument: ExtraArgument) => any };\n\n// Output\ntype ActionCreator<Handler extends ActionHandler<any, any>> =\n undefined extends SecondArgument<Handler>\n ? () => Action<string>\n : (payload: SecondArgument<Handler>) => Action<string> & { payload: SecondArgument<Handler> };\n\ntype ActionCreatorMap<Actions extends ActionMap<any>> = {\n [name in keyof Actions]: ActionCreator<Actions[name]>;\n};\n\ntype EffectsCreatorMap<GlobalState, ExtraArgument, Map extends EffectsMap<GlobalState, ExtraArgument>> = {\n [key in keyof ReturnType<Map>]: undefined extends FirstArgument<ReturnType<Map>[key]>\n ? () => Action\n : (payload: FirstArgument<ReturnType<Map>[key]>) => Action;\n};\n\n// Transformation\nconst createActionCreator = (type: string) => (payload?: any) => (payload === undefined ? { type } : { type, payload });\nconst createEffectCreator = (type: string) => (payload: any) => ({ type, payload });\n\nconst createReducer = <BlockState>(prefix: string, initial: BlockState, actionMap: ActionMap<BlockState>): Reducer => {\n const actions: ActionMap<BlockState> = appendPrefix(prefix + \"/\", bindAll(actionMap));\n return (state: BlockState = initial, action?: AnyAction) => {\n if (action && action.type) {\n const handler: (state: BlockState, payload?: any) => BlockState = actions[action.type];\n if (handler) {\n return handler(state, action.payload);\n } else {\n return state;\n }\n } else {\n return state;\n }\n };\n};\n\ntype MiddlewareCreator<T> = T extends undefined ? () => Middleware : (argument: T) => Middleware;\n\nconst createMiddlewareCreator = <GlobalState, ExtraArgument>(\n prefix: string,\n effectsMap: EffectsMap<GlobalState, ExtraArgument>,\n): MiddlewareCreator<ExtraArgument> =>\n ((argument: ExtraArgument) => (store: MiddlewareAPI) => {\n const effects = appendPrefix(prefix + \"/\", bindAll(effectsMap(store.dispatch, store.getState)));\n return (next: Dispatch) => (action: Action<string> & { payload: any[] }) => {\n if (action && Object.prototype.hasOwnProperty.call(effects, action.type)) {\n effects[action.type](action.payload, argument);\n } else {\n next(action);\n }\n };\n }) as MiddlewareCreator<ExtraArgument>;\n\nconst fail = (): never => {\n throw new Error(\"Can't have access to 'dispatch' and 'getState' during initialization\");\n};\n\nexport const createReduxBlock =\n <GlobalState, ExtraArgument = undefined>() =>\n <\n Name extends keyof GlobalState & string,\n Actions extends ActionMap<GlobalState[Name]>,\n Effects extends EffectsMap<GlobalState, ExtraArgument>,\n >({\n name,\n initial,\n actions,\n effects,\n }: {\n name: Name;\n initial: GlobalState[Name];\n actions: Actions;\n effects?: Effects;\n }): {\n name: Name;\n reducer: Reducer<GlobalState[Name]>;\n actions: ActionCreatorMap<Actions> & EffectsCreatorMap<GlobalState, ExtraArgument, Effects>;\n } & ({} extends ReturnType<Effects> ? {} : { createMiddleware: MiddlewareCreator<ExtraArgument> }) => {\n const actionCreators = Object.keys(actions).reduce((r, key) => {\n r[key] = createActionCreator(`${name}/${key}`);\n return r;\n }, {} as any);\n const effectCreators = Object.keys(effects ? effects(fail, fail) : {}).reduce((r, key) => {\n r[key] = createEffectCreator(`${name}/${key}`);\n return r;\n }, {} as any);\n\n return {\n name,\n reducer: createReducer(name as string, initial, actions),\n createMiddleware: effects\n ? createMiddlewareCreator<GlobalState, ExtraArgument>(name as string, effects)\n : ((() => (_: MiddlewareAPI) => (next: Dispatch) => next) as MiddlewareCreator<ExtraArgument>),\n actions: {\n ...actionCreators,\n ...effectCreators,\n },\n };\n };\n"],"names":["bindAll","map","result","i","appendPrefix","prefix","r","createActionCreator","type","payload","createEffectCreator","createReducer","initial","actionMap","actions","state","action","handler","createMiddlewareCreator","effectsMap","argument","store","effects","next","fail","createReduxBlock","name","actionCreators","key","effectCreators","_"],"mappings":"AASA,MAAMA,IAAU,CAAwCC,MAAc;AAClE,QAAMC,IAAS,CAAA;AACf,aAAWC,KAAKF;AACZ,IAAAC,EAAOC,CAAC,IAAIF,EAAIE,CAAC,EAAE,KAAKF,CAAG;AAE/B,SAAOC;AACX,GAEME,IAAe,CAAIC,GAAgBJ,MAA8B;AACnE,QAAMK,IAA4B,CAAA;AAClC,aAAWH,KAAKF;AACZ,IAAAK,EAAED,IAASF,CAAC,IAAIF,EAAIE,CAAC;AAEzB,SAAOG;AACX,GA2BMC,IAAsB,CAACC,MAAiB,CAACC,MAAmBA,MAAY,SAAY,EAAE,MAAAD,EAAA,IAAS,EAAE,MAAAA,GAAM,SAAAC,EAAA,GACvGC,IAAsB,CAACF,MAAiB,CAACC,OAAkB,EAAE,MAAAD,GAAM,SAAAC,MAEnEE,IAAgB,CAAaN,GAAgBO,GAAqBC,MAA8C;AAClH,QAAMC,IAAiCV,EAAaC,IAAS,KAAKL,EAAQa,CAAS,CAAC;AACpF,SAAO,CAACE,IAAoBH,GAASI,MAAuB;AACxD,QAAIA,KAAUA,EAAO,MAAM;AACvB,YAAMC,IAA4DH,EAAQE,EAAO,IAAI;AACrF,aAAIC,IACOA,EAAQF,GAAOC,EAAO,OAAO,IAE7BD;AAAA,IAEf;AACI,aAAOA;AAAA,EAEf;AACJ,GAIMG,IAA0B,CAC5Bb,GACAc,OAEC,CAACC,MAA4B,CAACC,MAAyB;AACpD,QAAMC,IAAUlB,EAAaC,IAAS,KAAKL,EAAQmB,EAAWE,EAAM,UAAUA,EAAM,QAAQ,CAAC,CAAC;AAC9F,SAAO,CAACE,MAAmB,CAACP,MAAgD;AACxE,IAAIA,KAAU,OAAO,UAAU,eAAe,KAAKM,GAASN,EAAO,IAAI,IACnEM,EAAQN,EAAO,IAAI,EAAEA,EAAO,SAASI,CAAQ,IAE7CG,EAAKP,CAAM;AAAA,EAEnB;AACJ,IAEEQ,IAAO,MAAa;AACtB,QAAM,IAAI,MAAM,sEAAsE;AAC1F,GAEaC,IACT,MACA,CAIE;AAAA,EACE,MAAAC;AAAA,EACA,SAAAd;AAAA,EACA,SAAAE;AAAA,EACA,SAAAQ;AACJ,MASsG;AAClG,QAAMK,IAAiB,OAAO,KAAKb,CAAO,EAAE,OAAO,CAACR,GAAGsB,OACnDtB,EAAEsB,CAAG,IAAIrB,EAAoB,GAAGmB,CAAI,IAAIE,CAAG,EAAE,GACtCtB,IACR,CAAA,CAAS,GACNuB,IAAiB,OAAO,KAAKP,IAAUA,EAAQE,GAAMA,CAAI,IAAI,CAAA,CAAE,EAAE,OAAO,CAAClB,GAAGsB,OAC9EtB,EAAEsB,CAAG,IAAIlB,EAAoB,GAAGgB,CAAI,IAAIE,CAAG,EAAE,GACtCtB,IACR,CAAA,CAAS;AAEZ,SAAO;AAAA,IACH,MAAAoB;AAAA,IACA,SAASf,EAAce,GAAgBd,GAASE,CAAO;AAAA,IACvD,kBAAkBQ,IACZJ,EAAoDQ,GAAgBJ,CAAO,KACzE,MAAM,CAACQ,MAAqB,CAACP,MAAmBA;AAAA,IACxD,SAAS;AAAA,MACL,GAAGI;AAAA,MACH,GAAGE;AAAA,IAAA;AAAA,EACP;AAER;"}
1
+ {"version":3,"file":"redux-sacala.js","sources":["../src/redux-sacala.ts"],"sourcesContent":["import { Middleware, Reducer, UnknownAction } from \"redux\";\n\n/**\n * Composable Redux block with state description, action creators, and effects handlers.\n * Use `ReduxBlock.builder` to start building a new block.\n */\nexport interface ReduxBlock<State, Creators, Context> {\n /**\n * Action creators for this block.\n * When composed, action creators can form a folder tree structure.\n */\n actions: Creators;\n /**\n * Reducer that can be used directly in Redux store configuration.\n */\n reducer: Reducer<State, UnknownAction>;\n /**\n * Effects to be called on effects actions.\n * Use `ReduxBlock.middleware` to create middleware for effects processing.\n */\n effects: Effects<Context>;\n}\n\ntype PayloadAction<Type extends string, Payload extends unknown[]> = Payload extends never[]\n ? { type: Type }\n : { type: Type; payload: Payload };\n\n/**\n * Checks if the given key exists directly on the provided object.\n */\nfunction has<K extends string | symbol>(v: unknown, k: K): v is Record<K, unknown> {\n return typeof v === \"object\" && v !== null && Object.hasOwn(v, k);\n}\n\nconst creator = (scope: string) =>\n new Proxy(\n {},\n {\n get(target, property) {\n if (has(target, property)) {\n return target[property];\n }\n\n return (...payload: unknown[]) => {\n const type = `${scope}/${property as string}`;\n return payload.length ? { type, payload } : { type };\n };\n },\n },\n ) as Record<string, (...payload: unknown[]) => UnknownAction>;\n\n/**\n * Effects creator. It receives context with side effect APIs and returns non-pure handlers.\n */\ntype Effects<Context> = (context: Context) => Record<string, (...payload: any[]) => void>;\n\n/**\n * Convert effects type to action creators.\n */\ntype EffectsToCreators<Name extends string, E extends Effects<any>> = {\n [K in keyof ReturnType<E>]: (\n ...parameters: Parameters<ReturnType<E>[K]>\n ) => PayloadAction<`${Name}/${K extends string ? K : never}`, Parameters<ReturnType<E>[K]>>;\n};\n\nclass BlockBuilder<\n Name extends string,\n State,\n Creators extends Record<string, (...parameters: unknown[]) => PayloadAction<any, any>>,\n Context,\n> {\n private constructor(\n readonly name: Name,\n readonly initial: State,\n /**\n * Per-message action reducers for this block.\n */\n private readonly reducers: Record<string, (state: State, ...payload: unknown[]) => State>,\n /**\n * Effects handlers for this block.\n */\n private readonly handlers: Effects<Context>[],\n ) {}\n\n static init<Name extends string, State>(name: Name, initial: State): BlockBuilder<Name, State, {}, {}> {\n return new BlockBuilder(name, initial, {}, []);\n }\n\n /**\n * Append an action handler to the block.\n * Action is a pure function that takes the state + arguments and returns a new state.\n */\n action<Action extends string, Payload extends unknown[] = []>(\n action: Action,\n handler: (state: State, ...payload: Payload) => State,\n ): BlockBuilder<\n Name,\n State,\n Creators & Record<Action, (...payload: Payload) => PayloadAction<`${Name}/${Action}`, Payload>>,\n Context\n > {\n this.reducers[`${this.name}/${action}`] = handler as (state: State, ...payload: unknown[]) => State;\n return this as any;\n }\n\n /**\n * Append effect handlers to the block.\n * Effects can call any side effects provided from the context.\n */\n effects<E extends Effects<any>>(\n effects: E,\n ): BlockBuilder<\n Name,\n State,\n Creators & EffectsToCreators<Name, E>,\n Context & (E extends Effects<infer C> ? C : never)\n > {\n this.handlers.push(effects);\n return this as any;\n }\n\n build(): ReduxBlock<State, Creators, Context> {\n const initialState = this.initial;\n const blockName = this.name;\n return {\n actions: creator(this.name),\n effects: (context: Context) =>\n this.handlers.reduce(\n (acc, effect) =>\n Object.assign(\n acc,\n Object.fromEntries(\n Object.entries(effect(context)).map(([effectName, handler]) => [\n `${blockName}/${effectName}`,\n handler,\n ]),\n ),\n ),\n {} as Record<string, (...payload: unknown[]) => void>,\n ),\n reducer: (state = initialState, action: UnknownAction) => {\n const handler = this.reducers[action.type];\n if (!handler) return state;\n const payload = \"payload\" in action ? (action.payload as unknown[]) : undefined;\n return payload && payload.length ? handler(state, ...payload) : handler(state);\n },\n } as any;\n }\n}\n\nclass CompositionBuilder<\n Name extends string,\n BlockMap extends Record<string, ReduxBlock<any, any, any>>,\n Creators,\n Context,\n> {\n private blocks: BlockMap = {} as BlockMap;\n private handlers: Effects<Context>[] = [];\n private creators: Creators;\n\n private constructor(private name: Name) {\n this.creators = creator(name) as Creators;\n }\n\n static init<Name extends string>(name: Name): CompositionBuilder<Name, {}, {}, {}> {\n return new CompositionBuilder(name);\n }\n\n block<Name extends string, Block extends ReduxBlock<any, any, any>>(\n name: Name,\n block: Block,\n ): CompositionBuilder<\n Name,\n BlockMap & Record<Name, Block>,\n Creators & Record<Name, ReduxBlock.TakeCreators<Block>>,\n Context & ReduxBlock.TakeContext<Block>\n > {\n (this.blocks as Record<string, ReduxBlock<any, any, any>>)[name] = block;\n (this.creators as Record<string, unknown>)[name] = block.actions;\n return this as any;\n }\n\n effects<E extends Effects<any>>(\n effects: E,\n ): CompositionBuilder<\n Name,\n BlockMap,\n Creators & EffectsToCreators<Name, E>,\n Context & (E extends Effects<infer ExtraContext> ? ExtraContext : never)\n > {\n (this.handlers as (Effects<Context> | E)[]).push(effects);\n return this as any;\n }\n\n build(): ReduxBlock<{ [K in keyof BlockMap]: ReduxBlock.TakeState<BlockMap[K]> }, Creators, Context> {\n const reducers = Object.entries(this.blocks).map(([name, block]) => [name, block.reducer] as const);\n return {\n actions: this.creators,\n effects: (context: Context) => {\n const blockName = this.name;\n const result = this.handlers.reduce(\n (acc, effect) =>\n Object.assign(\n acc,\n Object.fromEntries(\n Object.entries(effect(context)).map(([effectName, handler]) => [\n `${blockName}/${effectName}`,\n handler,\n ]),\n ),\n ),\n {} as Record<string, (...payload: unknown[]) => void>,\n );\n Object.values(this.blocks).forEach((block) => Object.assign(result, block.effects(context)));\n return result;\n },\n reducer: (state: any, action: UnknownAction) => {\n let result = state;\n let changed = false;\n reducers.forEach(([name, reducer]) => {\n const original = state?.[name];\n const updated = reducer(original, action);\n if (updated !== original) {\n if (!changed) {\n changed = true;\n result = { ...state };\n }\n result[name] = updated;\n }\n });\n return result;\n },\n } as any;\n }\n}\n\nexport namespace ReduxBlock {\n type AnyBlock = ReduxBlock<any, any, any>;\n\n export type TakeState<Block extends AnyBlock> = Block extends ReduxBlock<infer State, any, any> ? State : never;\n export type TakeCreators<Block extends AnyBlock> =\n Block extends ReduxBlock<any, infer Creators, any> ? Creators : never;\n export type TakeContext<Block extends AnyBlock> =\n Block extends ReduxBlock<any, any, infer Context> ? Context : never;\n\n /**\n * Create a block builder.\n * It's a starting point for creating a block.\n */\n export function builder<Name extends string, State>(name: Name, initial: State): BlockBuilder<Name, State, {}, {}> {\n return BlockBuilder.init(name, initial);\n }\n\n /**\n * Create a composition builder.\n */\n export function composition<Name extends string>(name: Name): CompositionBuilder<Name, {}, {}, {}> {\n return CompositionBuilder.init(name);\n }\n\n /**\n * Create middleware for effects processing.\n * It expects to receive a context object that provides necessary dependencies for effect handlers.\n */\n export function middleware<Block extends AnyBlock>(block: Block, context: TakeContext<Block>): Middleware {\n const effects = block.effects(context);\n return () => (next) => (action) => {\n if (action && typeof action === \"object\" && \"type\" in action && has(effects, action.type as string)) {\n effects[action.type as string](...(\"payload\" in action ? (action.payload as unknown[]) : []));\n }\n next(action);\n };\n }\n}\n"],"names":["has","v","k","creator","scope","target","property","payload","type","BlockBuilder","name","initial","reducers","handlers","action","handler","effects","initialState","blockName","context","acc","effect","effectName","state","CompositionBuilder","block","result","changed","reducer","original","updated","ReduxBlock","builder","composition","middleware","next"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redux-sacala",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "Andrey Monkin",