{"id":18799611,"url":"https://github.com/l2silver/erschema-redux-immutable","last_synced_at":"2026-01-02T20:30:16.718Z","repository":{"id":97819227,"uuid":"105184261","full_name":"l2silver/erschema-redux-immutable","owner":"l2silver","description":null,"archived":false,"fork":false,"pushed_at":"2017-10-22T17:58:59.000Z","size":70,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-29T18:34:59.126Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/l2silver.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2017-09-28T18:23:17.000Z","updated_at":"2018-02-11T18:26:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"b82c6569-d060-42eb-8007-3e19e3516b9c","html_url":"https://github.com/l2silver/erschema-redux-immutable","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/l2silver%2Ferschema-redux-immutable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/l2silver%2Ferschema-redux-immutable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/l2silver%2Ferschema-redux-immutable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/l2silver%2Ferschema-redux-immutable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/l2silver","download_url":"https://codeload.github.com/l2silver/erschema-redux-immutable/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239727900,"owners_count":19687267,"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":[],"created_at":"2024-11-07T22:15:54.085Z","updated_at":"2026-01-02T20:30:16.675Z","avatar_url":"https://github.com/l2silver.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# erschema-redux-immutable\n\nA smart immutablejs library for managing the redux-store\n\n### Basic Concepts\n\nRedux applications all have a few key components. Reducers to change the store's state, actions to trigger the reducer, and selectors to pull data from the store.\nMost applications will write a custom function for each case in a reducer function, which generally require custom actions to trigger the reducer, and custom selectors to retreive the data.\nerschema-redux-immutable uses standard RESTful reducers and actions, which also results in a standardized store state that is easy to select data from.\n\n### Redux Store\n\nThe erschema-redux-immutable provides a reducer function that stores data in two basic places: Entities, and Relationships.\n\n```\nimport {Record, Map} from 'immutable'\n// Example redux store with erschema\n{\n  other store properties...,\n  erschema: {\n    entities: {\n      users: Map\u003c{\n        id: UserRecord\u003c{id, name}\u003e\n      }\u003e\n    },\n    relationships: {\n      users: Map\u003c{\n        friends: Map\u003c{\n          [userId]: OrderedList\u003cfriendId\u003e (For one to many relationships) || friendId (for one to one relationships)\n        }\u003e\n      }\u003e\n    }\n  }\n}\n```\n\n#### Schemas\n\nerschema-redux-immutable uses [erschema](https://github.com/l2silver/erschema) schemas to normalize data, and construct the structure of the redux-store\n\n```\nimport {combineReducers} from 'redux'\nimport standardizeSchema from 'erschema-redux-immutable/schemas'\nimport erschemaReducer from 'erschema-redux-immutable/reducers'\n\nconst usersSchema = standardizeSchema({\n  properties: string[] | {[key: string]: any},\n  idFunc: (entity)=\u003eentity.id,\n  modifier: (ent)=\u003eent,\n  premodifier: (ent)=\u003eent\n  Model: UserModel,\n  relationships: [\n      {\n        name: 'friends',\n        entityName: 'users',\n      }\n    ],\n  },\n})\n\n// standardizeSchema has one purpose, it takes the known properties of a model and blacklists all other properties using a modifier function that pipes into any other modifier functions. This is especially useful when dealing with Immutable.Record models that actually error out when the wrong properties are passed to it for certain actions.\n\ncombineReducers({\n  ...otherReducers,\n  erschemaReducer({\n    schemas: {\n      users,\n    }\n  })\n})\n\n===\u003e creates a redux store with the following structure\n\n{\n  ...otherReducers,\n  erschema: {\n    entities: Map\u003c{\n      users: Map\u003c{\n      }\u003e\n    }\u003e,\n    relationships: Map\u003c{\n      users: Map\u003c{\n        friends: Map\u003c{}\u003e\n      }\u003e\n    }\u003e\n  }\n}\n\n```\n\n\n### Handlers\n\n#### The standardize erschema handlers for relationships are:\n\n```\nimport {\n  link,\n  unlink,\n  create,\n  index,\n  concat,\n  reorder,\n\n} from 'erschema-redux-immutable/handlers/relationships\n```\n\n##### link\n\nAdds a relatedEntityId to a relationship for one-to-many relationships, or for one-to-one relationship, changes relatedEntityId value\n\n```\n// Relationship change for links one-to-many and one-to-one respectively\n{\n  [entityId]: [] ===\u003e [relatedEntityId] || 0 ===\u003e relatedEntityId \n}\n```\n\n##### unlink\n\nRemoves a relatedEntityId from a relationship for one-to-many relationships, or for one-to-one relationship, changes relatedEntityId value to 0\n\n```\n// Relationship change for links one-to-many and one-to-one respectively\n{\n  [entityId]: [relatedEntityId] ===\u003e [] || relatedEntityId ===\u003e 0\n}\n```\n\n##### create\n\nCreates a relationship entry for an entityId\n```\n// Relationship created for links one-to-many and one-to-one respectively\n{} ===\u003e {\n        [entityId]: [relatedEntityId] || relatedEntityId \n      }\n```\n\n##### index\n\nCreates a relationship entry for multiple entity ids\n```\n// Relationship created for links one-to-many and one-to-one respectively\n{} ===\u003e {\n        [entityId]: [relatedEntityId] || relatedEntityId ,\n        [entityId2]: [relatedEntityId2] || relatedEntityId2 ,\n        [entityId3]: [relatedEntityId3] || relatedEntityId3 \n      }\n```\n\n##### concat\n\nAdds multiple relatedEntityIds to an existing relationship for multiple\n```\n{\n  [entityId]: [relatedEntityId] ===\u003e [relatedEntityId, relatedEntityId2, relatedEntityId3]\n}\n```\n\n##### reorder\n\nReorders relationship\n```\n{\n  [entityId]: [relatedEntityId, relatedEntityId2, relatedEntityId3] ===\u003e [relatedEntityId2, relatedEntityId, relatedEntityId3]\n}\n```\n\n#### The standardized erschema handlers for entities are:\n```\nimport {\n  create\n  update\n  remove\n  get\n  index\n} from 'erschema-redux-immutable/handlers/entities\n```\n\n##### create\n\ncreates an entity\n```\n{\n  data: {} ===\u003e {\n                  [entityId]: entity \n                }\n}\n```\n\n##### update\n\nupdates an entity\n```\n{\n  data: {\n   [entityId]: entity ===\u003e entity2\n  }\n}\n```\n\n##### remove\n\nremoves an entity\n```\n{\n  data: {[entityId]: entity} ===\u003e {}\n}\n```\n\n##### get\n\nsimilar to create entity except merges with previous existing entity if it exists\n```\n{\n  data: {} ===\u003e {\n                  [entityId]: entity \n                }\n}\n```\n\n##### index\n\nsimilar to get except takes an array of entities instead of just one\n```\n{\n  data: {} ===\u003e {\n                  [entityId]: entity,\n                  [entityId]: entity,\n                  [entityId]: entity,\n                }\n}\n```\n\n### Reducers\n\nThe handlers above are stored in reducers for specific entities and relationships\n\n#### Entity Reducers\n\nrecall that reduxStore has the following shape\n\n```\n  {\n    entities: {\n      users: Map\u003c{\n        id: UserRecord\u003c{id, ...}\u003e\n      }\u003e\n    },\n    relationships: ...,\n  }\n```\n\nThe entity reducer has the following state structure:\n\n```\nMap\u003c{\n  id: UserRecord\u003c{id, ...}\u003e\n}\u003e\n```\n\nThe entity reducer has all of the standard entity handlers built in to it.\n\n```\nimport entityReducer from 'erschema-redux-immutable/reducers/entities'\n\nconst userEntityReducer = entityReducer({\n  name: 'users',\n  ---\n  Model: UserModel,\n  or\n  modelGenerator: (ent)=\u003eent.inactive ? new InActiveUser(ent) : new ActiveUser(ent),\n  ---\n  otherActions: Object of additional handlers to put in reducer\n  defaultStateConfig: A plain javascript object to be wrapped by the immutable Map\n})\n```\n\n\n#### Relationship Reducers\n\nrecall that reduxStore has the following shape\n\n```\n  {\n    entities: ...,\n    relationships: {\n      users: Map\u003c{\n        friends: Map\u003c{\n          [userId]: OrderedList\u003cfriendId\u003e (For one to many relationships) || friendId (for one to one relationships)\n        }\u003e\n      }\u003e\n    }\n  }\n```\n\nthe relationship reducer acts on the users relationship map, and encompasses:\n\n```\nMap\u003c{\n  friends: Map\u003c{\n    [userId]: OrderedList\u003cfriendId\u003e (For one to many relationships) || friendId (for one to one relationships)\n  }\u003e\n}\u003e\n```\n\nThis relationship reducer has all of the standard relationship handlers in addition to handlers for specific entity remove actions. The latter is used to clean relationship data when entities are deleted from the redux store, and in order for the reducer to do this, it must understand the relationship schema for a specific entity schema.\n\n```\nimport relationshipReducer from 'erschema-redux-immutable/reducers/relationships'\nconst userRelationshipReducer = relationshipReducer({\n  entityName: 'users',\n  relationshipSchema: [{\n    name: 'friends',\n    entityName: 'users,\n  }]\n})\n```\n\nThis way, when a user is deleted, the reducer knows to look through those relationships for the deleted id, and remove it.\n\n### Erschema-Redux-Immutable Reducer\n\nThe entity and relationship reducers can be used as directed above, but you can also use the generateErschemaReduxImmutableReducer to generate the entity reducers and relationship reducers for all of the entities in the schema.\n\n```\nimport generateErschemaReduxImmutableReducer from 'erschema-redux-immutable'\nimport usersSchema from './schemas/users'\n\nconst erschemaReduxImmutableReducer = generateErschemaReduxImmutableReducer({\n  schema: {\n    users: usersSchema\n  }\n})\n```\n\n### Actions\n\nAll standard actions are paired with their respective handlers to complete state changes\n\n#### The standardize erschema actions for relationships are:\n\n```\nimport {\n  link,\n  unlink,\n  create,\n  index,\n  concat,\n  reorder,\n\n} from 'erschema-redux-immutable/actions/relationships\n\ntype $id = string | number;\ntype $relationship = {\n  relationshipName: string,\n  id: $id,\n  relationshipValue: $id | $id[]\n};\n\ntype $relationships = {\n  name: string;\n  idValuePairs: Array\u003c{id: $id, value: $id | $id[]}\u003e;\n};\n\ntype $changeRelationshipOrder = {\n  name: string,\n  id: $id,\n  originalOrdinal: number,\n  ordinal: number,\n}\n```\n\n##### link\n\nlink(entityName, $relationship, ?error)\n\n##### unlink\n\nunlink(entityName, $relationship, ?error)\n\n##### create\n\ncreate(entityName, $relationship, ?error)\n\n##### index\n\nindex(entityName, $relationships, ?error)\n\n##### concat\n\nconcat(entityName, $relationships, ?error)\n\n##### reorder\n\nreorder(entityName, $changeRelationshipOrder, ?error)\n\n\n#### The standardized erschema actions for entities are:\n```\nimport {\n  create\n  update\n  remove\n  get\n  index\n} from 'erschema-redux-immutable/actions/entities\n\ntype $entity = {id: $id, ...}\n```\n\n##### create\n\ncreate(entityName: string, entity: $entity, error?: boolean)\n\n##### update\n\nupdate(entityName: string, entity: $entity, error?: boolean)\n\n##### remove\n\nremove(entityName: string, entityId: $id, error?: boolean)\n\n##### get\n\nget(entityName: string, entity: $entity, error?: boolean)\n\n##### index\n\nindex(entityName: string, entities: $entity[], error?: boolean)\n\n### The Normalize Action\n\n```\nimport normalizeActions from 'erschema-redux-immutable/actions/normalize'\nimport schema from './schema'\n\nconst userWithNestedData = {\n  id: 1,\n  name: 'Example',\n  friends: [{\n    id: 2,\n    name: 'Another Example',\n  }]\n}\n\nnormalizeActions('users', userWithNestedData, schema)\n===\u003e\n{\n  indexEntities: [{\n    type: 'INDEX_USERS',\n    payload: {\n      entities: [\n        {\n          id: 1,\n          name: 'Example'\n        },\n        {\n          id: 2,\n          name: 'Another Example'\n        }\n      ]\n    }\n  }],\n  indexRelationships: [{\n    type: 'INDEX_RELATIONSHIP_USERS',\n    payload: {\n      relationships: {\n        id: 1,\n        idValues: [2]\n      }\n    }\n  }]\n}\n```\nAs you can see, normalizeActions breaks down a nested object into an array of entity and relationship index actions. You can use your own batched action mechanism for handling these actions in a performant way, like redux-batched-actions.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fl2silver%2Ferschema-redux-immutable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fl2silver%2Ferschema-redux-immutable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fl2silver%2Ferschema-redux-immutable/lists"}