{"action":"created","issue":{"url":"https://api.github.com/repos/Yomguithereal/baobab/issues/278","labels_url":"https://api.github.com/repos/Yomguithereal/baobab/issues/278/labels{/name}","comments_url":"https://api.github.com/repos/Yomguithereal/baobab/issues/278/comments","events_url":"https://api.github.com/repos/Yomguithereal/baobab/issues/278/events","html_url":"https://github.com/Yomguithereal/baobab/issues/278","id":93887221,"number":278,"title":"Baobab v2 proposal","user":{"login":"Yomguithereal","id":2571951,"avatar_url":"https://avatars.githubusercontent.com/u/2571951?v=3","gravatar_id":"","url":"https://api.github.com/users/Yomguithereal","html_url":"https://github.com/Yomguithereal","followers_url":"https://api.github.com/users/Yomguithereal/followers","following_url":"https://api.github.com/users/Yomguithereal/following{/other_user}","gists_url":"https://api.github.com/users/Yomguithereal/gists{/gist_id}","starred_url":"https://api.github.com/users/Yomguithereal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Yomguithereal/subscriptions","organizations_url":"https://api.github.com/users/Yomguithereal/orgs","repos_url":"https://api.github.com/users/Yomguithereal/repos","events_url":"https://api.github.com/users/Yomguithereal/events{/privacy}","received_events_url":"https://api.github.com/users/Yomguithereal/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Yomguithereal/baobab/labels/enhancement","name":"enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/Yomguithereal/baobab/labels/question","name":"question","color":"cc317c"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":17,"created_at":"2015-07-08T20:47:44Z","updated_at":"2015-07-10T08:30:38Z","closed_at":null,"body":"## Baobab v2 proposal\r\n\r\nThis document is a proposal for the release of Baobab v2. Some things need to be discussed here before we can advance, and this is really the point of this issue to discuss.\r\n\r\n### Installation\r\n\r\nYou can install the latest published dev version of the v2 with:\r\n\r\n\r\n```bash\r\nnpm install baobab@dev\r\n```\r\n\r\nUpdated `baobab-react` will soon follow and soon will be created `baobab-deku`.\r\n\r\n### Immutability\r\n\r\nThe tree is now immutable by default. My advice about this is to develop your apps with immutability (using `\"use strict\" so it would throw if you attempt to mutate) on and to disable it for production to see a welcome performance boost (I'd say ~30%).\r\n\r\n### Syncwrite\r\n\r\nThe tree now write synchronously only but will continue firing its update events asynchronously for obvious performance reasons.\r\n\r\n### Update specifications & transactions\r\n\r\nUpdate specifications have been dropped in favor of a simpler spec.\r\n\r\nAn update is now internally:\r\n\r\n```js\r\n{path: [...], type: 'set', value: 'Hey'}\r\n```\r\n\r\nFurthermore, the tree's update events now expose the full detail of the transactions so you can replay them elsewhere or display debugging information etc. (@christianalfoni :-) )\r\n\r\n### No more default limit on cursor's history\r\n\r\nBy default, cursor's history limit is set to `Infinity`.\r\n\r\n### Cursor setters\r\n\r\nCursors' setters now longer return themselves. This was made so you can chain them but now that we should embrace immutability, returning the affected node seems way more pratical than having to write then get the affected node to carry on your operations.\r\n\r\n### Append and prepend method\r\n\r\nIn Baobab v1 and before you would have the following:\r\n\r\n```js\r\ncursor.get() >>> [1, 2]\r\ncursor.push(3) >>> [1, 2, 3]\r\ncursor.push([4, 5]) >>> [1, 2, 3, 4]\r\n\r\n// But to push an array you'd have to do like `concat`\r\ncursor.push([[1]]) >>> [1, 2, 3, 4, [1]]\r\n```\r\n\r\nThe append and prepend methods intend to fix this (but this is really open to discussion):\r\n\r\n```js\r\ncursor.get() >>> [1, 2]\r\ncursor.push([1, 2]) >>> [1, 2, [1, 2]]\r\ncursor.append([1, 2]) >>> [1, 2, [1, 2], 1, 2]\r\n```\r\n\r\n### Facets rework\r\n\r\nFollowing the discussion in #240, facets are now to be defined within the tree itself using keys starting with a dollar by convention.\r\n\r\n*Example*\r\n\r\n```js\r\nconst tree = new Baobab({\r\n  data: {\r\n    messages: [\r\n      {from: 'John', text: 'Hey'},\r\n      {from: 'Jack', text: 'Ho'}\r\n    ],\r\n    $fromJohn: {\r\n      cursors: {\r\n        messages: ['data', 'messages'],\r\n        get: function({messages}) {\r\n          return messages.filter(m => m.from === 'John');\r\n        }\r\n      }\r\n    }\r\n  }\r\n});\r\n```\r\n\r\nThis way, there is only one way to select and get data in the tree and one can just create cursor on computed data and even select/get data beyond them:\r\n\r\n```js\r\nvar cursor = tree.select('data', '$fromJohn', 0, 'text');\r\n```\r\n\r\n*Disclaimer*\r\n\r\nThe current dev version only allows to define facets at the tree's instantiation but v2 will allow you to modify/set/unset facets on the fly by using the tree's setters like you would normally.\r\n\r\nThe only problem there is that once the facet has been define, you can't really access its definition anymore.\r\n\r\nFacets remain of course lazy on get and won't be computed until you really need them.\r\n\r\n### Alternative facet definition syntax\r\n\r\n```js\r\nconst tree = new Baobab({\r\n  data: {\r\n    messages: [\r\n      {from: 'John', text: 'Hey'},\r\n      {from: 'Jack', text: 'Ho'}\r\n    ],\r\n    $fromJohn: [\r\n      ['data', 'messages'],\r\n      function(messages) {\r\n        return messages.filter(m => m.from === 'John');\r\n      }\r\n    ]\r\n  }\r\n});\r\n```\r\n\r\n### tree/cursor.serialize\r\n\r\nSince there is now computed data sitting within the tree itself, one wouldn't want to get it when \"serializing\" the data, for instance when you would need to save it to the `localStorage`, for instance. This is exactly what the `cursor.serialize` method does.\r\n\r\nThe method would return data at any cursor but carefully avoiding any computed data.\r\n\r\n### tree/cursor.project\r\n\r\nNaming alert here! I did not find a better name. This method will probably used only internally but still. I'll take any better name.\r\n\r\n```js\r\nvar data = cursor.project({\r\n  messages: ['data', 'messages'],\r\n  user: ['user']\r\n});\r\n// Will return an object with the related data\r\n\r\nvar data = cursor.project([\r\n  ['data', 'messages'],\r\n  ['user']\r\n]);\r\n// Will return an array with the related data\r\n```\r\n\r\n### tree.watch\r\n\r\nUsed to watch a collection of path in the tree and fire updates if any of the paths is affected. (Used by `baobab-react`).\r\n\r\n### Dropped $cursor\r\n\r\nNo more silly `$cursor` sugar.\r\n\r\n### Misc\r\n\r\nThe code has been rewritten in ES6 and is now fully self-documented.\r\n\r\n`emmett` has been updated to its latest version.\r\n\r\n## Full Provisional v2 Changelog\r\n\r\n* The tree is now immutable by default.\r\n* Cursor's setters method won't return themselves but rather the affected node now.\r\n* Adding `cursor.append` and `cursor.prepend`, replacing some `cursor.push` and `cursor.unshift` weird behaviors.\r\n* Adding the `cursor.serialize` method.\r\n* Adding the `cursor.project` method.\r\n* Changing the way you can define computed data in the tree, aka \"facets\". Facets are now to be defined within the tree itself and can be accessed using the exact same API as normal data.\r\n* Adding an alternative facet definition syntax for convenience.\r\n* Dropped the `syncwrite` option. The tree is now writing synchronously but still emits its updates asynchronously by default.\r\n* Max number of records is now set to `Infinity` by default, meaning there is no limit.\r\n* Update events are now exposing the detail of each transaction so you can replay them elsewhere.\r\n* Dropped the `$cursor` helper.\r\n* Dropped the `update` specs for a simpler transaction syntax.\r\n* Updated `emmett` to `3.1.0`.\r\n* ES6 codebase rewrite.\r\n* Full code self documentation.\r\n"},"comment":{"url":"https://api.github.com/repos/Yomguithereal/baobab/issues/comments/120297523","html_url":"https://github.com/Yomguithereal/baobab/issues/278#issuecomment-120297523","issue_url":"https://api.github.com/repos/Yomguithereal/baobab/issues/278","id":120297523,"user":{"login":"Yomguithereal","id":2571951,"avatar_url":"https://avatars.githubusercontent.com/u/2571951?v=3","gravatar_id":"","url":"https://api.github.com/users/Yomguithereal","html_url":"https://github.com/Yomguithereal","followers_url":"https://api.github.com/users/Yomguithereal/followers","following_url":"https://api.github.com/users/Yomguithereal/following{/other_user}","gists_url":"https://api.github.com/users/Yomguithereal/gists{/gist_id}","starred_url":"https://api.github.com/users/Yomguithereal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Yomguithereal/subscriptions","organizations_url":"https://api.github.com/users/Yomguithereal/orgs","repos_url":"https://api.github.com/users/Yomguithereal/repos","events_url":"https://api.github.com/users/Yomguithereal/events{/privacy}","received_events_url":"https://api.github.com/users/Yomguithereal/received_events","type":"User","site_admin":false},"created_at":"2015-07-10T08:30:38Z","updated_at":"2015-07-10T08:30:38Z","body":"@marbemac: what you describe would mean to do a deep diff on the data and this is precisely what Baobab intents to avoid. However I might add a little option making the updates \"pure\" (probably not the good word) so they check shallowly if something has changed in the data before firing an update. But this should probably be the job of components to do so with PureRender etc. rather than the tree's job."}}