{"action":"closed","number":20,"pull_request":{"url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/pulls/20","id":192176705,"node_id":"MDExOlB1bGxSZXF1ZXN0MTkyMTc2NzA1","html_url":"https://github.com/rmmmp/mock-cloud-firestore/pull/20","diff_url":"https://github.com/rmmmp/mock-cloud-firestore/pull/20.diff","patch_url":"https://github.com/rmmmp/mock-cloud-firestore/pull/20.patch","issue_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/issues/20","number":20,"state":"closed","locked":false,"title":"Flattens data when fetch with .data()","user":{"login":"fizk","id":386336,"node_id":"MDQ6VXNlcjM4NjMzNg==","avatar_url":"https://avatars0.githubusercontent.com/u/386336?v=4","gravatar_id":"","url":"https://api.github.com/users/fizk","html_url":"https://github.com/fizk","followers_url":"https://api.github.com/users/fizk/followers","following_url":"https://api.github.com/users/fizk/following{/other_user}","gists_url":"https://api.github.com/users/fizk/gists{/gist_id}","starred_url":"https://api.github.com/users/fizk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fizk/subscriptions","organizations_url":"https://api.github.com/users/fizk/orgs","repos_url":"https://api.github.com/users/fizk/repos","events_url":"https://api.github.com/users/fizk/events{/privacy}","received_events_url":"https://api.github.com/users/fizk/received_events","type":"User","site_admin":false},"body":"## What?\r\nFlattens data (removes `__collection__` and `__doc__`) when data is requested from `DocumentSnapshot` via `.data()` as well as looks for `__ref__:` in nested objects.\r\n\r\n### Nested references.\r\nLet's say we have data-structure like this in **FireStore**\r\n```\r\nartist: {\r\n    'jfghw57efzjbsdft': {\r\n        name: \"Some Amazing Band\"\r\n        albums: [\r\n            {\r\n                type: 'LP',\r\n                reference: DocumentReference('albums/ghaeo5tgzd57th')\r\n            },\r\n            {\r\n                type: 'LP',\r\n                reference: DocumentReference('albums/bq58tgzdlkvb48')\r\n            }\r\n        ]\r\n    }\r\n}\r\n```\r\nand then we have some code that looks like this:\r\n```\r\ndatabase.collection('artist')\r\n    .doc('jfghw57efzjbsdft')\r\n    .get()\r\n    .then(artist => {\r\n        const data = artist.data();\r\n        return Promise.all(data.albums.map(album => album.reference.get()))\r\n    })\r\n    .then(albums => {\r\n        albums.forEach(album => console.log(album.data()))\r\n    })\r\n```\r\nNow this is gonna work in production, even though we get the top-most data for the **Artist** and the work on the sub-objects.\r\n\r\nIf we wanna test our code, we would build _mock data_ that could look like this:\r\n```\r\n__collection__: {\r\n    artist: {\r\n        __doc__: {\r\n            'jfghw57efzjbsdft': {\r\n                name: \"Some Amazing Band\",\r\n                albums: [\r\n                    {\r\n                        type: 'LP',\r\n                        reference: '__ref__:albums/ghaeo5tgzd57th'\r\n                    },\r\n                    {\r\n                        type: 'LP',\r\n                        reference: __ref__:albums/bq58tgzdlkvb48'\r\n                    }\r\n                ]\r\n            }        \r\n        }\r\n    }    \r\n}\r\n```\r\nThis is not going to work because `albums.$.reference` is not going to be a `DocumentReference` object, it's just gonna be the `__ref__:....` string.\r\n\r\nThe reason for it is that current code doesn't recursively go through the data-structure it is returning and makes sure that it has mocked out all `DocumentReferences` .\r\n\r\nThis PR goes through all the returned data and makes sure that all references have been converted.\r\n\r\n### Flatten data-structure\r\nLets say I have mocked data-structure like this:\r\n```\r\n__collection__: {\r\n    user: {\r\n        __doc__: {\r\n            '1': {\r\n                name: \"John\",\r\n                __collection__: {\r\n                    address: {\r\n                        __doc__: {\r\n                            country: \"Australia\",\r\n                            state: \"VIC\"\r\n                        }\r\n                    }                \r\n                }\r\n            }        \r\n        }\r\n    }    \r\n}\r\n```\r\nIf I have code that looks like this:\r\n```\r\ndatabase.doc('user.1.address.country').get()\r\n```\r\nIt will work, but if I later in my code need it like this:\r\n```\r\ndatabase.collection('user).doc(1).get().\r\n    then(doc => {\r\n        const data = doc.data()\r\n        return `${data.name} lives in ${data.address.country}, ${data.address.state}`\r\n    })\r\n```\r\nthat is not going to work because for example, `address` doesn't contain a **country** `key`, it contains a `__doc__` and so on.\r\n\r\nWhen data is returned via `.data()` call, it needs to be put in the same state as **FireStore** would return it. This means removing `__collection__` and `__doc__` keys. To put it simply , flatten the structure.\r\n\r\nThis PR does that.\r\n\r\n\r\n## How?\r\n\r\nWhen `DocumentSnapshot` is asked to return its data:\r\n1. Check value type (object, array, number, string...)\r\n2. Recursively go through each key in the data object\r\n3. For each sub-object value, create a shallow copy and  **go to step 2**\r\n4. For each key that is `__collection__` or `__doc__`, hoist its values up (remove key) and **go to step 2**\r\n5. For each string value, check if it starts with `__ref__:`, if so, create `DocumentReference`, else return\r\n6. For each array, inspect and for each item **go to step 1**\r\n7. For all other scalar types return.","created_at":"2018-06-02T03:23:38Z","updated_at":"2018-10-11T15:47:00Z","closed_at":"2018-10-11T15:47:00Z","merged_at":null,"merge_commit_sha":"832dde7ea7ad502de41722fa4d910a6846b33ecf","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/pulls/20/commits","review_comments_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/pulls/20/comments","review_comment_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/issues/20/comments","statuses_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/statuses/cf50c297e82996f8c9eae4eb88e27c1899679530","head":{"label":"fizk:master","ref":"master","sha":"cf50c297e82996f8c9eae4eb88e27c1899679530","user":{"login":"fizk","id":386336,"node_id":"MDQ6VXNlcjM4NjMzNg==","avatar_url":"https://avatars0.githubusercontent.com/u/386336?v=4","gravatar_id":"","url":"https://api.github.com/users/fizk","html_url":"https://github.com/fizk","followers_url":"https://api.github.com/users/fizk/followers","following_url":"https://api.github.com/users/fizk/following{/other_user}","gists_url":"https://api.github.com/users/fizk/gists{/gist_id}","starred_url":"https://api.github.com/users/fizk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fizk/subscriptions","organizations_url":"https://api.github.com/users/fizk/orgs","repos_url":"https://api.github.com/users/fizk/repos","events_url":"https://api.github.com/users/fizk/events{/privacy}","received_events_url":"https://api.github.com/users/fizk/received_events","type":"User","site_admin":false},"repo":{"id":134945506,"node_id":"MDEwOlJlcG9zaXRvcnkxMzQ5NDU1MDY=","name":"mock-cloud-firestore","full_name":"fizk/mock-cloud-firestore","private":false,"owner":{"login":"fizk","id":386336,"node_id":"MDQ6VXNlcjM4NjMzNg==","avatar_url":"https://avatars0.githubusercontent.com/u/386336?v=4","gravatar_id":"","url":"https://api.github.com/users/fizk","html_url":"https://github.com/fizk","followers_url":"https://api.github.com/users/fizk/followers","following_url":"https://api.github.com/users/fizk/following{/other_user}","gists_url":"https://api.github.com/users/fizk/gists{/gist_id}","starred_url":"https://api.github.com/users/fizk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fizk/subscriptions","organizations_url":"https://api.github.com/users/fizk/orgs","repos_url":"https://api.github.com/users/fizk/repos","events_url":"https://api.github.com/users/fizk/events{/privacy}","received_events_url":"https://api.github.com/users/fizk/received_events","type":"User","site_admin":false},"html_url":"https://github.com/fizk/mock-cloud-firestore","description":"Mock library for Cloud Firestore","fork":true,"url":"https://api.github.com/repos/fizk/mock-cloud-firestore","forks_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/forks","keys_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/teams","hooks_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/hooks","issue_events_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/issues/events{/number}","events_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/events","assignees_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/assignees{/user}","branches_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/branches{/branch}","tags_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/tags","blobs_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/git/refs{/sha}","trees_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/statuses/{sha}","languages_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/languages","stargazers_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/stargazers","contributors_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/contributors","subscribers_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/subscribers","subscription_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/subscription","commits_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/commits{/sha}","git_commits_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/git/commits{/sha}","comments_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/comments{/number}","issue_comment_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/issues/comments{/number}","contents_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/contents/{+path}","compare_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/merges","archive_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/downloads","issues_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/issues{/number}","pulls_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/pulls{/number}","milestones_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/milestones{/number}","notifications_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/labels{/name}","releases_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/releases{/id}","deployments_url":"https://api.github.com/repos/fizk/mock-cloud-firestore/deployments","created_at":"2018-05-26T08:57:57Z","updated_at":"2018-06-02T05:09:21Z","pushed_at":"2018-06-02T05:09:19Z","git_url":"git://github.com/fizk/mock-cloud-firestore.git","ssh_url":"git@github.com:fizk/mock-cloud-firestore.git","clone_url":"https://github.com/fizk/mock-cloud-firestore.git","svn_url":"https://github.com/fizk/mock-cloud-firestore","homepage":null,"size":236,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"rmmmp:master","ref":"master","sha":"b622bc70f4a0fd1444dfe03405999e8297b33e74","user":{"login":"rmmmp","id":13741847,"node_id":"MDQ6VXNlcjEzNzQxODQ3","avatar_url":"https://avatars0.githubusercontent.com/u/13741847?v=4","gravatar_id":"","url":"https://api.github.com/users/rmmmp","html_url":"https://github.com/rmmmp","followers_url":"https://api.github.com/users/rmmmp/followers","following_url":"https://api.github.com/users/rmmmp/following{/other_user}","gists_url":"https://api.github.com/users/rmmmp/gists{/gist_id}","starred_url":"https://api.github.com/users/rmmmp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rmmmp/subscriptions","organizations_url":"https://api.github.com/users/rmmmp/orgs","repos_url":"https://api.github.com/users/rmmmp/repos","events_url":"https://api.github.com/users/rmmmp/events{/privacy}","received_events_url":"https://api.github.com/users/rmmmp/received_events","type":"User","site_admin":false},"repo":{"id":121841962,"node_id":"MDEwOlJlcG9zaXRvcnkxMjE4NDE5NjI=","name":"mock-cloud-firestore","full_name":"rmmmp/mock-cloud-firestore","private":false,"owner":{"login":"rmmmp","id":13741847,"node_id":"MDQ6VXNlcjEzNzQxODQ3","avatar_url":"https://avatars0.githubusercontent.com/u/13741847?v=4","gravatar_id":"","url":"https://api.github.com/users/rmmmp","html_url":"https://github.com/rmmmp","followers_url":"https://api.github.com/users/rmmmp/followers","following_url":"https://api.github.com/users/rmmmp/following{/other_user}","gists_url":"https://api.github.com/users/rmmmp/gists{/gist_id}","starred_url":"https://api.github.com/users/rmmmp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rmmmp/subscriptions","organizations_url":"https://api.github.com/users/rmmmp/orgs","repos_url":"https://api.github.com/users/rmmmp/repos","events_url":"https://api.github.com/users/rmmmp/events{/privacy}","received_events_url":"https://api.github.com/users/rmmmp/received_events","type":"User","site_admin":false},"html_url":"https://github.com/rmmmp/mock-cloud-firestore","description":"Mock library for Cloud Firestore","fork":false,"url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore","forks_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/forks","keys_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/teams","hooks_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/hooks","issue_events_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/issues/events{/number}","events_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/events","assignees_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/assignees{/user}","branches_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/branches{/branch}","tags_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/tags","blobs_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/git/refs{/sha}","trees_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/statuses/{sha}","languages_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/languages","stargazers_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/stargazers","contributors_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/contributors","subscribers_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/subscribers","subscription_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/subscription","commits_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/commits{/sha}","git_commits_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/git/commits{/sha}","comments_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/comments{/number}","issue_comment_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/issues/comments{/number}","contents_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/contents/{+path}","compare_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/merges","archive_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/downloads","issues_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/issues{/number}","pulls_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/pulls{/number}","milestones_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/milestones{/number}","notifications_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/labels{/name}","releases_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/releases{/id}","deployments_url":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/deployments","created_at":"2018-02-17T09:18:29Z","updated_at":"2018-10-11T15:05:02Z","pushed_at":"2018-10-11T15:44:49Z","git_url":"git://github.com/rmmmp/mock-cloud-firestore.git","ssh_url":"git@github.com:rmmmp/mock-cloud-firestore.git","clone_url":"https://github.com/rmmmp/mock-cloud-firestore.git","svn_url":"https://github.com/rmmmp/mock-cloud-firestore","homepage":null,"size":230,"stargazers_count":16,"watchers_count":16,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":4,"open_issues":2,"watchers":16,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/pulls/20"},"html":{"href":"https://github.com/rmmmp/mock-cloud-firestore/pull/20"},"issue":{"href":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/issues/20"},"comments":{"href":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/issues/20/comments"},"review_comments":{"href":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/pulls/20/comments"},"review_comment":{"href":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/pulls/20/commits"},"statuses":{"href":"https://api.github.com/repos/rmmmp/mock-cloud-firestore/statuses/cf50c297e82996f8c9eae4eb88e27c1899679530"}},"author_association":"NONE","merged":false,"mergeable":false,"rebaseable":false,"mergeable_state":"dirty","merged_by":null,"comments":2,"review_comments":0,"maintainer_can_modify":false,"commits":2,"additions":2611,"deletions":4546,"changed_files":15}}
{"actor":{"display_login":"rmmmp"}}