├── .commitlintrc.json ├── .editorconfig ├── .github └── workflows │ └── main.yml ├── .gitignore ├── .prettierrc ├── .releaserc ├── .vscode └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── docs ├── api-reference.mdx ├── faq.mdx ├── getting-started.mdx ├── introduction.mdx └── media │ └── counter-example.jpg ├── doczrc.js ├── dts-jest.config.js ├── examples └── tasks │ ├── .gitignore │ ├── .sassrc │ ├── .vscode │ └── settings.json │ ├── jest.config.js │ ├── package.json │ ├── src │ ├── app │ │ ├── app.tsx │ │ ├── components │ │ │ ├── __tests__ │ │ │ │ └── snackbar.spec.tsx │ │ │ ├── category-indicator.tsx │ │ │ ├── category-item.tsx │ │ │ ├── category-list.tsx │ │ │ ├── icon.tsx │ │ │ ├── index.ts │ │ │ └── snackbar.tsx │ │ ├── containers │ │ │ ├── index.ts │ │ │ └── snackbar-container.tsx │ │ └── index.ts │ ├── index.html │ ├── index.tsx │ ├── scss │ │ ├── base │ │ │ ├── _color.scss │ │ │ ├── _global.scss │ │ │ ├── _module.scss │ │ │ └── _typography.scss │ │ ├── components │ │ │ ├── _app.scss │ │ │ ├── _category-indicator.scss │ │ │ ├── _category-item.scss │ │ │ ├── _category-list.scss │ │ │ ├── _module.scss │ │ │ └── _snackbar.scss │ │ ├── main.scss │ │ └── utils │ │ │ ├── _functions.scss │ │ │ └── _module.scss │ ├── store │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── snackbar.spec.ts.snap │ │ │ │ └── tasks.spec.ts.snap │ │ │ ├── snackbar.spec.ts │ │ │ └── tasks.spec.ts │ │ ├── configure-store.ts │ │ ├── index.ts │ │ ├── root.ts │ │ ├── selectors.ts │ │ ├── snackbar.ts │ │ └── tasks.ts │ ├── types.d.ts │ └── utils │ │ └── index.ts │ ├── tsconfig.json │ ├── tslint.json │ └── yarn.lock ├── jest.config.js ├── jest.tsc.config.js ├── netlify.toml ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── __tests__ │ ├── __snapshots__ │ │ ├── create-action-creator.dts.spec.ts.snap │ │ ├── create-action-creator.spec.ts.snap │ │ ├── create-action.dts.spec.ts.snap │ │ ├── create-action.spec.ts.snap │ │ ├── create-handler-map.dts.spec.ts.snap │ │ ├── create-handler-map.spec.ts.snap │ │ ├── create-reducer.dts.spec.ts.snap │ │ ├── get-type.dts.spec.ts.snap │ │ ├── index.spec.ts.snap │ │ ├── is-of-type.dts.spec.ts.snap │ │ ├── of-type.dts.spec.ts.snap │ │ └── types.dts.spec.ts.snap │ ├── create-action-creator.dts.spec.ts │ ├── create-action-creator.spec.ts │ ├── create-action.dts.spec.ts │ ├── create-action.spec.ts │ ├── create-handler-map.dts.spec.ts │ ├── create-handler-map.spec.ts │ ├── create-reducer.dts.spec.ts │ ├── create-reducer.spec.ts │ ├── get-type.dts.spec.ts │ ├── get-type.spec.ts │ ├── index.spec.ts │ ├── is-of-type.dts.spec.ts │ ├── is-of-type.spec.ts │ ├── of-type.dts.spec.ts │ ├── of-type.spec.ts │ └── types.dts.spec.ts ├── create-action-creator.ts ├── create-action.ts ├── create-handler-map.ts ├── create-reducer.ts ├── get-type.ts ├── index.ts ├── is-of-type.ts ├── of-type.ts ├── types.ts └── utils │ ├── data.ts │ └── index.ts ├── tsconfig.build.json ├── tsconfig.json ├── tsconfig.spec.json └── tslint.json /.commitlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@commitlint/config-conventional"] 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | jobs: 4 | test-build-release: 5 | runs-on: ubuntu-latest 6 | if: "! contains(toJSON(github.event.commits.*.message), '[skip-ci]')" 7 | steps: 8 | - uses: actions/checkout@v2 9 | 10 | - name: Cache 11 | uses: actions/cache@v2 12 | with: 13 | path: ~/.npm 14 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} 15 | restore-keys: ${{ runner.os }}-node- 16 | 17 | - name: Install Dependencies 18 | run: npm ci 19 | 20 | - name: TSC Testing 21 | run: npm run test-tsc --ci 22 | 23 | - name: Unit Testing 24 | run: npm run test --ci --coverage 25 | 26 | - name: DTS Testing 27 | run: npm run test-dts --ci 28 | 29 | - name: Codecov 30 | uses: codecov/codecov-action@v1.0.13 31 | 32 | - name: Lint 33 | run: npm run lint 34 | 35 | - name: Build 36 | run: npm run build 37 | 38 | - name: Release 39 | run: npx semantic-release 40 | env: 41 | GITHUB_TOKEN: ${{ secrets.VCS_TOKEN }} 42 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # IDEs and editors 33 | .idea 34 | .project 35 | .classpath 36 | .c9/ 37 | *.launch 38 | .settings/ 39 | *.sublime-workspace 40 | 41 | # IDE - VSCode 42 | .vscode/* 43 | !.vscode/settings.json 44 | !.vscode/tasks.json 45 | !.vscode/launch.json 46 | !.vscode/extensions.json 47 | 48 | # misc 49 | .sass-cache 50 | connect.lock 51 | typings 52 | 53 | # Logs 54 | logs 55 | *.log 56 | npm-debug.log* 57 | yarn-debug.log* 58 | yarn-error.log* 59 | 60 | 61 | # Dependency directories 62 | node_modules/ 63 | jspm_packages/ 64 | 65 | # Optional npm cache directory 66 | .npm 67 | 68 | # Optional eslint cache 69 | .eslintcache 70 | 71 | # Optional REPL history 72 | .node_repl_history 73 | 74 | # Output of 'npm pack' 75 | *.tgz 76 | 77 | # Yarn Integrity file 78 | .yarn-integrity 79 | 80 | # dotenv environment variables file 81 | .env 82 | 83 | # next.js build output 84 | .next 85 | 86 | # docz build output 87 | .docz 88 | 89 | # Lerna 90 | lerna-debug.log 91 | 92 | # System Files 93 | .DS_Store 94 | Thumbs.db -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "semi": false, 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "printWidth": 144, 7 | "tabWidth": 4 8 | } 9 | -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@semantic-release/commit-analyzer", 4 | "@semantic-release/github", 5 | "@semantic-release/release-notes-generator", 6 | [ 7 | "@semantic-release/changelog", 8 | { 9 | "changelogTitle": "# Deox Changelog" 10 | } 11 | ], 12 | "@semantic-release/npm", 13 | "@semantic-release/git" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "jest.pathToConfig": "jest.config.js", 4 | "files.associations": { 5 | ".releaserc": "json" 6 | }, 7 | "typescript.tsdk": "node_modules/typescript/lib" 8 | } 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Deox Changelog 2 | 3 | # [4.0.0](https://github.com/thebrodmann/deox/compare/v3.3.1...v4.0.0) (2021-03-15) 4 | 5 | 6 | ### Features 7 | 8 | * remove `configureStore` function and dependency to @reduxjs/toolkit ([1f488a1](https://github.com/thebrodmann/deox/commit/1f488a1650729c13e70d48f31c07fa82e81923a2)), closes [#164](https://github.com/thebrodmann/deox/issues/164) [#151](https://github.com/thebrodmann/deox/issues/151) 9 | 10 | 11 | ### BREAKING CHANGES 12 | 13 | * - `configureStore` function has been removed from public API. 14 | - There is no dependency to [redux-starter-kit](https://github.com/reduxjs/redux-toolkit) package 15 | anymore. 16 | - TypeScript version and `tslib` version has been bumped. 17 | 18 | Co-authored-by: Michael Schmid 19 | Co-authored-by: Mohammad Hasani 20 | 21 | ## [3.3.1](https://github.com/thebrodmann/deox/compare/v3.3.0...v3.3.1) (2020-10-17) 22 | 23 | ### Bug Fixes 24 | 25 | - use symbol for the `others` handler ([f5b1cee](https://github.com/thebrodmann/deox/commit/f5b1ceecf35b515bdfd7984657740e6dcae13a35)) 26 | 27 | # [3.3.0](https://github.com/thebrodmann/deox/compare/v3.2.1...v3.3.0) (2020-10-01) 28 | 29 | ### Bug Fixes 30 | 31 | - handle.others instead of handle.default ([ffe271b](https://github.com/thebrodmann/deox/commit/ffe271b664118eb28a233394f2f5641b65e76978)) 32 | - more explicit typing to avoid TS4025 ([25b78c3](https://github.com/thebrodmann/deox/commit/25b78c34bcf40bde0747e0b39961788f59741f6a)) 33 | - type for plain action creator. ([#144](https://github.com/thebrodmann/deox/issues/144)) ([f228b81](https://github.com/thebrodmann/deox/commit/f228b8179078dd68c2bd2e1789e94ef43a831ef1)), closes [#143](https://github.com/thebrodmann/deox/issues/143) 34 | 35 | ### Features 36 | 37 | - default handler in createReducer ([0b3dfcf](https://github.com/thebrodmann/deox/commit/0b3dfcfc26e5dcbaa0e34a8888aa72ac266ae327)), closes [#152](https://github.com/thebrodmann/deox/issues/152) 38 | 39 | # [3.3.0](https://github.com/thebrodmann/deox/compare/v3.2.2...v3.3.0) (2020-10-01) 40 | 41 | ### Bug Fixes 42 | 43 | - handle.others instead of handle.default ([f9aec53](https://github.com/thebrodmann/deox/commit/f9aec53a32acd72fa661ad9a216d5291764d1e89)) 44 | - more explicit typing to avoid TS4025 ([e703730](https://github.com/thebrodmann/deox/commit/e703730104178496c23f683b150a72d8811e91bb)) 45 | 46 | ### Features 47 | 48 | - default handler in createReducer ([611184d](https://github.com/thebrodmann/deox/commit/611184d39167cac8007e3985d3adc791d82b2155)), closes [#152](https://github.com/thebrodmann/deox/issues/152) 49 | 50 | ## [3.2.2](https://github.com/thebrodmann/deox/compare/v3.2.1...v3.2.2) (2020-03-16) 51 | 52 | ### Bug Fixes 53 | 54 | - type for plain action creator. ([#144](https://github.com/thebrodmann/deox/issues/144)) ([709fe60](https://github.com/thebrodmann/deox/commit/709fe605916ab806e9a9c94f4a56edd6ef65fb80)), closes [#143](https://github.com/thebrodmann/deox/issues/143) 55 | 56 | ## [3.2.1](https://github.com/thebrodmann/deox/compare/v3.2.0...v3.2.1) (2020-01-09) 57 | 58 | ### Bug Fixes 59 | 60 | - extract action from any, Redux.Action and AnyAction types ([18d0a9e](https://github.com/thebrodmann/deox/commit/18d0a9ec720e79c76df23fc7ae94f695aa3f5ae4)), closes [#141](https://github.com/thebrodmann/deox/issues/141) 61 | 62 | # [3.2.0](https://github.com/thebrodmann/deox/compare/v3.1.0...v3.2.0) (2019-12-09) 63 | 64 | ### Features 65 | 66 | - reuse isOfType helper in ofType RxJS operator ([#136](https://github.com/thebrodmann/deox/issues/136)) ([a5f0648](https://github.com/thebrodmann/deox/commit/a5f06482fe175abf8ae8e6bd2ec594e748cb9090)) 67 | - support mixed keys for ofType RxJS operator ([#133](https://github.com/thebrodmann/deox/issues/133)) [skip release](<[dc21e6d](https://github.com/thebrodmann/deox/commit/dc21e6d4c0d64874eb041a30bc3e5fad3b5bf2b2)>) 68 | 69 | # [3.1.0](https://github.com/thebrodmann/deox/compare/v3.0.1...v3.1.0) (2019-12-08) 70 | 71 | ### Features 72 | 73 | - add isOfType helper ([#127](https://github.com/thebrodmann/deox/issues/127)) ([03e6210](https://github.com/thebrodmann/deox/commit/03e6210b9d2866ba0a99c5811254bdeb031ae738)), closes [#87](https://github.com/thebrodmann/deox/issues/87) 74 | - generalize isOfType keys argument to readonly array ([cc01d9d](https://github.com/thebrodmann/deox/commit/cc01d9dbd72ba59dbea4a1916e254c4ddfe9adfa)) 75 | 76 | ## [3.0.1](https://github.com/thebrodmann/deox/compare/v3.0.0...v3.0.1) (2019-12-07) 77 | 78 | ### Bug Fixes 79 | 80 | - generalize TActionCreator generic type in createHandlerMap ([9825477](https://github.com/thebrodmann/deox/commit/98254776533c6d1be5cfe07188b3724197c861a5)), closes [#128](https://github.com/thebrodmann/deox/issues/128) 81 | 82 | # [3.0.0](https://github.com/thebrodmann/deox/compare/v2.1.2...v3.0.0) (2019-12-04) 83 | 84 | ### Bug Fixes 85 | 86 | - use tslib and rxjs as peer dependencies ([a58a4a9](https://github.com/thebrodmann/deox/commit/a58a4a9)) 87 | 88 | ### BREAKING CHANGES 89 | 90 | - Please make sure you have tslib in your dependencies if you are using TypeScript. 91 | Also, make sure you have rxjs in your dependencies if you are using ofType rxjs operator. 92 | 93 | ## [2.1.4](https://github.com/thebrodmann/deox/compare/v2.1.3...v2.1.4) (2019-12-06) 94 | 95 | ### Bug Fixes 96 | 97 | - generalize TActionCreator generic type in createHandlerMap ([a7dd90a](https://github.com/thebrodmann/deox/commit/a7dd90a)), closes [#128](https://github.com/thebrodmann/deox/issues/128) 98 | 99 | ## [2.1.2](https://github.com/thebrodmann/deox/compare/v2.1.1...v2.1.2) (2019-12-04) 100 | 101 | ### Bug Fixes 102 | 103 | - allow acceptance of any action by reducer created by createReducer ([1b39adb](https://github.com/thebrodmann/deox/commit/1b39adb)) 104 | 105 | ## [2.1.1](https://github.com/thebrodmann/deox/compare/v2.1.0...v2.1.1) (2019-12-04) 106 | 107 | ### Bug Fixes 108 | 109 | - make ofType operator typing works with plain action types ([fecabda](https://github.com/thebrodmann/deox/commit/fecabda)) 110 | 111 | # [2.1.0](https://github.com/thebrodmann/deox/compare/v2.0.1...v2.1.0) (2019-06-25) 112 | 113 | ### Features 114 | 115 | - upgrade redux-starter-kit to version 0.5.1 ([644acac](https://github.com/thebrodmann/deox/commit/644acac)) 116 | 117 | ## [2.0.1](https://github.com/thebrodmann/deox/compare/v2.0.0...v2.0.1) (2019-06-24) 118 | 119 | ### Bug Fixes 120 | 121 | - remove useless default generic value in createActionCreator ([7538ae0](https://github.com/thebrodmann/deox/commit/7538ae0)) 122 | 123 | # [2.0.0](https://github.com/thebrodmann/deox/compare/v1.4.1...v2.0.0) (2019-06-15) 124 | 125 | ### Features 126 | 127 | - export immutibility type helpers in public API ([b723d35](https://github.com/thebrodmann/deox/commit/b723d35)) 128 | - make DeepImmutable optional in input/prev state ([0f35d7f](https://github.com/thebrodmann/deox/commit/0f35d7f)), closes [#58](https://github.com/thebrodmann/deox/issues/58) [#55](https://github.com/thebrodmann/deox/issues/55) 129 | 130 | ### BREAKING CHANGES 131 | 132 | - The input/prev state argument in createHandlerMap (AKA handleAction) and returning 133 | reducer of createReducer will not obligated to be Immutable data structure by Deox which in turn can 134 | lead to changes in handler's and reducer's return type. 135 | 136 | ## [1.4.1](https://github.com/thebrodmann/deox/compare/v1.4.0...v1.4.1) (2019-06-09) 137 | 138 | ### Bug Fixes 139 | 140 | - infer return type of reducer from return type of handlers ([6b6edaa](https://github.com/thebrodmann/deox/commit/6b6edaa)), closes [#55](https://github.com/thebrodmann/deox/issues/55) 141 | - nested DeepImmutable and Immutable types neutralization ([d3f9a1a](https://github.com/thebrodmann/deox/commit/d3f9a1a)), closes [#65](https://github.com/thebrodmann/deox/issues/65) 142 | 143 | # [1.4.0](https://github.com/thebrodmann/deox/compare/v1.3.1...v1.4.0) (2019-04-21) 144 | 145 | ### Bug Fixes 146 | 147 | - make rxjs/operators in UMD bundle an external dependency ([cf94ab7](https://github.com/thebrodmann/deox/commit/cf94ab7)), closes [#41](https://github.com/thebrodmann/deox/issues/41) 148 | 149 | ### Features 150 | 151 | - rename createAction to createActionCreator ([a855997](https://github.com/thebrodmann/deox/commit/a855997)), closes [#30](https://github.com/thebrodmann/deox/issues/30) 152 | 153 | ## [1.3.1](https://github.com/thebrodmann/deox/compare/v1.3.0...v1.3.1) (2019-04-05) 154 | 155 | ### Bug Fixes 156 | 157 | - **tree-shaking:** rename browser field to unpkg in package.json ([159f2e7](https://github.com/thebrodmann/deox/commit/159f2e7)), closes [#43](https://github.com/thebrodmann/deox/issues/43) 158 | - **tree-shaking:** set sideEffects field in package.json ([dd5889d](https://github.com/thebrodmann/deox/commit/dd5889d)) 159 | 160 | # [1.3.0](https://github.com/thebrodmann/deox/compare/v1.2.1...v1.3.0) (2019-04-02) 161 | 162 | ### Features 163 | 164 | - add ActionType helper ([0b2906a](https://github.com/thebrodmann/deox/commit/0b2906a)) 165 | - export ActionType in public API ([f349705](https://github.com/thebrodmann/deox/commit/f349705)) 166 | - export configureStore from redux-starter-kit ([2499a02](https://github.com/thebrodmann/deox/commit/2499a02)), closes [#9](https://github.com/thebrodmann/deox/issues/9) 167 | 168 | ## [1.2.1](https://github.com/thebrodmann/deox/compare/v1.2.0...v1.2.1) (2019-03-25) 169 | 170 | ### Bug Fixes 171 | 172 | - export DeepImmutable\* types ([c9d0b3b](https://github.com/thebrodmann/deox/commit/c9d0b3b)), closes [#21](https://github.com/thebrodmann/deox/issues/21) 173 | 174 | # [1.2.0](https://github.com/thebrodmann/deox/compare/v1.1.1...v1.2.0) (2019-03-18) 175 | 176 | ### Features 177 | 178 | - add generic type capability to action creator ([4044db2](https://github.com/thebrodmann/deox/commit/4044db2)) 179 | 180 | ## [1.1.1](https://github.com/thebrodmann/deox/compare/v1.1.0...v1.1.1) (2019-02-20) 181 | 182 | ### Bug Fixes 183 | 184 | - attach non-undefined falsy values to payload and meta of action ([1fd8ed8](https://github.com/thebrodmann/deox/commit/1fd8ed8)), closes [#15](https://github.com/thebrodmann/deox/issues/15) 185 | 186 | # [1.1.0](https://github.com/thebrodmann/deox/compare/v1.0.2...v1.1.0) (2019-02-14) 187 | 188 | ### Features 189 | 190 | - add ofType operator ([63fb590](https://github.com/thebrodmann/deox/commit/63fb590)), closes [#11](https://github.com/thebrodmann/deox/issues/11) 191 | - deep immutable reducer type state ([de98e30](https://github.com/thebrodmann/deox/commit/de98e30)), closes [#3](https://github.com/thebrodmann/deox/issues/3) 192 | 193 | ## [1.0.2](https://github.com/thebrodmann/deox/compare/v1.0.1...v1.0.2) (2019-01-21) 194 | 195 | ### Bug Fixes 196 | 197 | - convert types.d.ts to types.ts ([852e196](https://github.com/thebrodmann/deox/commit/852e196)), closes [#5](https://github.com/thebrodmann/deox/issues/5) 198 | 199 | ## [1.0.1](https://github.com/thebrodmann/deox/compare/v1.0.0...v1.0.1) (2019-01-20) 200 | 201 | ### Bug Fixes 202 | 203 | - publish new README.md ([258bfc9](https://github.com/thebrodmann/deox/commit/258bfc9)) 204 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at thebrodmann@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Deox Contributing Guidelines 2 | 3 | ## Introduction 4 | 5 | First off, thank you for considering contributing to Deox! It's people like you that make the open source community such a great community! 😊 6 | 7 | Please note we have a [code of conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project. 8 | When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. 9 | 10 | **Why you should read these guidelines ?** 11 | Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue, assessing changes, and helping you finalize your pull requests. 12 | 13 | **What kinds of contributions we are looking for ?** 14 | Deox is an open source project and we love to receive contributions from our community — you! There are many ways to contribute: 15 | 16 | - **Q/A**: file bug reports, the more details you can give the better (i.e. REPL-links or repos that demonstrate the specific issue) 17 | - **Marketing**: writing blog posts, howto's, printing stickers, ... 18 | - **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ... 19 | - **Code**: take a look at the open issues. Even if you can't write code, commenting on them, showing that you care about a given issue matters. It helps us triage them. 20 | 21 | ## Your First Contribution 22 | 23 | **Working on your first Pull Request?** You can learn how from this _free_ series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github). 24 | 25 | **Unsure where to begin contributing to Deox?** You can start by looking through these [good first issue][good-first-issue] and [help wanted][help-wanted] issues. 26 | 27 | At this point, you're ready to make your changes! Feel free to ask for help; **everyone is a beginner at first**. 28 | 29 | ### Setup 30 | 31 | 1. Create your own fork of repository. 32 | 2. Git clone the [Deox repository](https://github.com/thebordmann/deox). 33 | 3. from the root of repository run following command to install dependencies required for development: 34 | 35 | ```bash 36 | # YARN 37 | yarn 38 | 39 | # NPM 40 | npm install 41 | ``` 42 | 43 | 4. Do the change in the repository. 44 | 5. If you like the change and think the project could use it, make a pull request. 45 | 46 | ### Building 47 | 48 | Run the following command to build Deox project: 49 | 50 | ```bash 51 | # YARN 52 | yarn run build 53 | 54 | # NPM 55 | npm run build 56 | ``` 57 | 58 | The above command will create a directory called `/dist` in the root of repository that contains all types of builds. 59 | 60 | ### Testing Your Changes 61 | 62 | To perform an on-off test using: 63 | 64 | ```bash 65 | # YARN 66 | yarn run test && yarn run test-dts 67 | 68 | # NPM 69 | npm run test && npm run test-dts 70 | ``` 71 | 72 | Or to automatically re-test on every change are made, use: 73 | 74 | ```bash 75 | # YARN 76 | yarn run test:watch 77 | 78 | # NPM 79 | npm run test:watch 80 | ``` 81 | 82 | ### Linting 83 | 84 | To run linter, use: 85 | 86 | ```bash 87 | # YARN 88 | yarn run lint 89 | 90 | # NPM 91 | npm run lint 92 | ``` 93 | 94 | ## Feature Request / Bug Report 95 | 96 | To issue a feature request or a bug report just follow the related template. 97 | 98 | ## License 99 | 100 | Deox is [MIT licensed](LICENSE). 101 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | ----------- 3 | 4 | Copyright (c) 2019 Mohammad Hasani (https://github.com/thebrodmann) 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Deox

2 | 3 |

Functional type-safe Flux standard utilities

4 | 5 |

6 | 7 | License 8 | 9 | 10 | Build Status 11 | 12 | 13 | Coverage Status 14 | 15 | 16 | Semantic Release 17 | 18 | 19 | Latest Release 20 | 21 | 22 | PRs welcome 23 | 24 |

25 | 26 | The only completely functional **type-safe** approach to Flux that its main goals are to diminish types **verbosity**, **repetition** and **complexity** without losing any type information (type-safe alternative of [redux-actions](https://github.com/redux-utilities/redux-actions)). 27 | 28 | Behold, the art of Deox: 29 | 30 |

31 | Deox counter example 32 |

33 | 34 | ## Highlights 35 | 36 | - **Minimalist** (almost no import cost) - checkout [Bundle Phobia](https://bundlephobia.com/result?p=deox@latest). 37 | - **Simple** - focused on self-declarative API. 38 | - **Secure** - complete test-suits for all of the edge and corners. 39 | 40 | ## Motivation 41 | 42 | The most common complaint about Flux is how it makes you write a lot of boilerplate. 43 | Also, existing solutions like redux-actions or redux-starter-kit are not type-safe by the idea (although there are some other ideas with classes 😱). 44 | 45 | So, this is where Deox takes place to **make maintenance of Flux architecture simpler and more readable** by sticking to **functional programming paradigm**. 46 | 47 | ## Installation 48 | 49 | You can install Deox package by running: 50 | 51 | ```bash 52 | # YARN 53 | yarn add deox 54 | 55 | # NPM 56 | npm install deox 57 | ``` 58 | 59 | > **Typescript tip**: notice that Deox internally uses some ES2015 type definitions to represent better developer experience. 60 | > So if you are using [`Typescript`](https://github.com/Microsoft/TypeScript) and targeting `es5`, be sure `es2015` lib has been added in tsconfig.json: 61 | 62 | ```json 63 | { 64 | "compilerOptions": { 65 | ... 66 | "target": "es5", 67 | "lib": ["es2015"] 68 | } 69 | } 70 | ``` 71 | 72 | The Deox NPM package contains a [CommonJS](http://www.commonjs.org/specs/modules/1.0/) build that can be use with [Node.js](https://nodejs.org/en/) or module bundlers (e.g. [Rollup](https://github.com/rollup/rollup), [Webpack](https://github.com/webpack/webpack), etc.). it also includes an [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) build that works well with [tree-shaking](https://webpack.js.org/guides/tree-shaking/). 73 | 74 | If you don't use module bundler, it's also fine. The Deox NPM package also includes a production minified [UMD](https://github.com/umdjs/umd) build that makes Deox available as global variable called `window.Deox`; you can add it simply to your page via following script tag: 75 | 76 | ```html 77 | 78 | ``` 79 | 80 | ## Usage 81 | 82 | ```ts 83 | import { createActionCreator, createReducer } from 'deox' 84 | 85 | const increment = createActionCreator('INCREMENT') 86 | const decrement = createActionCreator('DECREMENT') 87 | const reset = createActionCreator('RESET', resolve => (count: number) => resolve(count)) 88 | 89 | const defaultState = 0 90 | 91 | const counterReducer = createReducer(defaultState, handleAction => [ 92 | handleAction(increment, state => state + 1), 93 | handleAction(decrement, state => state - 1), 94 | handleAction(reset, (_state, { payload }) => payload), 95 | ]) 96 | 97 | counterReducer(undefined, increment()) //=> 1 98 | counterReducer(undefined, decrement()) //=> -1 99 | counterReducer(3, reset(0)) //=> 0 100 | ``` 101 | 102 | ## Documentation 103 | 104 | - [Introduction](https://deox.js.org) 105 | - [Getting started](https://deox.js.org/getting-started) 106 | - [API reference](https://deox.js.org/api-reference) 107 | - [FAQ](https://deox.js.org/api-reference) 108 | - [Using redux-thunk with Deox](https://deox.js.org/faq#using-redux-thunk-with-deox) 109 | - [Using redux-saga with Deox](https://deox.js.org/faq#using-redux-saga-with-deox) 110 | - [Using redux-observable with Deox](https://deox.js.org/faq#using-redux-observable-with-deox) 111 | 112 | ## FAQ 113 | 114 | ### Why not `redux-actions`, `redux-starter-kit` ? 115 | 116 | Both `redux-actions` and `redux-starter-kit` are neat and almost similar to each other. 117 | Actually `deox` is similar to those projects in the idea, but not in implementation and promise. 118 | The main goal of `deox` is to use the full power of **type-safety** and **type inferring** in typescript. 119 | If you have some experience with those libraries, the following piece of code should be familiar for you: 120 | 121 | ```ts 122 | type Actions 123 | = ReturnType 124 | | ReturnType 125 | | ReturnType 126 | 127 | const todosReducer = createReducer(...) 128 | ``` 129 | 130 | This is horrible; Why define a type like actions that a reducer can handle?! It's completely obvious which actions a reducer handles. 131 | 132 | On another hand there is a big problem with the pattern that `redux-actions` and `redux-starter-kit` follows. it's lack of correct type for action handler: 133 | 134 | ```ts 135 | const todosReducer = createReducer(defaultState, { 136 | [addTodo]: (state, action) => {...}, // action: Actions 137 | [removeTodo]: (state, action) => {...}, // action: Actions 138 | [editTodo]: (state, action) => {...}, // action: Actions 139 | }) 140 | ``` 141 | 142 | Type of action parameter in `addTodo` action handler is overall `Actions` type. It's inaccurate! 143 | 144 | And this is where Deox comes in action and practice: 145 | 146 | ```ts 147 | const todosReducer = createReducer(defaultState, handleAction => [ 148 | handleAction(addTodo, (state, action) => {...}), // action: AddTodoAction 149 | handleAction(removeTodo, (state, action) => {...}), // action: RemoveTodoAction 150 | handleAction(editTodo, (state, action) => {...}) // action: EditTodoAction 151 | ]) 152 | ``` 153 | 154 | That's it. Thanks to typescript type inferring **there is no type verbosity** at all. You can be sure `todos` reducer have the proper type of state and actions that it can handle. 155 | And every action handler's type is just what it should be. It's completely safe and correct! 156 | 157 | ### What's the difference with `typesafe-actions` ? 158 | 159 | The `typesafe-actions` is a great project that Deox carries huge inspiration from that. 160 | But `typesafe-actions` doesn't have any plan for a complete set of utilities (specially reducers); **It's all about actions and action creators**. 161 | 162 | ## Versioning 163 | 164 | Deox uses [Semantic Versioning 2.0.0](https://semver.org/) 165 | 166 | ## Contributing 167 | 168 | Please read through our [contributing guidelines](CONTRIBUTING.md). 169 | 170 | ## Inspiration 171 | 172 | - [redux-actions](https://github.com/redux-utilities/redux-actions) - Flux Standard Action utilities for Redux 173 | - [typesafe-actions](https://github.com/piotrwitek/typesafe-actions) - Typesafe Action Creators for Redux / Flux Architectures (in TypeScript) 174 | 175 | ## License 176 | 177 | Deox is released under [MIT license](LICENSE). 178 | -------------------------------------------------------------------------------- /docs/api-reference.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: API reference 3 | route: /api-reference 4 | --- 5 | 6 | # API Reference 7 | 8 | ## _createActionCreator(type[, executor])_ 9 | 10 | Creates an action creator. 11 | 12 | ### Arguments 13 | 14 | 1. `type` (**_string_** ): the type of action being created. It should typically be defined as string constants and is the only required parameter. 15 | 2. `executor` (**_Function_** ): a function that gives an argument named resolve that gives payload and meta as optional arguments and returns an action. 16 | 17 | ### Returns 18 | 19 | (**_ActionCreator_** ) 20 | 21 | ### Examples 22 | 23 | #### With only type: 24 | 25 | ```ts 26 | import { createActionCreator } from 'deox' 27 | 28 | const completeAllTodos = createActionCreator('COMPLETE_ALL_TODOS') 29 | completeAllTodos() //=> { type: 'COMPLETE_ALL_TODOS' } 30 | ``` 31 | 32 | #### With type and payload: 33 | 34 | ```ts 35 | import { createActionCreator } from 'deox' 36 | 37 | const addTodo = createActionCreator('ADD_TODO', resolve => (text: string) => resolve(text)) 38 | addTodo('Read the docs') //=> { type: 'ADD_TODO', payload: 'Read the docs' } 39 | ``` 40 | 41 | #### With type and meta: 42 | 43 | ```ts 44 | import { createActionCreator } from 'deox' 45 | 46 | const showTodos = createActionCreator('SHOW_TODOS', resolve => (param: number) => resolve(undefined, param)) 47 | showTodos(10) //=> { type: 'ADD_TODO', meta: 10 } 48 | ``` 49 | 50 | #### With type, payload and meta: 51 | 52 | ```ts 53 | import { createActionCreator } from 'deox' 54 | 55 | const getTodo = createActionCreator('GET_TODO', resolve => (id: number, meta: string) => resolve(id, meta)) 56 | getTodo(700, 'some-meta') //=> { type: 'GET_TODO', payload: 700, meta: 'some-meta' } 57 | ``` 58 | 59 | ## _createAction(type[, executor])_ 60 | 61 | Alias of [createActionCreator](#createactioncreatortype-executor). 62 | 63 | ## _createReducer(defaultState, handlerMapsCreator)_ 64 | 65 | Creates a reducer. 66 | 67 | ### Arguments 68 | 69 | 1. `defaultState` (**_any_** ): returning state when _undefined_ is passed to the created reducer. 70 | 2. `handlerMapsCreator` (**_Function_** ): a function that gives an argument named handleAction that gives action creator(s) and handler as arguments and returns a _HandlerMap_. 71 | 72 | ### Returns 73 | 74 | (**_Reduer_** ). 75 | 76 | ### Examples 77 | 78 | #### Basic: 79 | 80 | ```ts 81 | import { createActionCreator, createReducer } from 'deox' 82 | 83 | const increment = createActionCreator('INCREMENT') 84 | const decrement = createActionCreator('DECREMENT') 85 | const reset = createActionCreator('reset', resolve => (count: number) => resolve(count)) 86 | 87 | const defaultState = 0 88 | 89 | const counterReducer = createReducer(defaultState, handleAction => [ 90 | handleAction(increment, state => state + 1), 91 | handleAction(decrement, state => state - 1), 92 | handleAction(reset, (_, { payload }) => payload), 93 | ]) 94 | ``` 95 | 96 | #### Handle multiple actions in one handler: 97 | 98 | ```ts 99 | import { createActionCreator, createReducer } from 'deox' 100 | 101 | const fetch = { 102 | next: createActionCreator('FETCH_NEXT') 103 | complete: createActionCreator('FETCH_COMPLETE') 104 | error: createActionCreator('FETCH_ERROR') 105 | cancel: createActionCreator('FETCH_CANCEL') 106 | } 107 | 108 | const defaultState = false 109 | 110 | const isFetchingReducer = createReducer(defaultState, handleAction => [ 111 | handleAction(fetch.next, () => true), 112 | handleAction([fetch.complete, fetch.error, fetch.cancel], () => false) 113 | ]) 114 | ``` 115 | 116 | ## _getType(actionCreator)_ 117 | 118 | Get wrapped action type of an action creator. 119 | 120 | ### Arguments 121 | 122 | 1. **`actionCreator`** (**_ActionCreator_** ): an action creator. 123 | 124 | ### Returns 125 | 126 | (**_string_** ). The action type that the action creator wraps. 127 | 128 | ### Example 129 | 130 | ```ts 131 | import { createActionCreator, getType } from 'deox' 132 | 133 | const increment = createActionCreator('INCREMENT') 134 | 135 | getType(increment) //=> 'INCREMENT' 136 | ``` 137 | 138 | ## _ofType(keys)_ 139 | 140 | An RxJS operator that filters input actions according to the given action creator(s) or action(s) or action type(s). 141 | 142 | ### Arguments 143 | 144 | 1. **`keys`** (**_ActionCreator[]_** | **_Action[]_** | **_string[]_** ): 145 | 146 | ### Examples 147 | 148 | #### With action creator: 149 | 150 | ```ts 151 | import { createActionCreator, ofType } from 'deox' 152 | import { delay, mapTo } from 'rxjs/operators' 153 | 154 | const ping = createActionCreator('PING') 155 | 156 | const pingEpic = action$ => action$.pipe(ofType(ping), delay(1000), mapTo({ type: 'PONG' })) 157 | ``` 158 | 159 | #### With multiple action creators: 160 | 161 | ```ts 162 | import { createActionCreator, ofType } from 'deox' 163 | import { delay, mapTo } from 'rxjs/operators' 164 | 165 | const ping = createActionCreator('PING') 166 | const pong = createActionCreator('PONG') 167 | 168 | const pingPongEpic = action$ => action$.pipe(ofType([ping, pong]), delay(1000), mapTo({ type: 'DONE' })) 169 | ``` 170 | 171 | #### With action: 172 | 173 | ```ts 174 | import { createActionCreator, ofType } from 'deox' 175 | import { delay, mapTo } from 'rxjs/operators' 176 | 177 | const pingEpic = action$ => action$.pipe(ofType({ type: 'PING' }), delay(1000), mapTo({ type: 'PONG' })) 178 | ``` 179 | 180 | #### With action type: 181 | 182 | ```ts 183 | import { createActionCreator, ofType } from 'deox' 184 | import { delay, mapTo } from 'rxjs/operators' 185 | 186 | const pingEpic = action$ => action$.pipe(ofType('PING'), delay(1000), mapTo({ type: 'PONG' })) 187 | ``` 188 | 189 | ## _Action_ 190 | 191 | A type that creates Flux-standard compliant action. 192 | 193 | ## _AnyAction_ 194 | 195 | (**_Action_** ). 196 | 197 | ## _ActionType_ 198 | 199 | A type that infers action from (**_ActionCreator_** ) or (**_Reducer_** ). 200 | 201 | ## _DeepImmutable_ 202 | 203 | A type which gives any type as input and return corresponding **deeply** immutable data structure as output. 204 | 205 | ## _DeepImmutableObject_ 206 | 207 | A type which gives an `object` type as input and return corresponding **deeply** immutable data structure as output. 208 | 209 | ## _DeepImmutableMap_ 210 | 211 | A type which gives a `Map` type as input and return corresponding **deeply** immutable data structure as output. 212 | 213 | ## _DeepImmutableArray_ 214 | 215 | A type which gives an `Array` type as input and return corresponding \*\*deeply immutable data structure as output. 216 | 217 | ## _Immutable_ 218 | 219 | A type which gives any type as input and return corresponding **shallowly** immutable data structure as output. 220 | -------------------------------------------------------------------------------- /docs/faq.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: FAQ 3 | route: /faq 4 | --- 5 | 6 | # Frequently Asked Questions 7 | 8 | > **Time-saving tip**: notice that you can use Deox with almost all [Redux middlewares](https://redux.js.org/introduction/ecosystem#library-integration-and-bindings) without any problem. 9 | 10 | ## Using redux-thunk with Deox 11 | 12 | [Redux Thunk middleware](https://github.com/reduxjs/redux-thunk) allows you to write action creators that return a function instead of an action. 13 | The following codesandbox is a working example of using Redux Thunk middleware with Deox. 14 | 15 |