{"id":13679672,"url":"https://github.com/the-dr-lazy/deox","last_synced_at":"2025-08-28T17:31:01.079Z","repository":{"id":38173275,"uuid":"165498414","full_name":"the-dr-lazy/deox","owner":"the-dr-lazy","description":"Functional Type-safe Flux Standard Utilities","archived":false,"fork":false,"pushed_at":"2022-12-12T10:34:08.000Z","size":4233,"stargazers_count":206,"open_issues_count":19,"forks_count":12,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-12-18T08:11:29.574Z","etag":null,"topics":["action","action-creator","deox","flux","ngrx","reducer","redux","typesafe-actions","typescript"],"latest_commit_sha":null,"homepage":"https://deox.js.org","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/the-dr-lazy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-13T11:43:47.000Z","updated_at":"2024-02-26T19:43:21.000Z","dependencies_parsed_at":"2023-01-27T18:01:11.403Z","dependency_job_id":null,"html_url":"https://github.com/the-dr-lazy/deox","commit_stats":null,"previous_names":["thebrodmann/deox"],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-dr-lazy%2Fdeox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-dr-lazy%2Fdeox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-dr-lazy%2Fdeox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-dr-lazy%2Fdeox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/the-dr-lazy","download_url":"https://codeload.github.com/the-dr-lazy/deox/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231287319,"owners_count":18353182,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["action","action-creator","deox","flux","ngrx","reducer","redux","typesafe-actions","typescript"],"created_at":"2024-08-02T13:01:08.221Z","updated_at":"2024-12-25T22:08:26.486Z","avatar_url":"https://github.com/the-dr-lazy.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eDeox\u003c/h1\u003e\n\n\u003ch3 align=\"center\"\u003eFunctional type-safe Flux standard utilities\u003c/h3\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"LICENSE\"\u003e\n    \u003cimg alt=\"License\" src=\"https://img.shields.io/npm/l/deox.svg?logo=License\u0026style=flat-square\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://circleci.com/gh/thebrodmann/deox\"\u003e\n    \u003cimg alt=\"Build Status\" src=\"https://img.shields.io/circleci/project/github/thebrodmann/deox/master.svg?label=build\u0026logo=circleci\u0026style=flat-square\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/thebrodmann/deox\"\u003e\n    \u003cimg alt=\"Coverage Status\" src=\"https://img.shields.io/codecov/c/gh/thebrodmann/deox.svg?style=flat-square\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/semantic-release/semantic-release\"\u003e\n    \u003cimg alt=\"Semantic Release\" src=\"https://img.shields.io/badge/%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/deox\"\u003e\n    \u003cimg alt=\"Latest Release\" src=\"https://img.shields.io/npm/v/deox.svg?label=npm%40latest\u0026style=flat-square\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"CONTRIBUTING.md\"\u003e\n    \u003cimg alt=\"PRs welcome\" src=\"https://img.shields.io/badge/PRs-welcome-green.svg?style=flat-square\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nThe 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)).\n\nBehold, the art of Deox:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Deox counter example\" src=\"docs/media/counter-example.jpg\"\u003e\n\u003c/p\u003e\n\n## Highlights\n\n-   **Minimalist** (almost no import cost) - checkout [Bundle Phobia](https://bundlephobia.com/result?p=deox@latest).\n-   **Simple** - focused on self-declarative API.\n-   **Secure** - complete test-suits for all of the edge and corners.\n\n## Motivation\n\nThe most common complaint about Flux is how it makes you write a lot of boilerplate.\nAlso, existing solutions like redux-actions or redux-starter-kit are not type-safe by the idea (although there are some other ideas with classes 😱).\n\nSo, this is where Deox takes place to **make maintenance of Flux architecture simpler and more readable** by sticking to **functional programming paradigm**.\n\n## Installation\n\nYou can install Deox package by running:\n\n```bash\n# YARN\nyarn add deox\n\n# NPM\nnpm install deox\n```\n\n\u003e **Typescript tip**: notice that Deox internally uses some ES2015 type definitions to represent better developer experience.\n\u003e So if you are using [`Typescript`](https://github.com/Microsoft/TypeScript) and targeting `es5`, be sure `es2015` lib has been added in tsconfig.json:\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"target\": \"es5\",\n    \"lib\": [\"es2015\"]\n  }\n}\n```\n\nThe 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/).\n\nIf 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:\n\n```html\n\u003cscript src=\"https://unpkg.com/deox@latest\"\u003e\u003c/script\u003e\n```\n\n## Usage\n\n```ts\nimport { createActionCreator, createReducer } from 'deox'\n\nconst increment = createActionCreator('INCREMENT')\nconst decrement = createActionCreator('DECREMENT')\nconst reset = createActionCreator('RESET', resolve =\u003e (count: number) =\u003e resolve(count))\n\nconst defaultState = 0\n\nconst counterReducer = createReducer(defaultState, handleAction =\u003e [\n    handleAction(increment, state =\u003e state + 1),\n    handleAction(decrement, state =\u003e state - 1),\n    handleAction(reset, (_state, { payload }) =\u003e payload),\n])\n\ncounterReducer(undefined, increment()) //=\u003e 1\ncounterReducer(undefined, decrement()) //=\u003e -1\ncounterReducer(3, reset(0)) //=\u003e 0\n```\n\n## Documentation\n\n-   [Introduction](https://deox.js.org)\n-   [Getting started](https://deox.js.org/getting-started)\n-   [API reference](https://deox.js.org/api-reference)\n-   [FAQ](https://deox.js.org/api-reference)\n    -   [Using redux-thunk with Deox](https://deox.js.org/faq#using-redux-thunk-with-deox)\n    -   [Using redux-saga with Deox](https://deox.js.org/faq#using-redux-saga-with-deox)\n    -   [Using redux-observable with Deox](https://deox.js.org/faq#using-redux-observable-with-deox)\n\n## FAQ\n\n### Why not `redux-actions`, `redux-starter-kit` ?\n\nBoth `redux-actions` and `redux-starter-kit` are neat and almost similar to each other.\nActually `deox` is similar to those projects in the idea, but not in implementation and promise.\nThe main goal of `deox` is to use the full power of **type-safety** and **type inferring** in typescript.\nIf you have some experience with those libraries, the following piece of code should be familiar for you:\n\n```ts\ntype Actions\n  = ReturnType\u003ctypeof addTodo\u003e\n  | ReturnType\u003ctypeof removeTodo\u003e\n  | ReturnType\u003ctypeof editTodo\u003e\n\nconst todosReducer = createReducer\u003cState, Actions\u003e(...)\n```\n\nThis is horrible; Why define a type like actions that a reducer can handle?! It's completely obvious which actions a reducer handles.\n\nOn 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:\n\n```ts\nconst todosReducer = createReducer\u003cState, Actions\u003e(defaultState, {\n  [addTodo]: (state, action) =\u003e {...}, // action: Actions\n  [removeTodo]: (state, action) =\u003e {...}, // action: Actions\n  [editTodo]: (state, action) =\u003e {...}, // action: Actions\n})\n```\n\nType of action parameter in `addTodo` action handler is overall `Actions` type. It's inaccurate!\n\nAnd this is where Deox comes in action and practice:\n\n```ts\nconst todosReducer = createReducer(defaultState, handleAction =\u003e [\n  handleAction(addTodo, (state, action) =\u003e {...}), // action: AddTodoAction\n  handleAction(removeTodo, (state, action) =\u003e {...}), // action: RemoveTodoAction\n  handleAction(editTodo, (state, action) =\u003e {...}) // action: EditTodoAction\n])\n```\n\nThat'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.\nAnd every action handler's type is just what it should be. It's completely safe and correct!\n\n### What's the difference with `typesafe-actions` ?\n\nThe `typesafe-actions` is a great project that Deox carries huge inspiration from that.\nBut `typesafe-actions` doesn't have any plan for a complete set of utilities (specially reducers); **It's all about actions and action creators**.\n\n## Versioning\n\nDeox uses [Semantic Versioning 2.0.0](https://semver.org/)\n\n## Contributing\n\nPlease read through our [contributing guidelines](CONTRIBUTING.md).\n\n## Inspiration\n\n-   [redux-actions](https://github.com/redux-utilities/redux-actions) - Flux Standard Action utilities for Redux\n-   [typesafe-actions](https://github.com/piotrwitek/typesafe-actions) - Typesafe Action Creators for Redux / Flux Architectures (in TypeScript)\n\n## License\n\nDeox is released under [MIT license](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthe-dr-lazy%2Fdeox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthe-dr-lazy%2Fdeox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthe-dr-lazy%2Fdeox/lists"}