{"id":13608073,"url":"https://github.com/unirakun/k-redux-factory","last_synced_at":"2025-04-27T19:32:57.758Z","repository":{"id":35831366,"uuid":"94796603","full_name":"unirakun/k-redux-factory","owner":"unirakun","description":"Factory of Redux reducers and their associated actions and selectors.","archived":false,"fork":false,"pushed_at":"2022-12-09T08:16:01.000Z","size":2945,"stargazers_count":18,"open_issues_count":27,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-19T09:40:53.586Z","etag":null,"topics":["action","actions","factory","helper","nantes","reducer","reducers","redux","redux-reducers","selector","unirakun"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/unirakun.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-19T16:15:56.000Z","updated_at":"2023-11-07T12:45:52.000Z","dependencies_parsed_at":"2023-01-16T07:15:27.022Z","dependency_job_id":null,"html_url":"https://github.com/unirakun/k-redux-factory","commit_stats":null,"previous_names":["trampss/trampss-redux-factory"],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unirakun%2Fk-redux-factory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unirakun%2Fk-redux-factory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unirakun%2Fk-redux-factory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unirakun%2Fk-redux-factory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unirakun","download_url":"https://codeload.github.com/unirakun/k-redux-factory/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251196339,"owners_count":21550941,"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","actions","factory","helper","nantes","reducer","reducers","redux","redux-reducers","selector","unirakun"],"created_at":"2024-08-01T19:01:24.012Z","updated_at":"2025-04-27T19:32:57.398Z","avatar_url":"https://github.com/unirakun.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# k-redux-factory\n\nFactory of Redux reducers and their associated actions and selectors.\n\u003e Make your Redux code base tinier and simpler to maintain\n\n[![CircleCI](https://circleci.com/gh/unirakun/k-redux-factory.svg?style=shield)](https://circleci.com/gh/unirakun/k-redux-factory) [![Coverage Status](https://coveralls.io/repos/github/unirakun/k-redux-factory/badge.svg?branch=master)](https://coveralls.io/github/unirakun/k-redux-factory?branch=master) [![NPM Version](https://badge.fury.io/js/k-redux-factory.svg)](https://www.npmjs.com/package/k-redux-factory)\n[![npm bundle size](https://img.shields.io/bundlephobia/minzip/k-redux-factory)](https://bundlephobia.com/result?p=k-redux-factory@latest) [![Greenkeeper badge](https://badges.greenkeeper.io/unirakun/k-redux-factory.svg)](https://greenkeeper.io/)\n\n## Migrating\nHey ! If you come from an early version of `k-redux-factory` and want to upgrade, [you can read this migration guide 💎](./MIGRATING.md)\n\n## Contents\n - [Purpose](#purpose)\n - [Why ?](#why)\n - [Installation](#installation)\n - [Documentation](#documentation)\n - [API](./TYPES.md)\n\n## Purpose\n`k-redux-factory` creates generic reducers, actions and selectors in two lines.\n\n```es6\nimport { keyValue } from 'k-redux-factory'\nexport default keyValue({ path: 'api', name: 'todos' })\n```\nThat's it, you just exported the reducer function and now you can register it through combinerReducer in Redux.\n\nIn this example, we have a `todos` reducer, it has to be combined into `state.api.todos`.\n\nThe default `key` is `id`.\n\nYou can now use it to dispatch actions and select some datas from this reducer:\n```es6\nimport myReducer from './myReducer'\n\n// ...\n// add a todo\ndispatch(myReducer.add({ id: 1, title: 'Apply to some CFP', completed: false })\n\n// ...\n// select a todo\nmyReducer.get(1)(getState())\n```\n\nOne more thing, this lib handle state immutability for you !\n\nClick [right here to see the full API.](./TYPES.md)\n\n## Why\nWe like to write Redux code as simple as possible and use its middlewares to handle real world problems.\nFrom this point of view, our Redux code base is simpler : it's like a key/value store. But one drawback is the amount of duplicated code, each resource has its own reducers, actions and selectors.\n\nWe created this lightweight library, a factory of reducers, actions and selectors, to avoid inconsistency and painful maintainability from our growing Redux code base.\n\n## Installation\n - `yarn add k-redux-factory`\n - `npm i k-redux-factory`\n\n## Documentation\n - [factory](#factory)\n - [actions](#actions)\n - [selectors](#selectors)\n - [helpers](#helpers)\n\n### factory\nYou need to use the factory to get a new set of reducer/actions/selectors :\n```es6\n// modular factory\nimport { factory } from 'k-redux-factory'\n\n// or - prebuild simple factory\nimport { simple } from 'k-redux-factory'\n\n// or - prebuild simpleObject factory (DEPRECATED)\nimport { simpleObject } from 'k-redux-factory'\n\n// or - prebuild keyValue factory\nimport { keyValue } from 'k-redux-factory'\n```\n\nThere are multiple factories signatures, take you preferred between :\n - `factory(middlewares)(options)` : this is the root factory, with middlewares\n - `factory(options)` : this is the root factory, without middlewares\n - `simple(middlewares)(options)` : this is a `simple` factory with middlewares\n - `simple(options)` : this is a `simple` factory without middlewares\n - *DEPRECATED* `simpleObject(middlewares)(options)` : this is a `simpleObject` factory with middlewares\n - *DEPRECATED* `simpleObject(options)` : this is a `simpleObject` factory without middlewares\n - `keyValue(middlewares)(options)` : this is a `keyValue`  factory with middlewares\n - `keyValue(options)` : this is a `keyValue`  factory without middlewares\n\nParameters are :\n - **middlewares** (optional), contain an object with `pre` and `post` fields. Both are an array of middlewares to apply before and after the `core` middleware\n - **options** (mandatory), either a string representating the reducer `name`, either an object with these fields :\n   - **key** (exists only for the `keyValue` type -optional-), the field used to identify your objects (`id` is the default value)\n   - **path** (optional), where the reducer will be combined via `combineReducer`\n     - if empty, the reducer will be register at the root level of the redux state\n     - you can use dot notation, like `api.raw`: your reducer will be combined into `state.api.raw.\u003cyour_reducer\u003e`\n   - **name** (mandatory), the reducer name (for instance: `todos`)\n     - it's used to generate actions types\n     - it's used to retrieve informations from selectors\n   - **prefix** (optional) is added to actions to avoid some collisions when there are two reducers with the same name in two distincts paths\n   - **type** (optional) can be `keyValue` or `simple.\u003ctype\u003e` (default is `keyValue`)\n   - **defaultData** (optional), set the default data value, used by `reset` action and for initialisation (default is an empty object `{}` for `simple.object` and default hashmap model for `keyValue` - see [keyValue types section](./TYPES.md#state))\n\nExample:\n - this reducer will use `id` as key field\n - it's combined into `state.api.raw`\n - it's name is `todos`\n - have default data\n```es6\nimport { factory } from 'k-redux-factory'\n\nexport default factory({ path: 'api.raw', name: 'todos' })\n```\n\nData will be stored into `state.api.raw.todos`.\n\n### [Types](./TYPES.md)\nTypes are :\n  - `keyValue` : your state is a hashmap, useful to bind your API to Redux with the following redux state model :\n```es6\n{\n  data: [\n    [\u003ckey1\u003e, \u003cinstance1\u003e],\n    [\u003ckey2\u003e, \u003cinstance2\u003e],\n  ],\n  initialized: true,\n}\n```\n\n  - `simple` : your state is directly your `\u003cinstance\u003e`. **This implies that you can not set undefined.**\n  - *DEPRECATED* `simpleObject` : your state is directly your `\u003cinstance\u003e`. **This implies that you can not set undefined.**\n\nDefault type is `keyValue`.\n\n### reducer\nThe previous factory returns a function which is a reducer.\nYou just have to combine it like any other reducer :\n```es6\nimport { createStore, combineReducers, compose, applyMiddleware } from 'redux'\n\n// import your reducer\n// (created by k-redux-factory)\nimport todos from './myTodosReducer'\n\n// create your Redux store as usual\nconst store = createStore(\n  combineReducers({\n    // [other reducer]\n    api: combineReducers({\n      // [other reducer]\n      raw: combineReducers({\n        // import your reducer into api.raw\n        // since we configured this path\n        todos,\n      }),\n      // [other reducer]\n    }),\n    // [other reducer]\n  }),\n  /* your Redux middlewares */\n)\n\nexport default store\n```\n\n#### Exemple keyValue with default state\n```es6\nimport { keyValue } from 'k-redux-factory'\n\nconst defaultData = [\n  {\n    id: 1,\n    todo: 'write README.MD',\n  },\n  {\n    id: 2,\n    todo: 'watch rick and morty season three',\n  },\n]\n\nexport default keyValue({ defaultData })\n```\n\n```es6\n{\n  data: [\n    [1, { id: 1, todo: 'write README.MD' }],\n    [2, { id: 2, todo: 'watch rick and morty season three' }],\n  ],\n  initialized: true,\n}\n```\n\n### actions\nThe factory returns a function (this is the reducer) that also contains actions and selectors as fields.\nSome generic actions are available. By now, it's not possible to add custom ones.\n\nTo see them go to [TYPES.md](./TYPES.md).\n\nExample, we set todos to our typed `keyValue` reducer:\n```es6\n// import your reducer\n// (created by k-redux-factory)\nimport todos from './myTodosReducer'\n\n// dispatch can be given by one of your middleware (redux-thunk, redux-saga, etc)\n// or it can be given by react-redux for example (mapDispatchToProps)\ndispatch(\n  // set todos\n  todos.set([\n    {\n      id: '1', // we set 'id' as key in the factory\n      visible: true,\n      label: 'My first todo',\n    },\n    {\n      id: '2',\n      visible: false,\n      label: 'This todo is done',\n    },\n  ])\n)\n```\n\nYou can also retrieve action name like this : `todos.SET`\n\n### selectors\nThe factory returns a function (this is the reducer) that also contains actions and selectors as fields.\nSome generic selectors are available. By now, it's not possible to add custom ones.\n\nTo see them go to [TYPES.md](./TYPES.md).\n\nExample, we retrieve the todo with id `1`:\n```es6\n// import your reducer\n// (created by k-redux-factory)\nimport todos from './myTodosReducer'\n\n// state can be given by one of your middleware (redux-thunk, redux-saga, etc)\n// or it can be given by react-redux for example (mapStateToProps)\ntodos.get('1')(state)\n```\n### helpers\n\n| signature | description | comment |\n|---|---|---|\n|`mapAction(\u003cmapper(action)\u003e)`| create middleware and map only redux action | mapper(action) is mandatory |\n|`mapState(\u003cregex\u003e)(\u003cmapper(state)\u003e)`| create middleware and map the state of the corresponding redux actions type by the regex |\n|`reducer(\u003cyourReducer(action, state)\u003e)`| create a middleware from a standard redux reducer |\n|`mapPayload(\u003cregex\u003e)(\u003cmapper(payload)\u003e)`| create middleware and map the payload of the corresponding redux actions type by the regex |\n\n#### Example, we create a middleware but we modify only the action :\n```es6\nimport { factory } from 'k-redux-factory'\n// import your helpers\nimport { mapAction } from 'k-redux-factory/helpers'\n\n// define a function to map action\nconst mapper = action =\u003e ({ ...action, type: `SET_${action.type}` })\n// create your reducer and transform the type of action before core middleware\nexport default factory({ pre: [mapAction(mapper)] })({ path: 'api.raw', name: 'todos' })\n```\n\n#### Example, we create a middleware but we modify only the state :\n```es6\nimport { factory } from 'k-redux-factory'\n// import your helpers\nimport { mapState } from 'k-redux-factory/helpers'\n\n// define a function to change state\nconst mapper = state =\u003e ({...state, todos: 'TODO_CHANGED'})\n// create your reducer and transform the state before core middleware\nexport default factory({ pre: [mapState(/SET\u003eTODOS/)(mapper)] })({ path: 'api.raw', name: 'todos' })\n```\n\n#### Example, we create a middleware but we modify action and state :\n```es6\nimport { factory } from 'k-redux-factory'\n// import your helpers\nimport { reducer } from 'k-redux-factory/helpers'\n\n// define a function to map state depending on the action\nconst mapper = (action, state) =\u003e {\n  switch (action.type) {\n    case 'SET_TODOS': return { todos: 'TODOS_CHANGED' }\n    case 'LOG_TODOS': console.log(state)\n    default: return state\n  }\n}\n// create your reducer and transform the action and state before core middleware\nexport default factory({ pre: [reducer(mapper)] })({ path: 'api.raw', name: 'todos' })\n```\n\n#### Example, we create a middleware but we modify only the payload :\n```es6\nimport { factory } from 'k-redux-factory'\n// import your helpers\nimport { mapPayload } from 'k-redux-factory/helpers'\n\n// define a function to map payload\nconst mapper = payload =\u003e payload.map(p =\u003e ({ ...p, id: `ID_${p.id}` }))\n// create your reducer and transform the payload before core middleware\nexport default factory({ pre: [mapPayload(/SET\u003eTODOS/)(mapper)] })({ path: 'api.raw', name: 'todos' })\n```\n\n# About [uni rakun](https://unirakun.fr)\n**uni rakun** is created by two passionate french developers.\n\nDo you want to contact them ? Go to their [website](https://unirakun.fr)\n\n\u003ctable border=\"0\"\u003e\n \u003ctr\u003e\n  \u003ctd align=\"center\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/26094222?s=460\u0026v=4\" width=\"100\" /\u003e\u003c/td\u003e\n  \u003ctd align=\"center\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/17828231?s=460\u0026v=4\" width=\"100\" /\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/guillaumecrespel\"\u003eGuillaume CRESPEL\u003c/a\u003e\u003c/td\u003e\n  \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/fabienjuif\"\u003eFabien JUIF\u003c/a\u003e\u003c/td\u003e\n\u003c/table\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funirakun%2Fk-redux-factory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funirakun%2Fk-redux-factory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funirakun%2Fk-redux-factory/lists"}