{"id":17610028,"url":"https://github.com/darnfish/ramsay","last_synced_at":"2026-04-30T00:03:30.126Z","repository":{"id":63921611,"uuid":"535975983","full_name":"darnfish/ramsay","owner":"darnfish","description":"Simple API for Redux Reducers","archived":false,"fork":false,"pushed_at":"2023-02-08T08:22:18.000Z","size":95,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-26T01:23:14.799Z","etag":null,"topics":["redux","state"],"latest_commit_sha":null,"homepage":"","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/darnfish.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-13T05:43:55.000Z","updated_at":"2025-08-21T09:12:40.000Z","dependencies_parsed_at":"2023-02-12T14:03:02.298Z","dependency_job_id":null,"html_url":"https://github.com/darnfish/ramsay","commit_stats":{"total_commits":12,"total_committers":2,"mean_commits":6.0,"dds":0.25,"last_synced_commit":"c15840e59622bbe79b59afd608cc500e04e91dd3"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/darnfish/ramsay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darnfish%2Framsay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darnfish%2Framsay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darnfish%2Framsay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darnfish%2Framsay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darnfish","download_url":"https://codeload.github.com/darnfish/ramsay/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darnfish%2Framsay/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32448883,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T22:27:22.272Z","status":"ssl_error","status_checked_at":"2026-04-29T22:10:49.234Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["redux","state"],"created_at":"2024-10-22T17:43:03.668Z","updated_at":"2026-04-30T00:03:30.111Z","avatar_url":"https://github.com/darnfish.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ramsay\nSimple API for Redux Reducers.\n\nIf your Redux store looks like `store.users[id] = userObject`, then Ramsay is for you.\n\n## Installation\n```\nyarn add ramsay\n```\n\n## Usage\n```tsx\nimport Ramsay from 'ramsay'\n\ninterface User {\n\tid: string\n\tname: string\n}\n\nconst users = new Ramsay\u003cUser\u003e('users') // for non-TS users: const users = new Ramsay('users')\n\n/**\n * If you have a different field for your object id, or a different type (default is string):\n * new Ramsay\u003c{ _id: number }, '_id'\u003e('users', { idKey: '_id' })\n **/\n\n// This is your reducer\nconst reducer = users.createReducer()\nconst { store, dispatch } = configureStore({ reducer })\n\n// This is how you add/update a single object\ndispatch(users.update({ id: 1, name: 'William' }))\n\nconsole.log(store) // { 1: { id: 1, name: 'William' } }\n\n// This is how you add/update multiple objects\ndispatch(users.updateMany([{ id: 2, name: 'Walter' }, { id: 3, name: 'Jesse' }]))\n\nconsole.log(store) // { 1: { id: 1, name: 'William' }, 2: { id: 2, name: 'Walter' }, 3: { id: 3, name: 'Jesse' } }\n\n// This is how you remove a single object\ndispatch(users.remove(1))\n\nconsole.log(store) // { 2: { id: 2, name: 'Walter' }, 3: { id: 3, name: 'Jesse' } }\n\n// This is how you remove multiple objects\ndispatch(users.removeMany([2, 3]))\n\nconsole.log(store) // {}\n```\n\n### Custom Id Field and/or Type\nYou can customize which field Ramsay will use for indexing, in addition to the type of that field.\n\nBy default, Ramsay will scan for `id` on your object and assume it is a string.\n\nTo change this, adjust the following:\n```ts\nimport Ramsay from 'ramsay'\n\ninterface User {\n\t_id: number\n\tname: string\n}\n\nconst users = new Ramsay\u003cUser, '_id'\u003e('users', { idKey: '_id' })\n// for non-TS users: const users = new Ramsay('users', { idKey: '_id' })\n```\n\nIf you're using TypeScript, Ramsay will automatically pick up the type of your id key field.\n\n### Extending Reducers\nYou can add your own custom actions ontop of Ramsay using `extend` parameter on the `createReducer` method:\n```ts\nconst reducer = users.createReducer((state, action, prefix) =\u003e {\n\tswitch(action.type) {\n\tcase `${PREFIX}/CUSTOM_ACTION`:\n\t\treturn users.withState(state).manuallyUpdateObject(action.userId, oldUser =\u003e ({ counter: oldUser.counter + 1 }))\n\t}\n})\n```\n\nThese additional actions will not take priority over Ramsay's built-in reducers for `update`, `updateMany`, `remove`, and `removeMany`.\n\n### Dispatch Functions\nRamsay can create custom dispatch functions which you can use to avoid importing your reducer. See below:\n```ts\nconst users = new Ramsay('users')\n\nconst updateUser = users.createUpdateMethod()\n\nupdateUser({ id: 1, name: 'William' })\n```\n\nYou can also pass in a default set of options into this create method. They will not take priority over any options declared inside the generated method.\n\n```ts\nconst updateUsers = users.createUpdateManyMethod({ mapObject: user =\u003e ({ ...user, customChange: 1 }) })\n\nupdateUsers([{ id: 1, name: 'William' }])\n\n// { 1: { id: 1, name: 'William', customChange: 1 } }\n```\n\n### Plural and Singular Overrides\nRamsay attempts to figure out the singular and plural versions of your model name for internal use. For example:\n```\nusers:\n- singular: user\n- plural: users\n\nmessages:\n- singular: message\n- plural: messages\n\neventEnrollments:\n- singular: eventEnrollment\n- plural: eventEnrollments\n```\n\nIn some instances, Ramsay can't figure out a singular or plural version of your model name (for instance, `cash`).\n\nYou can provide your own custom singular/plural names in the options:\n```ts\nnew Ramsay('cash', {\n\tplurals: {\n\t\tplural: 'cashes',\n\t\tsingular: 'cash'\n\t}\n})\n```\n\n### Useful Information\n* By default, an action with the type `RESET` will reset the state to a default empty object (`{}`). You can disable this functionality by setting `options.disableResetAction` to `true` in your initial config (e.g. `new Ramsay('users', { disableResetAction: true })`)\n\n## License\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarnfish%2Framsay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarnfish%2Framsay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarnfish%2Framsay/lists"}