{"action":"created","issue":{"url":"https://api.github.com/repos/ngxs/store/issues/545","repository_url":"https://api.github.com/repos/ngxs/store","labels_url":"https://api.github.com/repos/ngxs/store/issues/545/labels{/name}","comments_url":"https://api.github.com/repos/ngxs/store/issues/545/comments","events_url":"https://api.github.com/repos/ngxs/store/issues/545/events","html_url":"https://github.com/ngxs/store/issues/545","id":350934177,"node_id":"MDU6SXNzdWUzNTA5MzQxNzc=","number":545,"title":"Proposal: Patch Operators","user":{"login":"markwhitfeld","id":1948265,"node_id":"MDQ6VXNlcjE5NDgyNjU=","avatar_url":"https://avatars0.githubusercontent.com/u/1948265?v=4","gravatar_id":"","url":"https://api.github.com/users/markwhitfeld","html_url":"https://github.com/markwhitfeld","followers_url":"https://api.github.com/users/markwhitfeld/followers","following_url":"https://api.github.com/users/markwhitfeld/following{/other_user}","gists_url":"https://api.github.com/users/markwhitfeld/gists{/gist_id}","starred_url":"https://api.github.com/users/markwhitfeld/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markwhitfeld/subscriptions","organizations_url":"https://api.github.com/users/markwhitfeld/orgs","repos_url":"https://api.github.com/users/markwhitfeld/repos","events_url":"https://api.github.com/users/markwhitfeld/events{/privacy}","received_events_url":"https://api.github.com/users/markwhitfeld/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":{"login":"markwhitfeld","id":1948265,"node_id":"MDQ6VXNlcjE5NDgyNjU=","avatar_url":"https://avatars0.githubusercontent.com/u/1948265?v=4","gravatar_id":"","url":"https://api.github.com/users/markwhitfeld","html_url":"https://github.com/markwhitfeld","followers_url":"https://api.github.com/users/markwhitfeld/followers","following_url":"https://api.github.com/users/markwhitfeld/following{/other_user}","gists_url":"https://api.github.com/users/markwhitfeld/gists{/gist_id}","starred_url":"https://api.github.com/users/markwhitfeld/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markwhitfeld/subscriptions","organizations_url":"https://api.github.com/users/markwhitfeld/orgs","repos_url":"https://api.github.com/users/markwhitfeld/repos","events_url":"https://api.github.com/users/markwhitfeld/events{/privacy}","received_events_url":"https://api.github.com/users/markwhitfeld/received_events","type":"User","site_admin":false},"assignees":[{"login":"markwhitfeld","id":1948265,"node_id":"MDQ6VXNlcjE5NDgyNjU=","avatar_url":"https://avatars0.githubusercontent.com/u/1948265?v=4","gravatar_id":"","url":"https://api.github.com/users/markwhitfeld","html_url":"https://github.com/markwhitfeld","followers_url":"https://api.github.com/users/markwhitfeld/followers","following_url":"https://api.github.com/users/markwhitfeld/following{/other_user}","gists_url":"https://api.github.com/users/markwhitfeld/gists{/gist_id}","starred_url":"https://api.github.com/users/markwhitfeld/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markwhitfeld/subscriptions","organizations_url":"https://api.github.com/users/markwhitfeld/orgs","repos_url":"https://api.github.com/users/markwhitfeld/repos","events_url":"https://api.github.com/users/markwhitfeld/events{/privacy}","received_events_url":"https://api.github.com/users/markwhitfeld/received_events","type":"User","site_admin":false}],"milestone":null,"comments":8,"created_at":"2018-08-15T19:25:26Z","updated_at":"2018-09-16T13:48:37Z","closed_at":null,"author_association":"MEMBER","body":"### Versions\r\n\r\n```\r\n* ngxs: v3.2.0\r\n* @angular/core: v6.1\r\n```\r\n\r\n### Background\r\nThe NGXS patchState method is used to do immutable object updates to the container state slice without the typical long-handed syntax. This is very neat and convenient because you do not have to use the getState and setState as well as the Object.assign(…)or the spread operator to update the state. The patchState method only offers a shallow patch and as a result is left wanting in more advanced scenarios. \r\nWhat if it is possible to make the patchState method extensible to create a more advanced yet simple mechanism for state updates?… Let me introduce patch operators…\r\n\r\n### Proposal\r\nThe basic idea of this proposal is that we could describe the modifications to the state using curried functions that are given any inputs that they need to describe the change and are assigned to the part of the state tree that they should be applied to. The curried function is then run using the state slice that they are assigned to and the returned value is used as the new value for that state slice. \r\n\r\nThe function that produces the curried function that is still awaiting the slice of state to be applied to is called a patch operator. The type of this curried function could be defined as follows:\r\n\r\n```TS\r\ntype op<T> = (state: T) => T;\r\n```\r\n\r\nWe can make a number of these patch operator functions in order to help with common scenarios for state manipulation. Some ideas are:\r\n\r\n- `patch<T>(value: T) : op<T>`\r\n- `set<T>(value: T) : op<T>`\r\n- `iif<T>(condition: Predicate<T>, then: op<T>, else: op<T>) : op<T>`\r\n\r\nAnd some array operators:\r\n- `patchItem<T>(selector: number | Predicate<T>, operator: op<T>) : op<T[]>`\r\n- `removeItem<T>(selector: number | Predicate<T>) : op<T[]>`\r\n- `insertItem<T>(value: T, beforePosition? : number) : op<T[]>`\r\n\r\n### Example:\r\n\r\nWe could express some modifications to a state as follows:\r\n```TS\r\nctx.patchState({\r\n  greeting: 'Howzit',\r\n  token: patch({\r\n    lastUpdate: new Date(),\r\n    active: true,\r\n    origin: iif( origin => !origin.ip, patch({ ip: '192.168.1.1'})\r\n  }),\r\n  roles: [\r\n    removeItem(3),\r\n    insertItem({id:55, name: 'Admin'}),\r\n    patchItem( x => x.id === 64, {name:'Editor'})\r\n  ]\r\n});\r\n```\r\nPlease add any other ideas for operators to the comments.\r\nFeedback welcome!\r\n\r\nPS. Related Meduim post here: \r\nhttps://medium.com/@mark.whitfeld/ngxs-proposal-patch-operators-75b24d309b91"},"comment":{"url":"https://api.github.com/repos/ngxs/store/issues/comments/421768319","html_url":"https://github.com/ngxs/store/issues/545#issuecomment-421768319","issue_url":"https://api.github.com/repos/ngxs/store/issues/545","id":421768319,"node_id":"MDEyOklzc3VlQ29tbWVudDQyMTc2ODMxOQ==","user":{"login":"Newbie012","id":10504365,"node_id":"MDQ6VXNlcjEwNTA0MzY1","avatar_url":"https://avatars1.githubusercontent.com/u/10504365?v=4","gravatar_id":"","url":"https://api.github.com/users/Newbie012","html_url":"https://github.com/Newbie012","followers_url":"https://api.github.com/users/Newbie012/followers","following_url":"https://api.github.com/users/Newbie012/following{/other_user}","gists_url":"https://api.github.com/users/Newbie012/gists{/gist_id}","starred_url":"https://api.github.com/users/Newbie012/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Newbie012/subscriptions","organizations_url":"https://api.github.com/users/Newbie012/orgs","repos_url":"https://api.github.com/users/Newbie012/repos","events_url":"https://api.github.com/users/Newbie012/events{/privacy}","received_events_url":"https://api.github.com/users/Newbie012/received_events","type":"User","site_admin":false},"created_at":"2018-09-16T13:48:37Z","updated_at":"2018-09-16T13:48:37Z","author_association":"NONE","body":"Just stumbled across an issue that could've been solved with this approach.\r\nLooking forward! :)"}}
{"actor":{"display_login":"Newbie012"}}