redux-sacala 0.0.18 → 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.
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
5
+ </profile>
6
+ </component>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="EslintConfiguration">
4
+ <option name="fix-on-save" value="true" />
5
+ </component>
6
+ </project>
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>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="PrettierConfiguration">
4
+ <option name="myConfigurationMode" value="AUTOMATIC" />
5
+ <option name="myRunOnSave" value="true" />
6
+ </component>
7
+ </project>
@@ -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>
@@ -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>
@@ -0,0 +1,5 @@
1
+ node_modules
2
+ build
3
+ dist
4
+ coverage
5
+ package-lock.json
package/.prettierrc ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "tabWidth": 4,
3
+ "useTabs": false,
4
+ "semi": true,
5
+ "singleQuote": false,
6
+ "trailingComma": "all",
7
+ "printWidth": 120
8
+ }
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;
@@ -1,33 +1,49 @@
1
- import { Dispatch, Action, Reducer, Middleware } from "redux";
2
- type UnknownToUndefined<T> = unknown extends T ? undefined : T;
3
- type FirstArgument<F> = F extends (arg1: infer U, ...args: any[]) => any ? UnknownToUndefined<U> : undefined;
4
- type SecondArgument<F> = F extends (arg1: any, arg2: infer U, ...args: any[]) => any ? UnknownToUndefined<U> : undefined;
5
- type ActionHandler<BlockState, Payload> = (state: BlockState, payload: Payload) => BlockState;
6
- type ActionMap<BlockState> = {
7
- [action: string]: ActionHandler<BlockState, any>;
8
- };
9
- type EffectsMap<GlobalState, ExtraArgument> = (dispatch: Dispatch, getState: () => GlobalState) => {
10
- [effect: string]: (payload: any, extraArgument: ExtraArgument) => any;
11
- };
12
- type ActionCreator<Handler extends ActionHandler<any, any>> = undefined extends SecondArgument<Handler> ? () => Action<string> : (payload: SecondArgument<Handler>) => (Action<string> & {
13
- payload: SecondArgument<Handler>;
14
- });
15
- type ActionCreatorMap<Actions extends ActionMap<any>> = {
16
- [name in keyof Actions]: ActionCreator<Actions[name]>;
17
- };
18
- type EffectsCreatorMap<GlobalState, ExtraArgument, Map extends EffectsMap<GlobalState, ExtraArgument>> = {
19
- [key in keyof ReturnType<Map>]: (undefined extends FirstArgument<ReturnType<Map>[key]> ? () => Action : (payload: FirstArgument<ReturnType<Map>[key]>) => Action);
20
- };
21
- type MiddlewareCreator<T> = T extends undefined ? () => Middleware : (argument: T) => Middleware;
22
- 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 }: {
23
- name: Name;
24
- initial: GlobalState[Name];
25
- actions: Actions;
26
- effects?: Effects | undefined;
27
- }) => {
28
- name: Name;
29
- reducer: Reducer<GlobalState[Name]>;
30
- createMiddleware: MiddlewareCreator<ExtraArgument>;
31
- actions: ActionCreatorMap<Actions> & EffectsCreatorMap<GlobalState, ExtraArgument, Effects>;
32
- };
33
- export {};
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 { }
@@ -1,79 +1,56 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createReduxBlock = void 0;
4
- function bindAll(map) {
5
- const result = {};
6
- for (const i in map) {
7
- result[i] = map[i].bind(map);
8
- }
9
- return result;
10
- }
11
- function appendPrefix(prefix, map) {
12
- const r = {};
13
- for (const i in map) {
14
- r[prefix + i] = map[i];
15
- }
16
- return r;
17
- }
18
- // Transformation
19
- function createActionCreator(type) {
20
- return (payload) => payload === undefined ? { type } : { type, payload };
21
- }
22
- function createEffectCreator(type) {
23
- return (payload) => ({ type, payload });
24
- }
25
- function createReducer(prefix, initial, actionMap) {
26
- const actions = appendPrefix(prefix + "/", bindAll(actionMap));
27
- return (state = initial, action) => {
28
- if (action && action.type) {
29
- const handler = actions[action.type];
30
- if (handler) {
31
- return handler(state, action.payload);
32
- }
33
- else {
34
- return state;
35
- }
36
- }
37
- else {
38
- return state;
39
- }
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);
40
34
  };
41
- }
42
- function createMiddlewareCreator(prefix, effectsMap) {
43
- return ((argument) => (store) => {
44
- const effects = appendPrefix(prefix + "/", bindAll(effectsMap(store.dispatch, store.getState)));
45
- return (next) => (action) => {
46
- if (action && effects.hasOwnProperty(action.type)) {
47
- effects[action.type](action.payload, argument);
48
- }
49
- else {
50
- next(action);
51
- }
52
- };
53
- });
54
- }
55
- function fail() {
56
- throw new Error("Can't have access to 'dispatch' and 'getState' during initialization");
57
- }
58
- function createReduxBlock() {
59
- return function applyConfig({ name, initial, actions, effects }) {
60
- const actionCreators = Object.keys(actions).reduce((r, key) => {
61
- r[key] = createActionCreator(`${name}/${key}`);
62
- return r;
63
- }, {});
64
- const effectCreators = Object.keys(effects ? effects(fail, fail) : {}).reduce((r, key) => {
65
- r[key] = createEffectCreator(`${name}/${key}`);
66
- return r;
67
- }, {});
68
- return {
69
- name,
70
- reducer: createReducer(name, initial, actions),
71
- createMiddleware: effects
72
- ? createMiddlewareCreator(name, effects)
73
- : (() => ((_) => (next) => next)),
74
- actions: Object.assign(Object.assign({}, actionCreators), effectCreators)
75
- };
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
+ }
76
51
  };
52
+ };
77
53
  }
78
- exports.createReduxBlock = createReduxBlock;
79
- //# sourceMappingURL=redux-sacala.js.map
54
+ export {
55
+ y as createReduxBlock
56
+ };
@@ -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,26 +1,43 @@
1
1
  {
2
2
  "name": "redux-sacala",
3
- "version": "0.0.18",
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
- "main": "build/redux-sacala.js",
9
+ "module": "build/redux-sacala.js",
10
+ "main": "build/redux-sacala.cjs",
9
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
+ },
10
19
  "peerDependencies": {
11
- "redux": "^4.2.1"
20
+ "redux": "^5.0.1"
12
21
  },
13
22
  "devDependencies": {
14
- "typescript": "5.1.3",
15
- "jest": "29.5.0",
16
- "@types/jest": "29.5.2",
17
- "babel-jest": "29.5.0",
18
- "@babel/core": "7.22.5",
19
- "@babel/preset-env": "7.22.5",
20
- "@babel/preset-typescript": "7.22.5"
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"
21
35
  },
22
36
  "scripts": {
23
- "prepublish": "jest src && tsc",
24
- "test": "jest src"
37
+ "build": "vite build",
38
+ "prepublishOnly": "npm test && npm run build",
39
+ "test": "vitest run",
40
+ "lint": "eslint .",
41
+ "format": "prettier --write ."
25
42
  }
26
43
  }
@@ -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, getState) => {
32
- return {
33
- incEffect() {
34
- dispatch(local.inc());
35
- }
36
- };
37
- }
27
+ effects: (dispatch) => ({
28
+ incEffect() {
29
+ dispatch(local.inc());
30
+ },
31
+ }),
38
32
  });
39
33
 
40
- function createMyStore() {
41
- return createStore(combineReducers({
42
- local: localReducer,
43
- }), applyMiddleware(createLocalMiddleware(100)));
44
- }
45
-
46
- let store = createMyStore();
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
  });
@@ -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 ? UnknownToUndefined<U> : undefined;
7
-
8
- function bindAll<T extends { [key: string]: Function }>(map: T): T {
9
- const result = {} as any as T;
10
- for (const i in map) {
11
- result[i] = map[i].bind(map);
12
- }
13
- return result;
14
- }
15
-
16
- function appendPrefix<T>(prefix: string, map: { [key: string]: T }) {
17
- const r: { [key: string]: any } = {};
18
- for (const i in map) {
19
- r[prefix + i] = map[i];
20
- }
21
- return r;
22
- }
23
-
24
- // Input
25
- type ActionHandler<BlockState, Payload> = (state: BlockState, payload: Payload) => BlockState;
26
- type ActionMap<BlockState> = { [action: string]: ActionHandler<BlockState, any> };
27
- type EffectsMap<GlobalState, ExtraArgument> = (dispatch: Dispatch, getState: () => GlobalState) => { [effect: string]: (payload: any, extraArgument: ExtraArgument) => any }
28
-
29
- // Output
30
- type ActionCreator<Handler extends ActionHandler<any, any>> = undefined extends SecondArgument<Handler>
31
- ? () => Action<string>
32
- : (payload: SecondArgument<Handler>) => (Action<string> & { payload: SecondArgument<Handler> });
33
-
34
- type ActionCreatorMap<Actions extends ActionMap<any>> = {
35
- [name in keyof Actions]: ActionCreator<Actions[name]>;
36
- };
37
-
38
- type EffectsCreatorMap<GlobalState, ExtraArgument, Map extends EffectsMap<GlobalState, ExtraArgument>> = {
39
- [key in keyof ReturnType<Map>]: (undefined extends FirstArgument<ReturnType<Map>[key]>
40
- ? () => Action
41
- : (payload: FirstArgument<ReturnType<Map>[key]>) => Action
42
- );
43
- };
44
-
45
- // Transformation
46
- function createActionCreator(type: string) {
47
- return (payload?: any) => payload === undefined ? { type } : { type, payload };
48
- }
49
- function createEffectCreator(type: string) {
50
- return (payload: any) => ({ type, payload })
51
- }
52
-
53
- function createReducer<BlockState>(prefix: string, initial: BlockState, actionMap: ActionMap<BlockState>): Reducer {
54
- const actions: ActionMap<BlockState> = appendPrefix(prefix + "/", bindAll(actionMap));
55
- return (state: BlockState = initial, action?: AnyAction) => {
56
- if (action && action.type) {
57
- const handler: (state: BlockState, payload?: any) => BlockState = actions[action.type];
58
- if (handler) {
59
- return handler(state, action.payload);
60
- } else {
61
- return state;
62
- }
63
- } else {
64
- return state;
65
- }
66
- }
67
- }
68
-
69
- type MiddlewareCreator<T> = T extends undefined ? () => Middleware : (argument: T) => Middleware;
70
-
71
- function createMiddlewareCreator<GlobalState, ExtraArgument>(prefix: string, effectsMap: EffectsMap<GlobalState, ExtraArgument>): MiddlewareCreator<ExtraArgument> {
72
- return ((argument: ExtraArgument) => (store: MiddlewareAPI) => {
73
- const effects = appendPrefix(prefix + "/", bindAll(effectsMap(store.dispatch, store.getState)));
74
- return (next: Dispatch) => (action: Action<string> & { payload: any[] }) => {
75
- if (action && effects.hasOwnProperty(action.type)) {
76
- effects[action.type](action.payload, argument);
77
- } else {
78
- next(action);
79
- }
80
- };
81
- }) as MiddlewareCreator<ExtraArgument>;
82
- }
83
-
84
- function fail(): never {
85
- throw new Error("Can't have access to 'dispatch' and 'getState' during initialization");
86
- }
87
-
88
- export function createReduxBlock<GlobalState, ExtraArgument = undefined>() {
89
- return function applyConfig<
90
- Name extends (keyof GlobalState) & string,
91
- Actions extends ActionMap<GlobalState[Name]>,
92
- Effects extends EffectsMap<GlobalState, ExtraArgument>,
93
- >({ name, initial, actions, effects }: {
94
- name: Name;
95
- initial: GlobalState[Name];
96
- actions: Actions;
97
- effects?: Effects;
98
- }): {
99
- name: Name;
100
- reducer: Reducer<GlobalState[Name]>;
101
- actions: ActionCreatorMap<Actions> & EffectsCreatorMap<GlobalState, ExtraArgument, Effects>;
102
- } & ({} extends ReturnType<Effects> ? {} : { createMiddleware: MiddlewareCreator<ExtraArgument>; }) {
103
- const actionCreators = Object.keys(actions).reduce((r, key) => {
104
- r[key] = createActionCreator(`${name}/${key}`);
105
- return r;
106
- }, {} as any);
107
- const effectCreators = Object.keys(effects ? effects(fail, fail) : {}).reduce((r, key) => {
108
- r[key] = createEffectCreator(`${name}/${key}`);
109
- return r;
110
- }, {} as any);
111
-
112
- return {
113
- name,
114
- reducer: createReducer(name as string, initial, actions),
115
- createMiddleware: effects
116
- ? createMiddlewareCreator<GlobalState, ExtraArgument>(name as string, effects)
117
- : (() => ((_: MiddlewareAPI) => (next: Dispatch) => next)) as MiddlewareCreator<ExtraArgument>,
118
- actions: {
119
- ...actionCreators,
120
- ...effectCreators
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": "node",
6
- "module": "commonjs",
7
- "outDir": "build",
8
- "sourceMap": true,
9
- "declaration": true,
10
- "target": "es2015"
11
- },
12
- "include": [
13
- "src/*.ts"
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
+ });
package/babel.config.js DELETED
@@ -1,6 +0,0 @@
1
- module.exports = {
2
- presets: [
3
- ["@babel/preset-env", { targets: { node: "current" } }],
4
- "@babel/preset-typescript"
5
- ],
6
- };
@@ -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,40 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const redux_1 = require("redux");
4
- const redux_sacala_1 = require("./redux-sacala");
5
- const { actions: local, reducer: localReducer, createMiddleware: createLocalMiddleware, } = (0, redux_sacala_1.createReduxBlock)()({
6
- name: "local",
7
- initial: { count: 0 },
8
- actions: {
9
- inc(state) {
10
- return { count: state.count + 1 };
11
- },
12
- set(_, count) {
13
- return { count };
14
- }
15
- },
16
- effects: (dispatch, getState) => {
17
- return {};
18
- }
19
- });
20
- function createMyStore() {
21
- return (0, redux_1.createStore)((0, redux_1.combineReducers)({
22
- local: localReducer,
23
- }), (0, redux_1.applyMiddleware)(createLocalMiddleware(100)));
24
- }
25
- let store = createMyStore();
26
- beforeEach(() => {
27
- store = createMyStore();
28
- });
29
- describe("Store with reducer and middleware", () => {
30
- it("Should be updated on action without payload", () => {
31
- store.dispatch(local.inc());
32
- store.dispatch(local.inc());
33
- expect(store.getState()).toEqual({ local: { count: 2 } });
34
- });
35
- it("Should be updated on action with payload", () => {
36
- store.dispatch(local.set(12));
37
- expect(store.getState()).toEqual({ local: { count: 12 } });
38
- });
39
- });
40
- //# 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,iCAKe;AACf,iDAAkD;AAUlD,MAAM,EACF,OAAO,EAAE,KAAK,EACd,OAAO,EAAE,YAAY,EACrB,gBAAgB,EAAE,qBAAqB,GAC1C,GAAG,IAAA,+BAAgB,GAAmB,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,EAEN,CAAC;IACN,CAAC;CACJ,CAAC,CAAC;AAEH,SAAS,aAAa;IAClB,OAAO,IAAA,mBAAW,EAAC,IAAA,uBAAe,EAAC;QAC/B,KAAK,EAAE,YAAY;KACtB,CAAC,EAAE,IAAA,uBAAe,EAAC,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"}