{"_id":"@nandorojo/swr-firestore","_rev":"73-73c4137154e3a6b4c673e241985b5eaf","name":"@nandorojo/swr-firestore","dist-tags":{"latest":"0.16.0","listen-key":"0.2.2","next":"0.13.1","dates":"0.8.0-alpha.3"},"versions":{"0.0.1":{"name":"@nandorojo/swr-firestore","version":"0.0.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/src/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.0.1","dist":{"shasum":"e4265d8788aa20169bd1d83f5da9360de68f3643","integrity":"sha512-xVsRMe60phOpKg0q1P7SurKAfYksWunbcP0kqpk2c17DQRR+SvUSYz1y8O9ETWgRCkVwlUyVx9ztM+VRypk0oQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.0.1.tgz","fileCount":99,"unpackedSize":97162,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJen6MKCRA9TVsSAnZWagAAxFgP/Ah5SzlTKSq8D++KPr1f\nKVBah2alBmR1FcUvVxO5ZOfG3H5GDihocEPz1x+4r2sgsIRA97N9pnl9jFxF\nuepLgdWYiwAJ5oSJ5gKw6Mq72eYXOrOlRiGaMgwEuvnVwAvz8LewURFsmocI\nb3z5EYnJngX+3hw5i3BV3EJ5NNdfsqkzL/lw3CaD7nUuv8y99Rzf57BXuH6Z\ndP8keTrgqfb/QlZpUD8V4UcHEeBXzEvI9w8b6z2neB3w7lQmJXvZ8ev1Uu/F\nq+KugLsUcx1ppZrV987maTwOpEwv+KTfthOF63kzsFRQD2vZYXzFWEs9/6QB\n1qMLXQNVM7mQiCofiuFPOH3kJYh9BJOveSXeiaGTVCd7eGbow3zXJOJo1UsR\nTNxHJb7ixkVULFEkohz7l+d0PTHEE1V6GxmyZV8rOP16geRfVeZZgoEVZ3Lg\nZh86H9vIjXqbnzoZiOhukkBjxSxGgRSq0CNUmUboKcGXUZTzHEqbERdpm0xM\nvhf1+kRPF5Prz32HA2+vjG4o37WgfHBrchILcaUaio15xC+ilrVQGFP5ZNjU\nDRfpR1ax2F29btZ8PZOe73tMjvlCPpp/9G64Q/Um0SdKpx7OaZFKr4diL4Rm\nD1pxyU4eRGYcCSmIYJIEVZFhmRb1l5h9vgeeaUyMQmJLNuf3y4Fh0AhFUXh3\nFfT3\r\n=uhVo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICDY4SciOkyOFHqO3IWVlD00DxU/b07lzZkc5l+5NkfSAiA3Hm4EZCQNjG8AdjT4fdhZ9kCx8ninG98ffFLjjFayYw=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.0.1_1587520265475_0.4555131533560062"},"_hasShrinkwrap":false},"0.0.2":{"name":"@nandorojo/swr-firestore","version":"0.0.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.0.2","dist":{"shasum":"a099d2348f28f23f4bc1bb2286e61659949bf122","integrity":"sha512-aQCz8aoroBgXmnQDGDJpsDX2keCdBCxXnzxZDTlzr30cQnMMrgbrLwLQLaOQ311zJh8gFogjZJF/QPpcKUmm5w==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.0.2.tgz","fileCount":99,"unpackedSize":97134,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJen73YCRA9TVsSAnZWagAAxDoP/0Yk7ZGxbrmD2n99idTl\nxbNOEeKNd0hFzhaOoHa8vqbhNA9q9rcGwRROZg4oQ5SIIzlAUemCN+5+tWRE\nyUYgpdmBm/keMwLV1jt7ph6+UT4YimDCYmamjXnV1DLlTJ3U1bw9fJHG4+NH\nskp5RVyYlTRVGngJDdHcxTs9FnzuCF6LrwjHbmnEpE6HPEiQaEWgk+fhCqQ1\n4C6qDJrP9JOxZTjjj8hakzmGjZaM1NLCU/skTUUGxwyimCmkbBHTrJJtgvnY\nEaVyLqdoO3HgtYzcI0IkIfcCFTW/J21qfUMaKvmgSJkiLjRYHBOZF5cMPiig\nJyeowf95jbdtPq781JVgDV8oJh/nLrytSFSLhS3khILmH+aWD24XfWPSG6kX\n4SFb9W+AXP2FO9f9S0EEqPZW4wquiDry0lLEuScNU7tJpusc3MM5sB/CXTJp\nE/hIVdfsIsCr+pvU9LhXuJd28qTTYQysI9QY42rGev5HF8p5fNU1JusPXHhC\nPnmmhLzJiYr/n5dlFViMx/okjJf8I8uabWFOtCtWSbSsVu5YTT5gjoBL8PbD\nlRuU2YS6Y5gxCDpIl3kLyXfTFmK9i19/7FFVgRH6b3ffvPi3lBMs6bWkK5IL\nu1P/FErKh4CnkQzVZnWrndIdUbRpCDHlro+f8+kaQL5kRisqgzq6X8t6DZ1x\n/JSj\r\n=wsN3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB+eHWYXabom3eZJvSWbejtmrhkrMd7xifikBPKJVRTcAiEAq0y28wMV8DI4zQQk3gLgms8CJmtOcwZ+/XEz/j6E/ks="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.0.2_1587527128386_0.5228379655569189"},"_hasShrinkwrap":false},"0.0.3":{"name":"@nandorojo/swr-firestore","version":"0.0.3","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.0.3","dist":{"shasum":"0d5494e7000f77f5ab4b48df351a41b42a9b2759","integrity":"sha512-hKDVoPmTmbQUZjTOMKAEC2r4P14C8ga4k2xQq4hgcf8r0lyalYwSuqxkcg+wRgMN3+CMsCR84NCDCGql1BcqTw==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.0.3.tgz","fileCount":99,"unpackedSize":99844,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJen9TdCRA9TVsSAnZWagAAocsP/RgVGITAQqw0Bt80Edlj\n0ltejUiTPJTuV288NPmZon7Bx6rRQ3EeEkO0iRn/AmtACB6zP3EW4+2oCtPf\n3615J469wJXOtnCajtgm8X1a6UTyG6s+qMaZ8S9BfdRjIKeNTCP9K6aTLDkL\ns+K7bfhIZvsqZeHeNocZpXvgYNfRmEq4agR6NoSYlnDquptusjAr3Tt8YY87\nTW2eryuMRLsQeoOVlKC20mpKek7NLWWE9vhnGqMrEYEc9+jUBOpI2jJicmTl\nZugfS0zYQwT+ZLHJRkLSBja4hrsovpBemXzL7L7DGS1owArBb4dUfFMne1YN\ndl0Fh3eFh1TnhrCfPeqMXs/PNefuUfLweTK2bfCxWH0YqAhvBWVEnYQzW9pf\nV8YykAeF5oVWwMw/MpOARmZ/koTCWhIRr1M9iAXM9Py+kbI0DXHPZ/7kaxXG\n+H77lnVT2vOW/42WGl8Agtx4PWuoH4+DFD174T6UymExaxJHj8Cdsg2+pUoz\nf4g0EiK36pwTBlEGVhBXCA+AAcmvkcX9XoCMMgqNXrqLBljnJcwFcX8udC61\nmYN1p/n38nXT8qS10O45v4n0syXhi1LuAqAHPXsmJ6iYKEeuLpvJVP2z+GYw\nJomq30zxH7iFOfMo1mEjlkfzbn7CUBeFhcwAwOw8CTxhVMnPTKykqDaRT9uE\nvBAV\r\n=R3B1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDVqt6xnbU68wXYKhcXEYGkAFVJ6q6cvJspVnGPmeUjrgIgQnftjvgUx6w62np24kT4nxushc4R6Um9t6hG2rehI58="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.0.3_1587533020382_0.9015482216877937"},"_hasShrinkwrap":false},"0.0.4":{"name":"@nandorojo/swr-firestore","version":"0.0.4","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.0.4","dist":{"shasum":"b65f2b3ed72de4a9fe0291b3a553ab7a562d2b0d","integrity":"sha512-y1ENwIAIHOE2TJhKymTBO+HIUGnOjzVgeo1aXvNJBDLxLSWk1wUJiMqvXdj9R90jpP1Nx4Zry5bcckfbWF+gJA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.0.4.tgz","fileCount":99,"unpackedSize":101030,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJen9k+CRA9TVsSAnZWagAAZWcP/0OXO3YBgQyzpPalpfjc\n4coQWiYs4ypoCrDswRf8LG57bn2xI55RYrqMbEC3yIUQfzWTH7rySHTh0Bk0\nMBYKgaF28k9gAMeASIK8xj5jf+S5B9bPlhuo97a4I2PBWOBppq8X/oG4mtZR\nk3ZQVZN2bRVoGMoo7b6ZPtOEwY29KRv/hSl8N2l5VJvFXoYb+gDipkEskyhz\nDFI8YRk4jPt0WWS7N53qp3tZQRo4wDu/1y/nh62rsZRCVj+hmLViaoyY6Ov+\nJKQNju9QglseUoT3NB4GiMAz0KUeuQxQykaLu67pDM1sKOK79XKkr9MhVVOK\nAxGABIzZGQsSzF21uszZzTW3re7MTDamfXv0DpWtTVFSlPQhdgo2bpFETip2\niz0qwtCXlaOPsBV+8tb6b6V2He6Q3ZLHbqSz+LgOJR751/1gwNDZjw1tJUEN\nPcqXwMAd5fAQ54OzDJzaCBApYJhs1raa4gp59ViKNF4yhLpAGC5KR3zOnI05\nWI4HPSsDNg7h2QFJ/FeuMf3DbVigNrGWhmJohlOAryP/V7XQvj7bWZGCZiun\n3K20XxIQWAPEd4W6xAYaqAXsqYx6wx8E5yyDuX5N7C6E7i9YNTqX5E3WP5M/\nMyZky6nkofC7b+xeKVLWV+qfzb7zf+rHOrah4+zGg+OqyIruz0Nqyw9IDblg\nmhF1\r\n=/Ytr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD9H9+9rO+ilqsfTIQ11Kn6kSkM0g2zpjhAOCtjj9+0HwIhAOF0IHVlKSkWocqaC+ekmAMN/MtOMWa6akeSp/bflWGh"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.0.4_1587534142418_0.6932653257255348"},"_hasShrinkwrap":false},"0.0.5":{"name":"@nandorojo/swr-firestore","version":"0.0.5","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.0.5","dist":{"shasum":"fd2df695d6e7f5b948551a4e3b4b749adfbe1557","integrity":"sha512-y1KqB5GLAliMptKwgebhzzG9pCB7DvxN+uLubN6GSO0FiFTBR1C9bvVjhrQg4A2wHvpndcDRI2fGOo4laqvr5w==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.0.5.tgz","fileCount":99,"unpackedSize":104458,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJen95YCRA9TVsSAnZWagAAcf4QAIgPM5wTEQH6ODK0s+ta\nl1aRBbAXHfDLeIva0VfG4T5P5klitCkjW56pXEDlUUVpo9pxu7DjpRuATw+W\nTXtZ45cwIzB/E2VW665xHyTxdyNf8ATPzmiPm2oE/af9iUx0HFsf7PfFTaSk\n80Ip6s/HU7P4hPSveWiYNZNzTPsKqyQdsWFeHDrWb6Dkz/wM8GpOwjqZq6g6\nph7KwyZdcOl1ai2jdmnWDN1GJVRUN3YWt8tjZeN8LRX+kHiPbej6HOJsV/Vj\nPmUL0oGO6b4SSa5IFQvjDOAIYeCilErwLNwnhYfLTLLUeEeri2aRCGi1Xn1w\nAsv2MRAhnLNL71F7Rl4l56YsXBqZKCIBYwQWPyusv6ZhB8T1xIWUOkYlcqh6\nadot+qgr+WxCBjhefzY+aeoDjQb1LUYRbjFK4Wl4AgOjuSFllwiT7fQMWlDQ\nsbqw8yn2EZTi4QZQMCgct1q+wVvmprcgnFcqRUfyg49G/gtRvTMDzc6YHwP2\n6xMHnhLo+u6IGuCh1cffUMMn5SLLIPU5FJaMRy3L3pjAj8h+F5yRR6gTuy0c\nsTUhuGh/Ly1BCq4d6zvHoBbmirK9T44vLsur8HYygAL8JA2hrLs/V0fj0jpE\n82KGkV7m3tdLqx6iFX8AYCHneP4d/3HNpgm1nvmTNuBoa1WU2vhwBO+oSj6m\n5TJs\r\n=bp+8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCGYOiETJg1pjwA8/j7JpuHxxVwjvMW66BMmzGJXbpNTwIhAP5tQwL/pW4l0YAcqRBKsiTgQh+k9+ITQxKikdkgQCCf"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.0.5_1587535447759_0.6080312238598267"},"_hasShrinkwrap":false},"0.1.0":{"name":"@nandorojo/swr-firestore","version":"0.1.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.1.0","dist":{"shasum":"5be839c01870e2e551ef058552eadfc0b9ddf03f","integrity":"sha512-N50uxqU91qkZvR/lqRonbqQNZJ6+dnrGgwyximZw2kCvV9U/OvVq9ukD+lJpxaeGDWgmAQ3ewz9/LQ+4yZM6pw==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.1.0.tgz","fileCount":99,"unpackedSize":109076,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeokJGCRA9TVsSAnZWagAAQhIQAI3XyZDXD0v4FOEGnPQe\nP6I8bYF/KaPlQ8hx4AXeRjDZCet5XfGXRDR8e7LVwr9DFng5MUp4BgYz6kLd\nC4oPzyO1j8wPRaYj3qKftJ1eCqHx8SVWbPfUkf1neMVnT4Ji9yJEwwClWZ3x\nQYoZQB7iHQZsk9DRzafrhz8sCSCMJkUVRQKfqHaXWVunDAL/fAAbnG9Unw4N\nrfPGXEctPihdbA1pqhtgJDwigoYww7ARjPVtPIjey9Ph8975I00c7SFDzGM7\nMmhRDgjwyFQIY3IZs1iG+xdEE+YCP+fP1z74XUOb4mJr5gDPyqD/sKYh7bfg\njo7L/ObAkGMmbDV91HT7Zoz3An2Rs3in8F2Dcr2E0jdzSx07sfba7Y+LU4Fz\nzYo5Z0RXcpj096HMNkUmmB82PmYQHlITxaG3ahLhRbt1DLRx+XXYgFu4i7mW\nRfCrX2h6YCWSI1p0efDZ3QYXMxyckMdCo3IQj/mwk8RDQyd/xFj4VSsmMJ7D\nJbqAg9viFbEPbN5UW6zICDgc6MWqSTCEnPUccLSjjzwL5asEkT6E8d5vQqRa\n1vA3xpGE2APv8nY7lusyJBjcAbujPHJH5WBrk5TzNPhSCwLRu56cQtfQMTYq\n3XdOm8yjlC9BPG9n9nDG/OT+uJcYSTjxEPiXMDGvnFa1YeFU8h7d2X8KKjQ1\nsBT3\r\n=NJSp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDv7uilAbr25h1QnqHzKvwri7tuV9gXztJFGkEtTMpGzwIhALy7vmjyaxMPWoUwzE/BQOYszAnqGKyLvg2cB9r8kyFI"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.1.0_1587692102188_0.37357799319407814"},"_hasShrinkwrap":false},"0.1.1":{"name":"@nandorojo/swr-firestore","version":"0.1.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.1.1","dist":{"shasum":"eba340136f9c0b97c0f4ec948915319879b5dbcd","integrity":"sha512-q3DMQbJ/bPo2RpIIFm5j4w87sYp+GobA+LbtYTjWlIj3XorxReJZL3BATaUU8wQeIQ3rAhoW5AdaVHKUIHa3bg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.1.1.tgz","fileCount":99,"unpackedSize":116350,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeolDHCRA9TVsSAnZWagAAIr4QAIGFqfJeyTycWzM7ehoI\ngCyyK4geV/Q6V7/f+9LeFDL8QSXa0dGufq73W6kaYb4xdhnB6COlF3qVPj0Z\ngT5hlifBKY/8B8NFJFXgGeVW0a7o9vRyr/cJzQbh+qfOU5sGbO6ATY6X3f6B\nb1SxIigvJIcxOoImptQ0rMmLTQiAH4LyK/LCccL7/vWCgE8hpEenCcu39ZSC\npUjAg9F65wXf+m5U6wD6fi/9gL+z7gpBNNetp7ZuDeBeKvrKODyIJDdhFQaB\nL11reMw3y2ohj+ip0jZC2jKcPwtRlOYeo+qDaya2YgDqrotEF09O1KafBxJ7\nmlgtxZ+zniVTrZFmqDKzPTUE7xEnn+z1VZSzDx2Ho8BJFes7gFJWVYnA3djh\n6yobgGmpGJcFZrz0vwSMNCT1shESEMJVLiIwsIbXpgZL5N1fyAqB2/agP0kM\nbKulGvsgs/xy0KA1BdQ1qkvJ5hsNQN+56qa5q0Mt926WvM2guVIp7nkjrjgv\nSLiDQPpnpf1tH3yAJos4/NeKFFrodENijkjtbWrWzUYrpZsAHda/KTVfhjkz\nb7PeAOc2UDAsVRcl1nl2n/u5uEEIHa5DP+qqGaJ+5rCb/L1rU/oYA31iEhe5\ndnpOVmo+XcC+/VEEkOqPZR1pJtiIZSjHxVLJV1ZfNGRKR47JLCTazvUs2N5O\ng1va\r\n=ZfPu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB2eAWGbQoNHyflaLLfgc3w8QIMjImDR4i58ZBC7VmpOAiBi3x+Pai+3PDAaz03oo21MTCSrGxgD6gUWFZa8n4T9wQ=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.1.1_1587695814658_0.7903597533285829"},"_hasShrinkwrap":false},"0.1.1-listen-key":{"name":"@nandorojo/swr-firestore","version":"0.1.1-listen-key","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"readmeFilename":"README.md","readme":"# @nandorojo/swr-firestore\n\nReact hooks for Firestore, that you can actually use in production, on every screen.\n\nThis library is built on top of [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\n## Installation\n\n```sh\nnpm install @nandorojo/swr-firestore\n\n# or yarn\n\nyarn add @nandorojo/swr-firestore\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst fuego = new Fuego({\n  // your Firebase config object goes here\n})\n\nexport default () => {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Usage\n\n```js\nimport React from 'react'\nimport { useDocument, useCollection } from '@nandorojo/fuego'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  // get one document\n  const { data: user } = useDocument(`users/${user.id}`)\n  // get a collection\n  const { data: userList } = useCollection('users')\n  // subscribe\n  const { data: user } = useDocument(`users/${user.id}`, { listen: true })\n\n  // query a collection\n  const { data: userList } = useCollection('users', {\n    where: ['name', '==', 'fernando'],\n    limit: 10,\n    orderBy: ['age', 'desc'],\n  })\n\n  // ...render here\n}\n```\n\nI'll add more docs soon. There are TypeScript suggestions for all the options already!\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.1.1-listen-key","dist":{"shasum":"ec87d6e80ff4b6f5e8c7ad8ccd85e60381faac66","integrity":"sha512-ZU4/WQ1bFWXUpDv7KVrRIADzQc5Gn4E5tYg8BbCv3ci+K/rRkShANGvpgapX892GEkeB1KBYh27lTUKeEv6syw==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.1.1-listen-key.tgz","fileCount":99,"unpackedSize":118555,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeoygsCRA9TVsSAnZWagAAuygP/jrjabNkEJa0e/ZdJSjy\nm8IFOlsno8okeHoIgWh23a+XlRg99FUnLXhCorq21Sy5O1qVpOx+g3MHehNL\nGLmk9MumdaEtQ3TP+YfWSvGe7SFiF69xzCC+xhv9FSabRGyhfHBEseFCvNF8\nY6w7oW7lwd9/kLp26V9HM9K4iA2y78MFJbTIGxpty5zjU67PtI8CH1Q4g9cI\nY2kpSgne5Its+mLcXUR1IJ0/n1NpQXf5Lw1OC1sox68PXOnfgOi1fT0Qx/xf\nEqiEeInUi/mUEE0f3PrcHtvzYJl3DsDx3NJPqVDD28/5Bz/HJHjT2Zcq05ik\nZH1m0hoY/t2HvSmZR6AAcK9Q5BKHYietMks5CFuhK2RzQ1nzLEo41PJZukO2\ngnxBLvuMYJeOBRXaBLGm5Jb0bA5W26FRRA7qd4lYqxYpiTrqtzT8rcYpG5Mv\nFuAV02ubaGwf7ZuK7ja6zvpOCnQKmoffDRhJ2jAY8I09CbTVWmwcOV/rRQco\navrJULPQfIXKEllloosAfHedOdqyvBUQn8K6gVOieKbrldq8yFuMJYrYn93F\ndbPEMnsychdlRxWycxRo+FFn8DV7hOKrlf68A/IIUtUF5tsDyAiUkwawvoBN\nq3Cl7ItXMJsmMTlw/YjvXe74wpM9rT40bza36Bo1l3XUIy6rbLvt+1tG3f7k\nhb+U\r\n=gyQu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCL8rmr196Tu7PNOtSEAVW/lktGTxxnB3Ffl+KExisRhAIhAM47hmJXzobGFlDB1nvf0204xR+u+4jZWT8bohNzbvKK"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.1.1-listen-key_1587750955984_0.4708937182345556"},"_hasShrinkwrap":false},"0.1.2-listen-key":{"name":"@nandorojo/swr-firestore","version":"0.1.2-listen-key","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"readmeFilename":"README.md","readme":"# @nandorojo/swr-firestore\n\nReact hooks for Firestore, that you can actually use in production, on every screen.\n\nThis library is built on top of [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\n## Installation\n\n```sh\nnpm install @nandorojo/swr-firestore\n\n# or yarn\n\nyarn add @nandorojo/swr-firestore\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst fuego = new Fuego({\n  // your Firebase config object goes here\n})\n\nexport default () => {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Usage\n\n```js\nimport React from 'react'\nimport { useDocument, useCollection } from '@nandorojo/fuego'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  // get one document\n  const { data: user } = useDocument(`users/${user.id}`)\n  // get a collection\n  const { data: userList } = useCollection('users')\n  // subscribe\n  const { data: user } = useDocument(`users/${user.id}`, { listen: true })\n\n  // query a collection\n  const { data: userList } = useCollection('users', {\n    where: ['name', '==', 'fernando'],\n    limit: 10,\n    orderBy: ['age', 'desc'],\n  })\n\n  // ...render here\n}\n```\n\nI'll add more docs soon. There are TypeScript suggestions for all the options already!\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.1.2-listen-key","dist":{"shasum":"9760a034d2782b757a11c8af2d9bdac11ecd96a2","integrity":"sha512-KWrv5HdQ/sqYFRSjzhhsaMz7CO9Tf9akCoSVua3YqHFyOCD/6I4X1M2/USjWv1HTthqWMQKScz2ZmmpCv0D2DA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.1.2-listen-key.tgz","fileCount":105,"unpackedSize":151395,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeo4pfCRA9TVsSAnZWagAA1rAP/3L7V2mw4jwS9Q8ErijB\nmQWySZVQZt+lZP0H6pI4on3P5AsovVBPT1R/MgX3Eyr7UU2DGiVxeiRnhsW4\nHmTaDiTeKnxIwn0ONSTglcO8E5oDO6+r/QpbdHvo+vHRJx6shSjZ20IGOZdi\no46hVpLzeWrPlv8onnRnqZAocQqM2b2Cwas21w/JXiVs+dvOuGQzRYdJv4R+\nQ958aN0opRu90T7wHovKnD6M2tJ1PkrR2OfU4uK2Vb4t8O4SVlBlqNlld9VK\nS70EOsAOsxXHXctZezRxvwBdp5LR+OmY9O9nMl9Q5vccPfkF2pUx35p02MR0\nIuImTZmNpfI4Rwf5zoUOsvyz+IW+KJkhLgIQ27ulF5Ti64l3Mgba6rOat4+8\nJUdhfsd8G0yhDRF1mhQiVVJIGgAarK5Em2XlxxyTxqLjccVhpDb1A/5yiZsn\niy9S3HSdWUlav2uub6vb5q7o3Yoydiy1CkycbqwyiWLDA8CP21L5nWv7C+G1\nMWgLk4Yu7xZuVAScPP4t5CAaSik21ByFaHQATT+sb68fDdonDCA5iLNKWD2s\naCHM8KcODF5u6ocYoJDHrnx5HaMb5jAn1lB5D+dpKfGJjJLrGQR4XjiuuxSw\njA56geRUKZpjwr8bTZxiFzGadT0gIlOp7UamZXLVLUJCAu2TeMndj7PWBFT+\nhkvE\r\n=gms5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDkwbve996DNxOgtbPUZ4He/OT9u8e1B1RPqj+0sRf+twIgDU7HxItb1wO9C5Ub/eqArJTuod1S8zNoKOhLXhf323s="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.1.2-listen-key_1587776094450_0.37506838145984434"},"_hasShrinkwrap":false},"0.2.0":{"name":"@nandorojo/swr-firestore","version":"0.2.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"readmeFilename":"README.md","readme":"# @nandorojo/swr-firestore\n\nReact hooks for Firestore, that you can actually use in production, on every screen.\n\nThis library is built on top of [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\n## Installation\n\n```sh\nnpm install @nandorojo/swr-firestore\n\n# or yarn\n\nyarn add @nandorojo/swr-firestore\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst fuego = new Fuego({\n  // your Firebase config object goes here\n})\n\nexport default () => {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Usage\n\n```js\nimport React from 'react'\nimport { useDocument, useCollection } from '@nandorojo/fuego'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  // get one document\n  const { data: user } = useDocument(`users/${user.id}`)\n  // get a collection\n  const { data: userList } = useCollection('users')\n  // subscribe\n  const { data: user } = useDocument(`users/${user.id}`, { listen: true })\n\n  // query a collection\n  const { data: userList } = useCollection('users', {\n    where: ['name', '==', 'fernando'],\n    limit: 10,\n    orderBy: ['age', 'desc'],\n  })\n\n  // ...render here\n}\n```\n\nI'll add more docs soon. There are TypeScript suggestions for all the options already!\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.2.0","dist":{"shasum":"be5ffa6e95d41413925c9a644a9558fdd941084f","integrity":"sha512-WygID23zBRdduLCXuKMkb7RLsQ20RkWq28xLi/IeVOUPwchR9oTtwDD4U8lpFpkSDE5MXenXpHaVeRUeUdUOJg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.2.0.tgz","fileCount":105,"unpackedSize":151686,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeo4qwCRA9TVsSAnZWagAA3O4P/iz0IW81+0fUY8sRBWwW\nvYk+1G0rDC6XY1l5EbW3ZhXxh1OCv0v/BRwrHPi76NiLgD5jOSmE6EVXmD7t\ntBLSeKz2/GVgTXlRx+SZlKwmdx1h5W+KF4yq21FXYizkuFFMT4KUUHqitgMJ\nbn6cSCOOHLUatmd4CLofIhMZoqsUY2u653IWgyHeDTh7IK1aBgudI9FWJXyG\n2YKPl8C5fEPVcLXSn6Vf3XRkkzUnNlIWo4AaemcF40KlEKEB4oH4hSEbgjjJ\nZNRGBxZeIUcZsqqRwca70yjuYA+rXp1sC7kLzUxdP1sd1U1EmV0Xpz1hHRcw\nTzHU5PMon6IYiEMr/QMPWDKE3L5Ne9Fs0vPjWgpY0htl53sjwby9LYSU7LTw\nVw81raSTEvSK9EOlZh4PZUUrkBINaPPmg4TUrOt48R6i+gSEeExTPMRumtNN\nWCy0UnZk6ohOjt2HNqWVMSJqM3gOdiQUzpHNemE/osLkUIa8MZgm5cqDGkX8\nssMmM4eSs//WLj9xEKX3zpP8115QcSXCICw8VzeETSK8j/KcNm2ayrGb5o/4\n8vFdOBusPq+tHD5ZjkLpc8VxVm6hEgBG35J5xWGkbamr8YoYEVYf/9Sb3am6\nZdD0K8BcvQAEXUJohRIRUKap+4B63r/4Nu0Mcq99wDuGNBNNpLU974BJH/7s\nNHi9\r\n=mI1M\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDyrWY7SJ6Mk6KwHQRGdnKGQnOlrf3GQmrESK8vP7hElQIgUIrw6C3KQxR37Phv3pUdhvAAe+SmLCWKJ4sjvp4g90g="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.2.0_1587776176112_0.3799151198371422"},"_hasShrinkwrap":false},"0.2.1":{"name":"@nandorojo/swr-firestore","version":"0.2.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"readmeFilename":"README.md","readme":"# @nandorojo/swr-firestore\n\nReact hooks for Firestore, that you can actually use in production, on every screen.\n\nThis library is built on top of [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\n## Installation\n\n```sh\nnpm install @nandorojo/swr-firestore\n\n# or yarn\n\nyarn add @nandorojo/swr-firestore\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst fuego = new Fuego({\n  // your Firebase config object goes here\n})\n\nexport default () => {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Usage\n\n```js\nimport React from 'react'\nimport { useDocument, useCollection } from '@nandorojo/fuego'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  // get one document\n  const { data: user } = useDocument(`users/${user.id}`)\n  // get a collection\n  const { data: userList } = useCollection('users')\n  // subscribe\n  const { data: user } = useDocument(`users/${user.id}`, { listen: true })\n\n  // query a collection\n  const { data: userList } = useCollection('users', {\n    where: ['name', '==', 'fernando'],\n    limit: 10,\n    orderBy: ['age', 'desc'],\n  })\n\n  // ...render here\n}\n```\n\nI'll add more docs soon. There are TypeScript suggestions for all the options already!\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.2.1","dist":{"shasum":"630289713472e1ffb3388a690c403a2de7b3a5df","integrity":"sha512-Dh9tPcNj28BkJSZbxoLqvLZawXSZ3YQmF+3zyhiuOXEzfRR8SwCFuHhlirmRCDKVBlTwmXpboAYlRdmtJhw8tg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.2.1.tgz","fileCount":105,"unpackedSize":152369,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeo5AoCRA9TVsSAnZWagAAZ+wP/RkiUewsL5TEcGhn2Yk4\n0/YbzbUXA+6Y4JSR9y9PLm0EheIiUmPzEMdNRwR5TBuSY1rj/fBCOQE06grN\nvfjf3xnRmyUOJ3Hn1OJC9CK6gxx0Gg+DOJINQxdn9sPXttgKcTbcqVI73EdR\nwt2kKOhBJl/eyliBEsqG+1TbeT3B2vt6GFNB26whBrBvA4oaNT38VyCy4edh\nhcs09DHC+leeC6q7Jwr8UC/PBQiAfP0v2PkgJfPESzkPbp7L5IKlmZwME9dj\nxMpxUbOtVfimVe7KZ6p9crvOz0BIuL/k+2tHVJY7mFgd/offkGzbhOIsR3y4\ne2+3fWGodOL0B7kxkftki59NbKwUWhPpt6Us9SUacVgwajQWOxWpgPn3ddcq\nHrJn7zZr64GzQXWNbXDemOOLY/tJym9vjEMMQ4Hjchp8Ow5VgBsNvSXwYvf5\nz27aBMT2WcHSllutHnpni4EqliZjvyXTzZZd/MNewlLp6AbjnUPGbnL+C9uI\nYH57iSg4/FB5Jusf3tSMptkhRT2Z1ltW60sK2hQG0va3pxIibkukLk6Xnqds\ngTkUYNX42gdoAy6II2PlJs6McT7+7xDaNIDpzRlrNYOAhT4C9ne84GIqzY1Q\nUuEtV856sCGVbQYl6lr+911bI6pd8XCy5HydvtZ/9H9DbDXmCEnEZ/MoHK0h\nssOH\r\n=28dx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB/pWhPMHmj27xJENVcMVBth1UrkKrbYgH0pVStj4DBMAiAXuC/Z7GYrV1xEmFp76+W9HVXnfa9AnJPE6fNsHFHdeg=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.2.1_1587777576253_0.7629025778911191"},"_hasShrinkwrap":false},"0.2.2":{"name":"@nandorojo/swr-firestore","version":"0.2.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"readmeFilename":"README.md","readme":"# @nandorojo/swr-firestore\n\nReact hooks for Firestore, that you can actually use in production, on every screen.\n\nThis library is built on top of [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\n## Installation\n\n```sh\nnpm install @nandorojo/swr-firestore\n\n# or yarn\n\nyarn add @nandorojo/swr-firestore\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst fuego = new Fuego({\n  // your Firebase config object goes here\n})\n\nexport default () => {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Usage\n\n```js\nimport React from 'react'\nimport { useDocument, useCollection } from '@nandorojo/fuego'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  // get one document\n  const { data: user } = useDocument(`users/${user.id}`)\n  // get a collection\n  const { data: userList } = useCollection('users')\n  // subscribe\n  const { data: user } = useDocument(`users/${user.id}`, { listen: true })\n\n  // query a collection\n  const { data: userList } = useCollection('users', {\n    where: ['name', '==', 'fernando'],\n    limit: 10,\n    orderBy: ['age', 'desc'],\n  })\n\n  // ...render here\n}\n```\n\nI'll add more docs soon. There are TypeScript suggestions for all the options already!\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.2.2","dist":{"shasum":"a358b7b7bc5556f3efb81561927d7341057636f9","integrity":"sha512-G0YhfU9hJcfc++JHWYGgknT4kZBw2RvW9Kx9F/Kq38jfeJ4uxTAeg+GiSiU+jTM8WvK7xkWO5I2xrTN3UmmUnA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.2.2.tgz","fileCount":105,"unpackedSize":154794,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeqbY4CRA9TVsSAnZWagAAtJUP/0U2zs/pmCN5nH8P4BsR\nA5m64fSVFvYc/3uZPmOdlP/vbXJyXmWQ7RAoRocWkPzzJo9kv5BCLSMyU/4+\nspWxCn7FpziIiqtleZ/+Opcd+zAVF48YUv0nzwvPYYUkJodjVROV8EziQ8Nk\nQQoP5K6EirCbsrRxd1OMdsHfUf1kSTTE/I0oUL95Hautwu6LbQ3Xic6IGFAF\n5w9URWKkd/9m4X3LIH9zRubi4qzvIj19K19DHKgjoqA1wR3BgHX//7eskwV7\npgCgc1U2WyYq0eczO/GgLnDy0bYdM0ek4ynGl48z09k+YxCwN5KIiHr0cU5E\n6ioSeMXNal+Cx9JYOtNlElKEnJHTlSRZMnfXXe4bRPn8q++PLn4bUS3xSIzU\nbTG3itAo85wYh40mNLKe7cpIlA045yPJDdN0ZOVZbYiUA/C8uQoxHtPO+Acf\nPNzY0aGYd5AT2rv9vJS5+w5hKz8QuHL8Nct/mSktAVePwjmx5LuthZ7X8g6q\nBmzNLBeqz5ysgfT45lCWXLCKgHzREXP7PzbhDUgGXqfdld7Owh0GJ/yM7hKC\n2HN8zCuWAfJjkOb3+VrQTsdYK5OQvgNKPLgU4MlPMgshgZlN4xxQGXWQf+W+\nYRBZq30xEYEn/4CkQuiLZ1RcwlOBDIm29SR48LQ1XyxBnvV8F4gRlvok25+I\nXKxh\r\n=vh1A\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICa7OUazwBUPPjNN2cl0fcDsm7HU3CZAlrrfAdJEUtUXAiABp8vUyv2TE63cKF8fEUQkx1o5xSSiM2ViLvmchHbU8w=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.2.2_1588180535485_0.27341215964983845"},"_hasShrinkwrap":false},"0.3.0":{"name":"@nandorojo/swr-firestore","version":"0.3.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.3.0","dist":{"shasum":"17db3c29e11263f0bc2b0a1f2d4506aab7cdefd5","integrity":"sha512-hQ+V6X5PQuHsJ3W/UkOAe0fB6Lycc7ldaWMB/AcbemXmcrNi2HobAWe1VN9hzLbMpPQ/hUEP+SRQPvg4bDnElQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.3.0.tgz","fileCount":105,"unpackedSize":154794,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeqbjaCRA9TVsSAnZWagAA4AMP+QDkGm0O5otSnyWczcu1\nuQ1/RsWyVirVnn6TxApmZARtybcrqYYpiveYglMsaSLP+WFX4KS31mQznC5O\njZg8pGAPlvEfIab1Sb6bLOsgI7NCI4jmGjtWu8OlKI7DXobkh6garcX5iEvD\nweqsWy1sqiPFuxBIh9PGdvbfycXM6kUx2lpM9lbXC7CjCjL/ufKsZmCwJ/Nq\njPu4pOyhumDHOxiphfv0j7Q++zKvTB15KRduFyJshZGiHkcNFV3NSRKvTcY0\nYT/nH8S1RLTTolvQVNzI7CGdTx94RHF/tGSKvhf1od8dqZwnm7mnLZ2JgYyC\nt7fYNJfKro8f9q/ALwQRqLe3hPV4xGk1C/XjbCfpxbEhMeQ7oJ5rF7hErISM\nUnpExaAM+Bo2+fot93QHDAQ3w8hHAvHOq9sbn1Fxq41dEPOv01G23CyobZgC\nMMMfOOmUh7P1hCIkt5KeUDgX5crBZdsWAnAAButwT7PoCcjaD5OT9LERe4HS\n5NARSaP+6oKGClAlPu7wBSS6zG58F4kXWCvyy9M8KL4foU7rdz31Ww7tuiZT\ngKb6WJp2mCrS6UzHin8B4+auo9FPkle8HtZwEannsNANU5ozm+hK/xcV+cBx\nqH1leBhhI5EzBUMrcZMIOvM9WyLE23JDWTBm0dLK7XnpQRh9Eo10UdhvUJix\n4xrj\r\n=Eax1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCVoIboq4tRrhTIZe74F/KXzV0aYKaIRU2J3RH+c5CWTQIgDv5fAsPgLlDkCwpcZYxsaalJvoL9AQIotC5m+KWpnbw="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.3.0_1588181209980_0.7012621414277747"},"_hasShrinkwrap":false},"0.4.0":{"name":"@nandorojo/swr-firestore","version":"0.4.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/nandorojo-fu/issues"},"homepage":"https://github.com/nandorojo/nandorojo-fu#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.4.0","dist":{"shasum":"f24bb66ec4336a07cde2301fafa188ed0eef40e3","integrity":"sha512-3m6xkRQgqAd7g1Xm6nbRkzI9Ljl5E6btOq1XXhbwan1RfgtvoRxPcxLgQ9kp46Q9lEmQkGeMxYCS3NGHchL++g==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.4.0.tgz","fileCount":99,"unpackedSize":151462,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJerGlUCRA9TVsSAnZWagAAuLcP/izNveFKnwUZ477qQ75j\nR0oq/5ntgyqu7gfHeHqhVqxDYgs9OdNVO6OL99fcUkVlibGZ2vLclj9CvabU\nLucIrqWTisnFY5OnimDyAgcfKt9uw9ySo5nsPy29eK0GjuFSOjrvrq/n4bTz\nbBNEWul8/OhS2vrN4zgSwBMllXdv7qCGQt4k5/BlFbZb+De3a/XRcm9rrgWf\noNoj+unSdcc3/jzFnGa7WBOnkVSUm99lATm23zPLbBhSXVNLpEFLDFnKsPq0\nhWVGfuQVaByYfHJHg/gVciuHfWWdO8eq6wV3zxbf6sSu2HcmvqIiD6cKYnNC\nGof8qi+QVwWw9SXTLwS/VRWTaUeXvZ73A0nl9FS+uNZNOIUa1aV1HMAObQm4\nLteGhzELcoZyq3M7TjVuH56yj3uWms3uYB9CtfwwV/PNWxasZr2Bzi4c1HNk\nkWgIPoRd7ocN6ub0ZUVS7u94uvBVr/FSj/YdzrTRPR3CVtn8hXy1MT9cxS2P\np6ngH5xduw6aimIF3EGqrmYU9d6yZTCqpsR3yoi3u2ohaeMmIRdLmx7g9LFH\naPiwOpHlgD7V8FmsFRcYwAA+LPCMtahzaN9bBOZhsFwx2c5BvwSrSmsZroXc\nUEMRjceadiw/7LTLoc2zhNZTgRKNkXD2UxawiWTyLXDOOmtZ1DXp0Vg47L/K\nUMxL\r\n=+/q9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDuL0tVCgS4WEJMkfD4JyaeFVn8QNJ2HbYuCElZWGs3+gIgWs9x6yOx0+RxXU87D2QajnsiJ/SCXj6B0idp21FdzB8="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.4.0_1588357460223_0.4978023465730148"},"_hasShrinkwrap":false},"0.4.1":{"name":"@nandorojo/swr-firestore","version":"0.4.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.4.1","dist":{"shasum":"d616d617cc41f778f763b5e2b4df735cd578a936","integrity":"sha512-wXcwpbvnMzMhuZSHGRP6JkFkjFmCCQdWG3NS1wcqjMP/KfkAkPMgciDRtSnc/RqN7Upqd2qK7O774wt7j4k2dw==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.4.1.tgz","fileCount":99,"unpackedSize":151464,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJerGmiCRA9TVsSAnZWagAAU3IP/3jL9RFyWeZGUh6YEjIp\nB3NdllgHkmjzGNUhAwQoCmAH/wEs7hrDz30jKHJV824q1ZU/V1VncxhcNysY\n3eRE0HzStOj+fioDYjb4dL5dECEx0J3At/lnd6n0fgsMyNlXl/7PktQqL4yc\njAC2nFjf28ExlKYfz7rv9Lg5Ueztp1wgW36KA7+nF7zQ7oXKb+T8ptH5m63k\nPb7NsXOFs5YXHNLySnT8NxW3DsfP/ol6J93E93jjdmuxxJ+rs/5R7na5d08r\ndWZ7AeazsoVxBW+gWyGPwx14ZkWbR77eei5yfgmVFdILGW0oEeIAJVA7HnJV\ny6HHknWDenm25Q/AJDr/tSfQL9V6LSk9H20r8+FUwSdj/XhS/IVo7/bbQmd2\nnJFM2kc13SEhHKu8IQBBb70EoT9tdilVhougp7z78Fc9a/GIdQLJu8M/zuGD\nVLfh3b3+oQ+e7rWbbR07S1XdXIE7rKhpyaM8ECN8i1IRU4VtPHWeZj8r16B0\n6s+4TwovvR+F3nnDsCpVSxC3F1O1mKly+n/RmxlKz1DmHUnSEFsNcPqnAtZr\nJO5xx5m9J5Ng42HYtJFBNK2J5cooRTVLd429YgS1JEZ+fXmZA5kdcLYnDX5O\nAjox4EOJI5gark7UBxV0K7d+aBD5BxWMtzeVltS/FUaalnMZ3DBEuuNQUcL8\nm2zK\r\n=/KN/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDkUzyZvpTgw9ceeNCEJypZiU38VcoBFr5zGMVTArTJpAIgPcd/3nf2VajqtEGPLwFReEJ3+T7lDLASzouiUDzenRE="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.4.1_1588357538120_0.6691484512653563"},"_hasShrinkwrap":false},"0.4.2":{"name":"@nandorojo/swr-firestore","version":"0.4.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.4.2","dist":{"shasum":"19704cb43fede777b8a29d4c5f806c028a6a6d5f","integrity":"sha512-otXhdzzz7fW4rNB/nPY86W8uTvl0zFCpnzlhKYqxYHD0AXCo6O5swGV34LVrpXTJKt+W7x9CpKCYVdQRKEnCDA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.4.2.tgz","fileCount":99,"unpackedSize":151464,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJerGnXCRA9TVsSAnZWagAAwVYP/j5VSmIXl/uCN61PbBH3\ndd9f7MR1QyP8kGtq0WrAGCGJEGlutxLxGGKmRQ1sxSqf3cqdHaJ0/BFJJXuC\nRaAPrTaFKzLyvq+us0Qh5RbN6wE54XxVGt9jlldBIrOK7+fzB3p6mCFKro5r\n2uOJa+asb7/YiCPDonwdWphuOBSbRUp4HJ8sPCRVpM/G7r+YxXdsXROAl/A8\nilEAozLU2NApDAUGutX6qZXb9Y2kDSdpBLjh5M6q62hGt3CG2FvjhGYG1o9X\nU/LtsZST9xNIgwqOUee91xnENXH3Py37YVezbq2aVfkTI+mCsRQqOLBfFJ99\neehp90Y7B60aJPRt4tD82611A2WEGGxExWiQJza0QKVqcf+TK/lwrekG8b/+\n/2tnuAlR1IUcgbr/XN4+yJWK2lcHHs5hHnXLedT5HbhNdqtcDqUs9qKwwUQR\nUtGqmralVfJMVP0PbLU8ssaSNLP+NkgU182Vml1tlcBp8qMGBCEs3tPMagWu\nwRNAfNIQpue22qlckxh5HCXiMdLkAlfZT0KgE4yGgCpi7fyk6P2xG97L5fwd\njsi8ZZLp3r4cFqV0KeLJCvYPp91eAVnHXK39+jqTgSoTgbMyVNrPO8fYDTaF\n5RSd734EXZfm1Fw8/fRXKjr08x+O5t4vzCz5SiSzbaesoEGlVD9UTo5rP0/i\nDdp/\r\n=mEQX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDSVXGvqXmgCCZrBy/dVIRr4I6zeJQVHd2of7eu4k2goAiEAqZk3z0uZsu93UMPWerOwc/lpqkP1xgymwoMvQek0NKA="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.4.2_1588357591078_0.23909655999064383"},"_hasShrinkwrap":false},"0.4.3":{"name":"@nandorojo/swr-firestore","version":"0.4.3","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.4.3","dist":{"shasum":"39fb056b96d9a5f3726b40dae29b5f1d0fe74732","integrity":"sha512-O5rCjKKn5FTXn2c6rmnCpHwLzhpsEG0ycITwPC3/zWarUuDnkZGe+WUQLwfeUkGzOJ3vb12vtyaSmyB+TxPURQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.4.3.tgz","fileCount":99,"unpackedSize":151464,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJerGr3CRA9TVsSAnZWagAAqJcP/Ahmho1Carmvi+vdRvS0\nFz+Ve0wm9lx4za9K4uiTDH55wvXGjYEb7MtJOmwu3mxApN7WuOvgGP/BH3d9\n1g1QUrFEWgTBAALWk5gEHGzoyp2LSYYuKBpzgICcCaDomcg6K9tc4F8yQ+ci\njx72xp/eLdFwOmXwMm69dqO9NkjSpDS+odd2Cy9HRlENoAjGZ7pUXxC/TA5L\nZ2jZnn9oq4fbNpzFHcbB1R95VZkdCv5M+zG9GiDcUz5dCty5NrAehOL3bd/S\nenakDjI2F4q39xRxjpSO3c8gbMal4t2jqbEbelpKusn+pmZCLy+PfvITI90R\ndqpGYHDitAPZvdCNujpDxkI54B+X8OOjiBdLjGFlDKD7j3vikQHQRuQIB414\nciTRZM+w9ZWhavvYdQ8foKqxmPV4KgOfJFaqJmiNnC9sfY302kPkSUBngYPR\n3Z13zZn9zfsIxqCX6/Xu22VciFwoGA2NPjyBlLT2EaJcck/dCkL79DrvHUWR\nO+lcxJAMBOt3wSD6AWiTd08X2y0EYCsjuOqXYi6YfULDo1DHBRA40UaYWERl\nzWjICdikiuqxwaQNmLSNgk0VMaDNU3FFTPKj2NrwdB3WzBnDn050RKu8PLOJ\npEI+tGVy15bqfC1ECw4VvL0qxASvsJdN0cdhlOCd8Wb+KOgAP51a187fDUGO\ntQxI\r\n=lzso\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCGyfJcBqeA1KfQBelVzhIYQfPAqSTLOhiwc7XNpicq7wIhANNlMhGB8pDCPpRDGWP0BZ41vKL60pGk5QtQelwj6Tzx"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.4.3_1588357879090_0.15979409547187307"},"_hasShrinkwrap":false},"0.4.4":{"name":"@nandorojo/swr-firestore","version":"0.4.4","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0","use-memo-one":"^1.1.1"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.4.4","dist":{"shasum":"9e12e81475b14eb7fd2fe03cb8d964df3a277687","integrity":"sha512-yH/DzSWDCz2joByMWeguqNCgreiQXP1iYPZsrowEKUYcU7iQzyEgDM6Stx54CrrvwqKlhlUQnFjefyihyoP8Jg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.4.4.tgz","fileCount":99,"unpackedSize":151464,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJerGspCRA9TVsSAnZWagAATxgP/i54GccQjgDaB4e/wBi9\nFmFKB5Ovq9S717KAEeDy/F/hte0xjaA0frq9KP3A1frX8Yz8rb4rzdnJE1rt\nTww41nEQ06ebQaCs76IU0qTdI3JKJThpOoWJQIz/w0OVKeL5yMWnDXHQjApJ\nCOddQL8iE/SDWYUkt5KVsjBCIdb0veWP2XLsiriq5FcDCTO4kfPITJuR66hH\nDLhqFzWNf1VxAX7IyVF648jVtaL6FqghKNugKdGLI2tm3Z6dxjaQvtOyzBCS\nIQ7M9LefRCA+dTVIZs0In0lhZCw4gUcAjzDwkElJcRZ/8W5FgboEcLwOywud\nfuMsh7o5+qCa4CqDwLxe16aDvF6zyxsukjPZIwfgd27L3O9vI0caJ0rzaKq8\nyq2BoMM2QC0a31mWknqJf7oohltQ4pkyhB7RJapyDTO7zI4q0TB28v8HbjYF\neeRa6Oa+576vlTWunrNToyeklX50Lb3rsVSftUulM3whImLSP/xN9FaYcNI3\nQDf9PX/iMYOFxUOiDIkiAeC1RGJ2CHRDZ1/epWFiZKOo+/H78dYVO9N2ILu1\nneM3v4DcVpxJZl951GqW5JfLRNreMjIT4TQbmK/xvAyAXiz/d4KgAujOoEoF\nNir/k7Ho1LO+ZM8j9P4tSA82VVRHFn6w/RmBrgGAmxcMTdsOVVGAIX1RcDPe\nA1o+\r\n=yFIU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCTJqkd+7l3vROVl/0R464VhJBhwsV8J3BGJe81bcGIcAIgO5/bTjBLMfOA8RIgkgfY3sXwc7KhLxY6gqeJpaAvg64="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.4.4_1588357928549_0.21846327752803685"},"_hasShrinkwrap":false},"0.4.5":{"name":"@nandorojo/swr-firestore","version":"0.4.5","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"git+https://github.com/nandorojo/swr-firestore.git"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","husky":"^4.0.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0"},"gitHead":"e73eccd386929ec7d5874373b2d64a7e57b272d1","_id":"@nandorojo/swr-firestore@0.4.5","_nodeVersion":"12.13.1","_npmVersion":"6.12.1","dist":{"integrity":"sha512-7YU5Zmv09XKQeHgxiJ74FEZARap4bnrvFYViTSnlKFJO21tgIsICjHvl9RmybHacyqUlVloFkBFg9lNcNMjT6Q==","shasum":"fbf6ee851b1846913130e615a13736ed395bd1c3","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.4.5.tgz","fileCount":71,"unpackedSize":151434,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJerGx9CRA9TVsSAnZWagAAUk4QAKTzjXOmosIYj2jfHh+I\nUii6X6EprOzUpeNc8qzzQBQIkZGHcM5+5BLcl5wjHlo53Quy/ELu+AVbqfap\ngNhquibPGAfiDVIHogRloIcn2Bp33vcqgbtLtMSJkTq7t73WRmdiT/a3cMuP\nPRp9AW8AieBN9jDAaWsV7JzADQBlpoMorOwUSRsK61C5e8Ws3haqeDscrRpC\nFZuQaQV5Aix/pJeqF5lv1lLJo3GEtGNFHi8daz9dP75YYxsYLuTpNs4usOZT\n7b2PIMTfWEHCrMDCi+IBT29pasXQmv24oF8X27fh1sUV4Hjvr+namBJ8de2G\nuUF+IWLecfBIM9WasAl2oK/h+3dE57hVqAoNyaRl8JpOu0T/rEgHgD9P4lpV\nKTEEgGZahVbq0oqof7e4EvFpP9L3xpKltrdbNrMFmnrkiMPbQdEbdJUaU6qS\nEPZHVO+sVqmuDF5AS4HBuzOKdnPPDGJebkxfqQspF9+KJyF6kHWQcH/TGRfS\ni/JgW3pslaOJ4eBWRSeQiQvSBp9aixOV6QmrP22uFNO3oPq55fUIa6EFOfA/\ndmNogX6tEdLE77Pf5VCixyTFyu1gFCqDA1cSuvRn9jdLyVw8X4VnW+aLsHKF\nJn/5PWv9RPWFlpm3CfXBQLYHH52AufcE0XXSasV7DVuj4PEC3lsAfbUSvtCs\nEWlF\r\n=Pia+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC+4f0/pn1PXwxcEomthKKaowSIWmY1g5JWCumMF6q3EQIgJhZ4w3E5+iQEjBGEdK520b/Pkm5WaW3ngSXZNu/yB0Q="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.4.5_1588358268641_0.4117223148195659"},"_hasShrinkwrap":false},"0.4.6":{"name":"@nandorojo/swr-firestore","version":"0.4.6","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.4.6","dist":{"shasum":"5c61f4e0665e7b089f84af32ccb57d1010b60512","integrity":"sha512-JaRAGPmiXSK75pUIinHyAkVtyYZSGzxtfEx2Dn49AZ02O13Jr8IgwcMFcmpqkjD0aa3/LibnSMgvI8nIzstjGg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.4.6.tgz","fileCount":99,"unpackedSize":151403,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJerG4lCRA9TVsSAnZWagAARY4QAKBKGx5eY9ajKEl4DcTL\nabZtvayJEysL8FX6MPlt8qjyu5wrh7ZDGGO7RL0dQSVRfDXgZhxdV6drqY7j\nqvUcoAXPFwxN5bTvplqVrVcpEwEM5NtPCpoX3AHNQWETgZBmPHvkqqbsulDG\nFV3DCdGO42Kv2P4tOdT3iFBPWCS4VdytPTmyEhN4yOr07ORTjHt+88VyKfZ6\nA0n8c4SSZhJeLwkjQaVosSeUiFX0wstwSPm8pZZWqTOjyTmxDwRnxVsyKdx2\n86vw09+Va/6A2+KHZaGaCeR/LoRLP1EFQLuaNvTLNd5fn3b+56xNHrhdhjHP\ngANXjKE8oZglsqNDFb5m9ERhy2SP4323H8YwCe77J+Z8ChwVkkdchmOftTXx\nk4cRNAOILKv5/daF+IdnD7n0w22JGOMzJzJuK7lqumSng+fw/RP31H9Ebbob\nS2rVejys/zTUWcNO2V0yDda++tGUZLvBBrj0tkCNzB5g23oza2lXQD8414u5\n5ukcEuAoyz0Wo+1zNIRG33D4s6jN/Zs9uO26sLGLkDChxnt7vcI8czAI0ESu\n/DtzKyJ5ItLbLOtuAnY90/Ld1ex2SbHsWNGCg2JDksFUgYepabvUdLZ8AloR\np+7DP9vv1fkPL+g5O/p4ZHjH671xabwh29WoujRIKhKh42WCB793yxMsd9NU\nOink\r\n=K8mf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICx2WkiDsm31J4jNSardnHfAIApXs5GCsdFJmZdPQhfjAiEAk9u0NHlQE+bcyTX8JmCHSMkl0206wIndVeDmSBiq3mI="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.4.6_1588358693501_0.2466268070626736"},"_hasShrinkwrap":false},"0.4.7":{"name":"@nandorojo/swr-firestore","version":"0.4.7","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"git+https://github.com/nandorojo/swr-firestore.git"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0"},"gitHead":"570179a50527717df7415c619f4ad705167c868f","_id":"@nandorojo/swr-firestore@0.4.7","_nodeVersion":"12.13.1","_npmVersion":"6.12.1","dist":{"integrity":"sha512-N8+xIMBTnCeMy4ZBnCAHHbCC4kDXjXDwKvhmkH5h/5pC7kQ3HIVo/N6xF2OQeUh8Jw9kCK7++bZFSZK1CuA+kw==","shasum":"d3d2e65b33d3eb82da52c56be7b3054ce71086eb","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.4.7.tgz","fileCount":71,"unpackedSize":151403,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJerG5WCRA9TVsSAnZWagAAJbkP/R5mGLZuZZEnS01iv0EP\n6UJR8T6dJIWRLkigu3tEQmKUjzkxI4FF4SHJl3WsLxFlX5+aX0F2guCMRUKB\n4FlrWddhyCy4lWJLcTS3UJcnTudrKVJZTCqBADPD+LRnoiEyh+v4sv5EC7ab\n/45WLJLSbCgl9RoiY+uO/I5hJLWA0DXqQ8R9wer4TPAfEGY0IfUt2iib+qbD\n3brSxXWq6/cC7Xte9JUXWmiPYYlTdfas6V6dKHq8W0v2jdXqQTf2jAoanC20\ng1D9qp08eqKc0sQrxqmxeFuoj8zM1zo1SP3Vn45e8ObFuZMNZO3r1bJSjDPX\nTDYsb2AuwxtZLBiGEm3xEF9qmJeqH06Yqt+JQconGvjRGJbN7Vfi7fsU4VR6\n2RizuJnLPRt39itM4VA2RkHaututcT5+dnp2+h5+lRZjY7Fo0QY9irgjJJNf\n2qtPkO43BzrpvuKfZctKvoSe6lrW8u5hS9Y0zMC3+zl9HO2LIr4tONkS+Vjp\nqCx41rWzV474gr03g3Y04wVKKw09wu+T2YCT+XsM7z0vtK8fyb+LvXYLGNV8\na7br8LmqkNRKQdLMfFPYbNt/fOmqfjcz/lf/NwvSPpocsQBcIMBwUvxTc5bS\naH2g/O+JPjdOUwP/3yKgvBGiqZxJoQM1FiQ7QTnd9KkAx+IDw0u/dfNO1CAr\nxc/M\r\n=RnIX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHrR2RD+0PzX4uTLIUhLeo6REAPt1JSjMUiJpHtRUHgxAiADEwtXLWEd0xXqFc8wE0pZPZnIt1K4rRxFK2C/Pp0oKw=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.4.7_1588358741599_0.5721581365661106"},"_hasShrinkwrap":false},"0.4.8":{"name":"@nandorojo/swr-firestore","version":"0.4.8","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.4.8","dist":{"shasum":"a0d6b0c77be443a52db5b4cda14d3b816ac618d1","integrity":"sha512-mA2rFYkCTd4pjcBh14r0YxHj4q/SKi6Uv6A6ANmQCZ65ghCGzKntCD0TMEVUyGAq3vAe88P/yDr8p0Bs//bKRA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.4.8.tgz","fileCount":99,"unpackedSize":156601,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeryvRCRA9TVsSAnZWagAAvpMP/RnI3TA7MLwklVsNz/X+\nGQ9rwu6serXqndMpkA588BA/1tP9cNfXNRLk8oKnCkCmT4q00eX4JBdYGeBj\ngCdfI7Y4kM1L78a2MBWWdVUPnrD1ofFaHD8BFd8Sm51m37FQSJD0G1uguhPP\nVmxbJ/7uFdZGusQemHwWiuD1IGFAEUyy9BwbAhdop2rupFMfw5L0FWQwtVBW\niS8qtFtkhVjO6coXQkTITs5C14jIXpPYX+XaI83J8cydpyjgcekkDtjx/dK6\n8jicWAjfKC4tEySbFuiK49DKk08LwZQzQRi0GUdDfUYXihnXb0lhODikLr1M\nhAchR5upJTywKLUpoH2cLba3qH3FH7yOofAvgRBi6AEf7XVJJ1gwGBwEFbNY\nv+eEP3hsTTe7Ds8RCTyJRqn4tFwCNZwRE0fNFx2uyhqqprPcSY44VhUo6n0Q\n5ZU9tNiCh7BkWEV88yM9kQxotxZIoaB9eJQiqh2nj/m2yL9Wu+bDtsAPTwWA\ny2litrA5KT7eSgqqSemVNb5X9RJrxWAHgNPN6ftNNxxakgmEntcQTVOlJ+NS\nxqkuiFrVILvzvGDeus3bItReINtAn/AgaNk24THITqJE1GPz7Cqa8HYPTs90\n9lH3ojKiVdHI6UAlywHehzCJHbBWI3QSlXON1C2lTz/bydlbijWpm5YA+rZx\nWBkN\r\n=2zvN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDt01v6q0v1D0pU+QtbGvqAHimxOWD3FAgwUgYgA3aJyQIgSsgZ9LhU5pSUZvMhWVLiCv0P4nE/zXaku0MhuIn0wtA="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.4.8_1588538320643_0.1604429983457698"},"_hasShrinkwrap":false},"0.5.0":{"name":"@nandorojo/swr-firestore","version":"0.5.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.5.0","dist":{"shasum":"314ae865fed49c2bc3bfe5bd0a82afe9883f018b","integrity":"sha512-pJpRXsVvU9EoHyd6Aa7P9Fstw7zYtw/0YVQZqIwFIkMqlpr2QdiaRA22cBAidY6Xhmx2b9yEPoWMs/55rsGg4Q==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.5.0.tgz","fileCount":99,"unpackedSize":157284,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeryyCCRA9TVsSAnZWagAAi2gQAIlpqvbJVHYKUv7pyr+n\nC5T4sfXbEs0oe7U19RkE2J2Hua6NMluIASZfTgh8g9cEqZzlh72izTNn4UbJ\nZMLM6/zkUS9E8KfPwxPIeFCUenTzjl5Pfsc4cQXj86o0E/NFc5yMhLO1ESUW\n37lcICQBG5BcF7eGwTrtjBd99uosEZ3wIdOFClqnNRvvEC71Tt5e4KkZd9qu\nSL2neykLdzJEuFOhaCKjDVyzzoTOYK7ieRm+Gvv9EiiIt4NXNe5IAT+7iNWG\nuJh+dOFK0wDLnN4DcfmMM8g1To5DLtYi7NV96ojzFrzWt3kDV8L5AOkFx6mn\ntXhk9LO0YcPC3wOS1F06qWurp2zCFZO3fKABVWUJNbXRlz6ED5Y1MzDjzwJk\ncaVVZfJWvK4MRdq8qHnhvZUaKcvXCCRWl6y9QExmy9cEfJegJqayfZM2E8uB\nUIT6fV/1MynEPGRIOcGNbq38xIz8dsfuS3riTcF8KCHrJi+s/KkyAcRfBaYP\n+HmMn0JIJPP2hI+O9pt4uzGc6ETamP4csnBEeLSiWgA4tdfH0Ld9eg5TEffW\nQJFanBAaJStRnQETorvHnjWlGxEt8tTS6CDL3TvtQKGnjP7IHkvBuWG1f1LI\nNNquRBUSYyJfVYr/lttYmIma6Q9XY/3xGI22piXfJ5iOxvtIeN3aAKcskJrA\nG29C\r\n=WCx6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEMCIFl+EZwz8ZyzYQ/QlWO/17TXIaxUkrGOIQNKLp150s5aAh9DVTihmthedkuiCiAmKwJr3ZYkx/GdG81b4vXnS9cE"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.5.0_1588538497842_0.5281695926788912"},"_hasShrinkwrap":false},"0.6.0-alpha.1":{"name":"@nandorojo/swr-firestore","version":"0.6.0-alpha.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0"},"readmeFilename":"readme.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared global state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`)\n\n  // ...render here\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.6.0-alpha.1","dist":{"shasum":"ac7c71787f2e0b151176808afb03fe52b7761713","integrity":"sha512-cPO5Nmx5HQ3CzZGuf1zKVvDBGsEvnuZL1zAudoidJ5Rz+k4olD8oxVnwsMzybCXGj1wCgzCg4fpp1O3CF2hqTQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.6.0-alpha.1.tgz","fileCount":105,"unpackedSize":178157,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJesywdCRA9TVsSAnZWagAAQSEP/0lQt2PHVgbIwquSavml\nOpDkOCxb3/eWcZLKGEEd6y0R9UzZaFSktPgzgEO8HhfjHO1ObNZeMxFgO47W\nw4B3a4v53WniFzgXyYEFzal9bkzRxVvajUZWm9TycCydfpFxwDQnxRr9tXPo\n6DcHBYnddar+/ZE2ywyfafeUDc8WR/6p/8kcDWdaLFY6+BQYBywjLzPldWSN\nVapujzGCF9yU+oU1Oy3UowKbc9pCXu2uaq4s5baYFVOWEGO9XdQFuJLn2Qxq\n0zQmyHpWoev0Wv+S/mNYBKW7vSnlQYPOXA6UQi1jTH/NSypeMCUVVpWimQs3\nDwBfP+aXM/9dxCxQhl9RuO5MtyyzcS6ar4Rip6UBwwXmJTGKfBZF+Tjiv2xi\ngNbZucGzzXh9ECXSs7FwGZXvhlxg+ZJzoz+mFU9dAM7wCyUO92syJjxVvAbO\n/U6cV78n+Ibukm/ov7rnV93+5xtgDahlga1Cuu4LW8iZB43v1vvXWRW32bYf\nrGeLnMkJ9fAv9ecNnnZKp2u6hLk+q96Mj8dDpktVnlLL4j4VZCxpSiDvUxPK\n9zDky5oZq9OG7uAEqBL+KvhdHci8Fh7A2dxhUZz+uwGHLIg8vY1l0xgwp4ou\n85NJexq71EuIhyVYSBlV4oOBEP6aIM7lahxNM7ljujQkFgJ6z6Ssc6yrg3YS\neWJB\r\n=yTra\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCx1bLCl7s1djCq9ou0Fp5PuuKHYv7LSadTi6wi5DIe1AIhAMBnHviOqw7Tw2OSupNHW+vo1UlO5BLvfvH26+wpuAt/"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.6.0-alpha.1_1588800541255_0.8554113533251462"},"_hasShrinkwrap":false},"0.6.0-alpha.2":{"name":"@nandorojo/swr-firestore","version":"0.6.0-alpha.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0"},"readmeFilename":"readme.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared global state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`)\n\n  // ...render here\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.6.0-alpha.2","dist":{"shasum":"94f2267cf662c7c5b3824fb77bccb405868c268a","integrity":"sha512-2BZxo3EzuG/xE9B0YG1NmxnL+rjyC1cYTSp4OoMSla6JlBkhlIeDBsnsaJn7PsxKT4YQiB7XM+u6JqMehiTUcA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.6.0-alpha.2.tgz","fileCount":105,"unpackedSize":178097,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJesyxBCRA9TVsSAnZWagAA8w0QAIKTf4DCrYE/nHdtOchZ\ne69YWkaWy3Czz70LfmM4PYAQf7sbBbp9g5eqJ+AuNNOq/NopIDjDbiOyG6Is\nv7ulH0A5F2ZH2yNrOptH9/rBP8d2ZKBKViG1yNxk+q4EXmDd9bQTdtoHz5+d\nHvB4CgVz0h6m1Nm9WmpBATd5C9b8yznuei2sYYuhpfUlCzEyGj1CeYhs0vxO\nD/Md2Pe55qjqGSdPJecl85RN2hoSbrclp7bXiWiJu6lRQ4h7/iKh7NjJLyZs\nwuzMnOTMcpoDOHxXfWg2Hxt/MiuuZahwrt/BKMulC0pDo8cBTQgGVMOsSDda\nDzA8teExTqcmlzZ7yqbPE+5OungAcO0Ia1b56WPMBXQ8puzjkbHXlpeqVM1a\nw8xZgSxe5T6rLyWODxeEibKivFWt71hobQhtvbRUF3MBhyInfEvPKTZ1HXn4\nrvyyXQBhb1VzIz900U0Eoz3tkUQ8LeZoJAFb4gkortHpUxPeJFfykq/P4WsK\npjCPtYELq/o7FmjUuxIRmB+RDHX2w6kLTW45ar+wCEMtAg1FWp975kx7Yry/\nv003hHOljgOgFYuT6Py3F+EJQDT9khHHArhv7HiD8alJR9eI58lae94XOlD1\nziZbUFBR2JAxw/O2A8IWkVM9AL0ocvAKMQoaYt1QTbaM0aDe3cj89O6pjIaK\nu5lu\r\n=Nzmz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF1h62N93lSC35W9MiqZfedvakkF0hs+L3CpcjF2HTQWAiEAtPT9OecH17MQt9MiV0DOp1V2nOcwcjPqNiuucrjshPM="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.6.0-alpha.2_1588800576423_0.6173304149323979"},"_hasShrinkwrap":false},"0.6.0-alpha.3":{"name":"@nandorojo/swr-firestore","version":"0.6.0-alpha.3","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0"},"readmeFilename":"readme.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared global state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`)\n\n  // ...render here\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.6.0-alpha.3","dist":{"shasum":"bf86fa4d40cf59e1895923c2e4dbb3e28888fdc9","integrity":"sha512-JSZMxHZtcaatMTXlBcviRdKdrNuW3CbsvDrGUk0ro9Sz9B+OG4JVIp2bldHmebN0oyRfGcD//GgfD90T9QtwCA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.6.0-alpha.3.tgz","fileCount":105,"unpackedSize":178364,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeszUtCRA9TVsSAnZWagAAq5UP/2uY8Rmf9/ni9FiDR2Fd\nasADoKc1RbWyL4q5pPQATLnaPFn9NZBC+kkt+5N83OyQOve6UBy0J9qjohFr\ngYl+cS6fJmnH2qB+uTSuu9V1bRlp4oTfugDZO/qQnhNHkN3CnuF104LA+4Xr\nIZQ33M6YhqKh5Akfsx6FCdugjkXwCVXo8Wp+BP9BIncjhe2+qwBfkzq/F7gQ\nn8NO99MXt8IdmHf/5v8HTmLNl0vJpb+lqN4VSPoaf3rqZGQk0vT1U+oxKK41\n+TY5jELnS+sQQC4S597qoC6ZWLKJM4Yzd6UtjRJ3DLe7QLi6YmQ9iAljPDs5\nOsmcly/rPQ74YMUtHgWox+WKtxYRNsouZj8QYalVGNp9v+cMazfX0xs4iREi\ntOlR9zOp0hO9eU9L+cRblxhzkg3kTv7DlvLLCQqjNgtmxVVDNNibpz1x7y7V\njkPOOGZaSY1dMofkTtrdvpXwoshjgFH6ByKiEVKJx1qiccUNHkw53wSa344H\nHlnDuCyMttBm0SLLLUUvGTWHwwetjvJ8OxiWcFAIv9Ako+VPUsMIi5Kb4bpj\n1aSCqpOHy6q81E7aAtFN+JQKc+3nGQH2iBX18K5o59Rzw7oXMOv0koHXy1cK\nlSVhg6k7WEZz+/IwVnfYDUTM/deVB7SPzmy9KRxy/U4eaUQpoOpcyvdQaCFX\nx4qI\r\n=avG0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFdxe8csiDojLuk4MAxrPsFyxjzM4aBB8q8XFp2VFU1HAiBHyOa0KNwJYDfvqEc0zdnm51kyx9oBI0AS3cQijcRT2A=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.6.0-alpha.3_1588802861145_0.6993844573956511"},"_hasShrinkwrap":false},"0.6.1":{"name":"@nandorojo/swr-firestore","version":"0.6.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.6.1","dist":{"shasum":"2865498d836d8f0188ad25cf34be818eb195a62f","integrity":"sha512-aOD+jNJzoUCkACKTvLhHK9R696prRMLH0aYVNDb2EejdfX9kmjlIw5HFS7UmiWYElNdKGQJSiFRpbDwTJgqJiA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.6.1.tgz","fileCount":105,"unpackedSize":178356,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetE9RCRA9TVsSAnZWagAABmoP/1cTIYa9ByDJe86E0yYw\nlxgFZ2+iyArGfHvGOhQ2dZ8YDytLNxxqK0Hz6O63Gj2/1v/zi+G1zMtYkP2o\nezB+/V8Ve9VMKzdzht/iV0wPcnNDb5ve1c0v9WTls43WdGvr1zqMouJnLF+B\nfX4nrreQbjCz72nHlOC/NLKqlS5CVIPEkTixMh+/880nmGrz/a07HJ2uACOK\nO19JWfn3pFtJ6YqDt3SQ+gMU5gMQ2YApaRBt1hyPixo6C8fh0GAOpFJG69HU\npv6oY4qwSDuQ8AgqIbX/oBCQJMUVwy5GujVTKaGFGv8mhUXw39x3wWdHkpPH\nhzYB817wQOI+kWOE9nhFroTo/62FaK4s4UYm7wR/tiVse2Np6v8fE+XDcz44\nqLoqaivGGAVtUeD8RnMIxiJIPDZIxTGD6FVo3TkGxN6VGe7NZRgR9Twd6/9X\nZCjVNReua5mkQt5+fBQjXDm/Xr7m/sI3mT9GplcxNcXgNAcczggybAWYUgy4\nTqXnsJJTB/c+KT5XcYp+iERoN/bxRm4iSe0LBrpaNaMBbB+BKuVyPglbKdaC\nYIgLPHCYHML+g7zmtN/8gqWNGiKuE0vc7rXM4nDd4LuGtCQumCkf7DrsUcpC\nDPnSshhu45uQIamWAfv+q1SQ0oqAzSzwmSzTXuXt19nludm4NMW/8aerJFCI\nRMXm\r\n=Lqmi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH5vfXTjtg1CpmLQ00+qeowRyPFKy0VbYu/iZ7IJJp7sAiAcjshGt/McyH57Eo3bnvYeRjX0j1sFaQW8M0QVSaZZgA=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.6.1_1588875088632_0.36921886469625464"},"_hasShrinkwrap":false},"0.6.2":{"name":"@nandorojo/swr-firestore","version":"0.6.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.6.2","dist":{"shasum":"220063ab6949de159027c6ded808d11430e2ae9e","integrity":"sha512-K4wn52QlkQqJB4d0cpaZmh4Erl9bWQw8p2tTKz7Y4KE6TMO5wXKJbkBrZF4PFHjGQI0YuowpzEv2Twgn7KIIyA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.6.2.tgz","fileCount":105,"unpackedSize":179423,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetFiCCRA9TVsSAnZWagAAlJUP/jXRG1hgekXz0CUK7q03\n6QIFMsOlgxp7nxfWPgz/vN8V5mqQJbzQr6dBGwH5GLrrc5Ea8f30VoqpgMPY\nVV+m7r+o5q1sA0P1WZtUZeIHTDvjoA+sdReYF+YhkbBlt1BI12YTlv7UvIk/\nojejN4C6EuMxNyuUZ0Mw2DtBFBvV8Gjml5SDbS8fLjT/txd28keHHzdFM2bz\n+R9Sg6kBWj7lRT9G2tUjXTlBEYv59dQJibpahTKUjteR5s0saNd96waYWSSj\n+cRJGq0aEl++PWLT7P4i5Sv63Uc5WxFup+g1nSyfz5Acrkr68csvdFM9A5Ti\nR8IXrjSzPaqx6KNmzkaQICfXJUPI2JqWc1nm82TgQ4/7YxbAEVTOaDb2e8ip\nxdEVzsxxoE1wuu86ZPecii+8JzqCIOPjJO1azANv/2AeGbUWtY1NhPcg0JBW\nLzLs2Od4EgfuxrRaWSntkslYMeJVRsUhdFYLOdUO3nprVQbtBDb1ByAulri1\nzV+Aa+FCUzzDPY8dxQXo9Azt8XlQdod21VA8skLsNLpKFWcBOhhOWNGfOO8Q\n4zxWnwbzwWsZsWW7jeEe5k6/rLNn9oMAGEL2uWnXI7T05eST6BzcOm0no7tC\n5qBhZhzT4fD/+8TAR80ivKJReYdJ/SdMOGQEtQvl8+/CHvqWrTo6XNAAJbvL\nBn6Y\r\n=qcXW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHPmHrtRlUjtIN7OoXVpujPn6gd5Qi/Eey7cfCTEbMInAiEA+cPS60jYebr0Ixp0huB6qcItEu75ZI1ulVF29vEUopU="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.6.2_1588877441742_0.6595223979520168"},"_hasShrinkwrap":false},"0.7.0-alpha.1":{"name":"@nandorojo/swr-firestore","version":"0.7.0-alpha.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.0-alpha.1","dist":{"shasum":"8b754d855bd255e7b45ff0b133187a5baa85d24d","integrity":"sha512-J2RoIJXabYiFzq6NhrCutEXGTzILo80HY1pWwQ98SOa9LMkauZPgKCryLWvQPWV1qoZfBm80aaPMCeXLZnLJHQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.0-alpha.1.tgz","fileCount":111,"unpackedSize":202635,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetLTICRA9TVsSAnZWagAAFmgP/0Y/uoXye/aSoPaj5gnu\n7QmEK0OmY3g0LF0J/kMArq9LRupef9FpDhLdVgAzFuZ/4KNmpQMSVLHw5ja2\nguKZTB1XBVJr9Pyl46E9MOjKbpuH1r2SSJ0CHJqaBTWt5Ux3TO75bV3a2LOj\n4CEvrSl50N6vR+SmjWU6ZfSLt/KtbCz+27rnoSDMnwxbGBe+eyk/vfgaPAyb\nzvgasWw88eP71PQtr66EDmHbzxZUrhPzLkU1JOfoDh7UQMQN5ir3MRF1CTqP\nyRVymxP1Y6jqns/rvmWtwTvGdZSP86QWjEczYhFNNPgiFTL8HgpXP7G5tbTY\nWopp7FrDxTkHlY+ZLedbYdxYQ3hB2c/nqDXsOd98M/S1HQh1JSHAyI2sV3Ls\nUFMeZAc/jV4T6nNxUNsw+AMObxqAifD3ndCl8g03hEoY3+AV9exq0MfX/2h6\n9jkjK9A/2GgidXBKeg1zxv5r6YycmE+75eqf3d0JGmnVKfpkQDstWHf2ptfl\nXQVy+DHq7g7PkXlJSjOXUFlkkd/W+99SqKqsx0Qf86pu4P+bV84Y9s79AQ64\nXRSn10jtTsuqyAghvXcNMuqxP4wffKlzt7Q9ciWB6jYUseHeteQzVcqdJ/01\nR3StfGBasY4f5Rsp1/QI6xeW5gcywdIYt1jpFq1sY6nNCmofvSGER90gnAh5\n2ibb\r\n=clY6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD3sbweraThiROf71XiStBPk+f4Ely0sxI8Alj6QSueMAIhAIsEx4HwEibw4TQhTyM26Bu0Zt+qybmZnzW7AA5P0Vy0"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.0-alpha.1_1588901063665_0.7225965188647296"},"_hasShrinkwrap":false},"0.7.0-alpha.2":{"name":"@nandorojo/swr-firestore","version":"0.7.0-alpha.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.0-alpha.2","dist":{"shasum":"1e675e3e77ab190ab7e8e8ad93d13161de9980f5","integrity":"sha512-TKwkAiY6WlH86L1CSWf9S+hzgOkVvqaXVndojK7NPRF/lPmA4Y8/qxDvQS3L4/6Om4g5+qLoav8uyvQTeu8eCg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.0-alpha.2.tgz","fileCount":111,"unpackedSize":204311,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetLgtCRA9TVsSAnZWagAAiioP/RkI8KmdUsBB2CqjX2hi\nfLyAtU0rmGFuO/+Uy3QaORV/6p5H+sNLwT7EpcbvV3czKEGu2+y8HIn/D7Fi\n/4E/GUoSsiZ4f/L4/vOHi4h1+4AAoCZZC7b6dHk5NRjF4w5Td6KPQryN65Kz\nXgIJaomaG1SODRCY8u7i85ek/ePLMPM/+NU9sW3I/6I0at8OQQfBtv53T2p1\n7p34qOR7Sg+/Iy3pnnRzkdXMlUP7eNLSPlxjci3W10g9pNF3Nq+aZ+cA/CoE\nkd4Di0/dGMx1KjCVlNTOo9qujZcC5KxclCFTtUt5X7aPBsLtJIkTtflIy0zr\nUwVbQpWSudoHVh1/ePePVLY2ZzX++EasZoznjaqyv5NoRj0zBVzImar1lZp+\nl2KIQ2JIlYSqVxRI0tt5ibyo13truIfGsrkD/VQEOfXdzXyFTyc6gEpLA9uc\n+AJ87AUisRbUuD6uFLUq/TVVYG03Zfidf8jaLYvso+e3Wqrc+i4tIdKG1MlI\nyyjJWv6E4eJgWgd6P/xaIfBcfyUqv/yqjzy/KuezinImL4PAffODRUAsNSU9\nGHrz+n5GfwzDF2PKuRgHEvT6cz9O0rSz5Sl53dSUckxYKG4BieT70+/kv/kq\nTi4duu0jMe/8NaqnGIb3ra3/B+80CVyhr2kQawyVxH35qSoGWzYYRv8MGWtw\nUbVA\r\n=HYKo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC90xWYpZTqdxBN+qyXURT6tTtX4K+yuElDRf3hHPEcGAIhANjRYpR4O4/YQkW2Qzg4sVKr63xhsUYzIaxxBs5U5Bnn"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.0-alpha.2_1588901933153_0.7179561175332307"},"_hasShrinkwrap":false},"0.7.0-alpha.3":{"name":"@nandorojo/swr-firestore","version":"0.7.0-alpha.3","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.0-alpha.3","dist":{"shasum":"0961fe6e23a25534736890b6438a147c710af705","integrity":"sha512-Tu6jEWUbOAHpCTl30qhlpKQLs4CPkRNalas0AtsjNoAT88PrNUceQ91Gnc5KlB0IbYsH2QoXcouU76F3eRLWzQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.0-alpha.3.tgz","fileCount":111,"unpackedSize":204311,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetLnwCRA9TVsSAnZWagAAqzsP/0qZM6o0mXWRuRw6JOro\nzCrY8M3TtC8d4tciGdyGzB927azvNczqTuKwRGQbN0EfnhmYw7t8k0DKlZxO\nAeuKU48gDYukNV10xGdHGsUmFhMmJ03433xTE6Lu+ZJ6Ok+GUhlsK/2JhJPO\nO51vM1QNUurQf09lsXZokNP+7fXK5tJ9e6/m81oEJ9FdQ9COJPnp6EhSA1+/\n65TXagU9+zc8/668H7A9zlrQZO5WUhMmDmmwJi2eKM+ZwBXc0XoVt5rFnGur\n11ofxTlVRras3Z1lZYxrXwyNCQT6xrD5fQ95b446V6KXe8IhjU7wRSMMtlp0\nQCEht4kndVRh5KUv2cDhPp2vYhZP7g6K6+NkR99TqbHfbsJQvbTgkJzcC2ns\ng1ePNRycNqDqMThE32Pli/0RWDlAtRkWxfVZciKyFYtp6PP8BhS5iycCZE2f\nksaA8fyjbhQnvE/6k3jDAsMLioH0PT7thUzuW1481VPoLeahDA7wxEZa5old\nhqs4/cqHVcwvHwtxlC4WJcyQf2tOCiNJJf9wj8lL1ACQ3XPP4QwYdHhfTseB\neBynWbO04F9ZZ1+b86SXAc3ENKO9h2pXIMvafOUMzwqigYAI+6dRhRzeJ9P5\nvqYTJaENcbkJGGs5V/G2WZA4iCcf9BrTv6Dn5LYmbAW27teLeLy2WXwo22Br\na0t4\r\n=ypx7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGkkBKgxlIBX+AJxwkwAqXMLK7KZANvCLcXvHKdEsuqtAiEAnMWnL7BjMOx3qNOMUfZOVkomVAinSlMhdd2MBIYBFJo="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.0-alpha.3_1588902384343_0.929061639037972"},"_hasShrinkwrap":false},"0.7.0-alpha.4":{"name":"@nandorojo/swr-firestore","version":"0.7.0-alpha.4","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.0-alpha.4","dist":{"shasum":"776cc86d43499aebb00f782fc43646f39838f5f9","integrity":"sha512-2kx3JsaRfJB674Ng+qLGDWB6mvJ9XKMDr1yxQAVXJ9OqTImFJzE0mcvV7Jo37QJ8098VQNIIpkN9idwWLHmZgg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.0-alpha.4.tgz","fileCount":111,"unpackedSize":208981,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJevaoqCRA9TVsSAnZWagAAtNUP/jriF+FmiFtd9AT8e0Q6\nY2NRJWxyxxJxtAjDRqOD+G0nuaNaTPiJghXgZK9NCdraVh1QOiReIt6GmlEd\nMyM6yACn0Qa3LXfWsxXh53Ax2n77DOYRrmqKGORDO1C7Ti8Q2jWGRIDPN5Vz\nVfCzhK5b2TwY1b/hM3NWpffrYfq6E+M8qK5fohmIFs7k/QQf19I0xaYCAXBw\nC8iaC+QR70hLdFpOOU7TB5PO1gVn8enRDwQR7VXfdrlEjN4CnGqJxG4hISEq\nZXmKhkdj7vKN1R/g8UaRZB1jsQ6yiOlH0J4yeDXfq76TQdIDkJzFJA3CfQeQ\nRurvutFvU38v7w1EqqRVnhZCu5C0RA7XBVuH+CbOP3B58++ZJH18Vs0u+I4r\nA0rKrRx2LeBjdynKcvNP5Nd3Z34FG8PdxeQ+Qa2uaHEDrxBG9n+LyueA4NcA\nmaeYgsCgYJCzIxlrMw1yr7e39NInMK3cHpxixy4ukhkACcFcoOwRXJYhyKs2\nLEd7ZZNCaMDVq2+Fe2j8rQm/w5J9louRzzsNz2iuP5UTv+m/W5IeoNsHnr6q\n5wzZZmj+aeXDyKOtGkQuSXQ9Me0FRs51NmJ+9KOmDUMo2h1XwR+mc9P3rJ3Y\nKumMyiUSFe273ABbaVfBErMfHt8Bgj/HXnse2npFFWdq8xqFIQyPDAJMylVi\nPpWR\r\n=0HME\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJdKbTcbJnE10YGKTd/b81Z3WckqXheB98N+fazoouewIhAM6ZUKyX0LLQb3+qdSJOIlpkpvVQ0ygshHf9xOXglj0C"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.0-alpha.4_1589488170028_0.5962635453133127"},"_hasShrinkwrap":false},"0.7.0-alpha.5":{"name":"@nandorojo/swr-firestore","version":"0.7.0-alpha.5","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.0-alpha.5","dist":{"shasum":"f347c6ae3aaf0479423980adfb1654127db4b882","integrity":"sha512-w5zJmFl+BdlvNjRIYifip1lWcjH6gUAxzPkzI+ITEyISoASA44VwZyenMK4L9Iy343Ep+NEnrwQ+LthvtN2ouQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.0-alpha.5.tgz","fileCount":111,"unpackedSize":209013,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJewL9pCRA9TVsSAnZWagAAI4YP/jMBM/3RD2g6jeN2HJAE\no81fnYZfuZUfTdBClk7PAJDFDk6VdNJaemGVqwT1e/UpTfQF9svHxAAtcTcZ\nRgoGPG27mxoMIxwdMTLvU55aIaqddaX4tWQnsu7xmCtHo2mdbCSC4lXbNgKO\njCcxMN2eQiXKdtyUc+em8Vj6l/HLIadIcAcYJ5W6gaCiFlAXrO4v7er1XRTa\nMrnRWfBCp3IfPVqwZWoCTbpOlytFUV5BtZCKq/U1j0ko2TbNcXbsfzLQZwrV\nhXSFtRLR4sY0oKtmJVoRLDjbBPxwWXyHBU8cZa2auWiPpjf2MHw+ULZNhVZY\naH1ZTaOI80bwchVS5AzYgpbFtxsPDYUt5XgIteaje4E6NMTb1CLR4B+RtMCI\nT5g6QQC2xzv3BCxvwbkvOci8M0kggnHwcBvGScuhFQ+ckAeQ+p+o1bQJ50L9\n4JsdepZi0+xmPMM3tIGAa0sm4Lb/5dExck2Uo0WTTxvVZHOS+KFbBHgOR7IH\nG8mFmPcSiUheHKnhcOLblSAm81Iwl/QoeWp8ndw+qL9M1lKCrkU0gWEzpzMT\nH2tZLxKLMOK5hs3aUtrmvogIbMgK8bDOdWF6o2WK+LZS1o2pxKKJOMLpTQHU\nAKBzUlowjmFbFTl2/7zoO4kG6TRWz6iHEKLtHh1jJ+6UNnkzsJMAmTSMhbF1\nRwnq\r\n=R+jS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQClqTdRP+rXbVyta5g0GHMHzHRViMqPEowzT/Hs8SXjMgIgBPR6rNMR2yUVTAqjtjCsARBkRWfxncHfZ63IbQcEOAk="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.0-alpha.5_1589690216648_0.7432214430451713"},"_hasShrinkwrap":false},"0.7.0-alpha.6":{"name":"@nandorojo/swr-firestore","version":"0.7.0-alpha.6","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.0-alpha.6","dist":{"shasum":"62e48cb08beb7651e61bdd19b2fd087954cf716e","integrity":"sha512-Q/wM4TlycjEcdfNtWS9eqCeGh1r1FZBESaXYSNILXcPpSu5sfb0B7Z/7UQRahS88hElkw2AApvyYNadTpd9Qvg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.0-alpha.6.tgz","fileCount":111,"unpackedSize":209037,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJewVTRCRA9TVsSAnZWagAAlkkP/0N0btrcfz4vRR+nycK1\n6UEh/AqIXQ2TDrci32mYUguSmOnqPT3HNvfVwHTiUw/AAlJU7jk1h35f9NC4\nyYs7g5yD5w8B6w8D0kyzxg/EyRoyttFXMCpQXttllBac5xse1dq+pIcgQFvp\nrpNGbF/g8bp0JSUTFUSHTaL0fQmKH2NzrPfOpFxSFmfRSm47RvuhmqVN/qTZ\ni39XburKPqADVMpJmhiz1Id+e6ejJDdUqfArWwR4xjUYf0MqD9b1HCqvDKdA\nYtOFgpZSL2qqsqJLPunsXipl89SsPEeEoue5cC4Ip8LsfKoJHHbJajmWWzYH\ncY3SsRO3QB4FJw9Mjl7+8JCd7NZ561UXnjKMpFonVwHuES9s5q2zQhby/CIN\n5NaXXBkosgkosOSHjNo/pdzG9BcSkix/5T3EIYaSDyw5fyWDKzvFWr6WXxuc\nFwo3qt/xla7lHjKTPMttTa4yFZHFI/DypgX5PG4lKbcHzjGx+96W/Pg6p2AR\nKjXyEPu0p9mm0EG7DsQpYCFhiAEWGGYX7jstZDemQy6KbyDmwYlYfLnZ6811\nADsC2UiCAGkATGIqxY3cp7Z7zTXiswUNxbHPhqxF2/XQlOrsLHpISpvcw+c4\nlrJYjmNt3HN698ZPtQ7MU1oazUi/WYh5GisEkDDSi57IL8Sa6esy4lZVnRM3\nc99/\r\n=rNX1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCOj6Hz75PBUAKG9nCxNGi+j0wYckO7jh1ebpyyLeyghAIgbpWJYqkA/fpE+xlorLpVBxHqXJ3xCDxDoLHa3/YnXUk="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.0-alpha.6_1589728465140_0.23187129395681771"},"_hasShrinkwrap":false},"0.7.0":{"name":"@nandorojo/swr-firestore","version":"0.7.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.0","dist":{"shasum":"c73a58216e988cf2a461d56a45646a83f1f01c81","integrity":"sha512-XTszF4SXmY1Kee+bJ+emVxsTOm7nDeUKObVpAXtjKGL+C1+DfwHD8nQjZoSHd695yYU7i+6uBdeOQ5P51igwKA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.0.tgz","fileCount":111,"unpackedSize":209029,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJewwehCRA9TVsSAnZWagAARXEP+wc8WoIXi5qYchTC8RuZ\nyUgpQGWunx31I7Nr660txhdtP9iMbcETJ243yZrujR9/Rp7oFRF7b9tRxApd\n+lUo50YYnj7YazWE3Gt/ed1FNHKhGLcFFQ2+HBX4yyQLL2B5UxHTCX039SpW\nP9xwGeNLTVm0YA/lsKknmoixkLs/FmPsOcTA2UpwldWFt2fb8miNHFQMzXaO\n8ozXzAbOFNcUZTxRseaaDcCewBS62AS+RUHEZIW1NJylhE4ULyAMpqu3LfpU\nsIOzifNjOGvYad+iJ9TFl6Pobox2Z0T//wNN478LmDVKHpUiRKiJMb/SdZ7N\nOxbxbnTnVDg0msuPgCw6BPYZq5Aixcs/+SEH1ArQuciuVREJq+YJzFJXqJ74\nKF8dtyVbBVmMxQ+HV/9xL+juvXNaBGwtEtpOEwaauSSEAAIZ/RkcaKXcrQiv\n6hCJ9szmX/OhDApVuM5g4znCmWgHtIrGDdb0NlxPoB18uXVuCL4xA+lUWZPF\n9/kdBmlLjdLQAL2LCkoIntVupKMGp+qafBCJjZ2DcTWXnbKwwSeZOmDtzXOb\nFzUp1EAIqxDX6lYuZj09KxT+R9Jdi8JB0yzX63As1UBapyhtNKr2sDFuSwgp\nqe0F4exZ1QajXTrSN0OXwEALygeBjyd6HbMyVTAo0WyJQdIIuKpQ2NRhhGNN\no6KA\r\n=fBDS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCOdgEploIeN9pApvKxA0lymTlbIwdQDXmB3D6zoVJVMAIgNwGnaOXX15xnJSuUAg1ocCsjeO+L3bILbCSLnZx699c="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.0_1589839776686_0.8824782207797957"},"_hasShrinkwrap":false},"0.7.1":{"name":"@nandorojo/swr-firestore","version":"0.7.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.1","dist":{"shasum":"596473c351fb515aede74f7f95d5a05cd71bb357","integrity":"sha512-o9Cx42VQ8daL2b+RbDQAbg4C/Rl6qIpPx59+n6+Baqa9c+P/SKXWSe9kPNg7Q6mb55kJWHDxZLTM518W7pSi5g==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.1.tgz","fileCount":111,"unpackedSize":208980,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJewwgYCRA9TVsSAnZWagAAlHcP/inVJCTBH9Qw2uV4VKVz\nVHVjstRqWM+tIiUBJ6Tktz7qncfS46D/aCdasLnuXHzE3t1paRa7u/VUhoet\n6I9ZtrrLx4K/Jq3gEnxdr60ZC3VYDmjPgdyrZVawO1lNU/SZJxrYe/8qut2W\nh/88jOVz+2bK6LO+FZZTGq59PwKaFqJ0jyRLwMCigBabVb22wjruOxa+56yf\nJFd7U0yqD+d9Xgl3S0uK7zVihv0ZGNWx0u62lo4y/zeAXTx3V8B8xNXjN63I\ng0Pc4A9rcVs0UaM8pK58dt2gQMvY/JLl8smB3lCsWomiBr/CK79W7jW639yZ\nNbWMecVAIrajCeOkKdMk1jJMd+95kzoQWzx0RxliOdAqqCWPk0sblZ4Z9F24\ntyBHxaPM8mciAp5V2idIp7d72QgdX/rwmJF0K55exfVsGB8wG2EmuEcCW0+Y\nccORz7O6kIm2dzmrFo1sYOfZbxp+ZwJ/pzcha1DGnahdspu6kgrX3NR40lUL\nQQ9mbDCYiAHWmBcuqClu/T53JNreZOnR3tNGuqtQKec21MVnBgUVBa4SZymm\nc6ZvALh+OiFj5Bhz/3zzz9pUOi5oJ4cHWcHvKfC4Xl2zqYv4sRTC2FSdM8Pa\nLWH5tLN1WO3LzNmZjyTP8/uRYdRfSoxcY0sTpBVkgcuo5+OAgCbga4+ePtx7\nXffF\r\n=0wrT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD0oyN+yKIaGFcD8YWx04YvgEqjLhtOkiCzwsTUyutKKQIhAKMvJj+wgkmZtuaoFWVgVemJRb9T30rVu1D2GLtpu+/u"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.1_1589839896070_0.9103650442119953"},"_hasShrinkwrap":false},"0.7.2":{"name":"@nandorojo/swr-firestore","version":"0.7.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.2","dist":{"shasum":"3804651492fc944d176bfbe95b9a8f77e563e9d7","integrity":"sha512-8QgxiU3NAkQPeGxOP9zcrDW1jieKXjJ6uNIXtyFAV+T223ym7bRZ9o9YkynUiNZA8d5jAD4lhLWUmMrbh/H2HQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.2.tgz","fileCount":117,"unpackedSize":210395,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJewwtSCRA9TVsSAnZWagAAME8P/jxc/sgQzyeYzWtu8g0q\ngHl0xNT9wZgiqA3DQo4+CCrA6uV9evI9h3Y93sBNfZ4BfQAWVhip5chACSxq\nACPdIPEnkv+L0kVEi9Elfdje/VCTRRMH5uJj40fFz3spyKc9/0E68w7fh6GO\n6IQ4m3vjeZgLeDdMeSsDBPu9X5RhHZCB/ja56jHEaxWNba78oYwhYi8j2Bd2\n/+2XUV7U8RvMzuPzvPaNTlgdAFOqhMiQHieg58fr7YkkAMd16cEzBuCICbg2\nyFBOhADqM5l/l61cmV5LnjTpbP9pFeGR9YjkFLTkzH/5s/2iU4yvlft7PrBM\n4yu+7RRbi6XZebIBOHqSeNmsobAQm9T+xr7uscaVjXsLBRwnh7tchkzP4R8O\nY4dDbvWa6tKqMCqiyXONbRENNPGcbJv5E6Q2ITSy7GHMM1r3BmpGU6TzhHMv\naj1xHR0mKnjcXbaJQnNOKRZveBvXzZWo2lveDO8WrL6QwVaSbovp5G9/V/cc\nGhDdSZY6zGXPl/N+/FB2+CMdofg2+kASlqZVtk63WZZVl4Pd8HKmEF9ZqY51\nG35AP8fhBcduC7wC2sf6XVa7Tdr+5fry6YpH8NUvAYG+lZrtl6cKwKayHjL0\ndAkavPKAKqEw+so+efGhBWQKy1HPXKNhm0EDSWiNUpyONEjThJzNU8M8/9nD\nULn2\r\n=Rh/A\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDh211UfDQPd6Q2PCw49JmPuSaeTZcv2M26ApmmWt1DiAIgALxAZSvCfmUNJ2ahyrB6ttQg4hnG+rO2BD3qki7zinA="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.2_1589840721491_0.9932921918876376"},"_hasShrinkwrap":false},"0.7.3":{"name":"@nandorojo/swr-firestore","version":"0.7.3","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.3","dist":{"shasum":"60a5c33e8453b2b77356f4270c9a3c68ab5ff7b7","integrity":"sha512-Hbq250A0W3q6X0yZN4SIri+LZTzA0+f+s2YDzXGv7XB/FekcYvo8x/pGUyNqg4NEhTCHntlQhgCXQXsGRJg8Hw==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.3.tgz","fileCount":117,"unpackedSize":210385,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJewwx6CRA9TVsSAnZWagAA76AQAJ6HqdH6d9XBgMQeRnGS\nDXBMfRx/rta42hL00pNH0slXw5HAg2fcNB277L7S7dkzEDxScxMauVuxd2Dd\nTchv+APqJnte2R1QFOibdj1p1eToBzQbejlrueeGtjH6UNK8GEgwhm2bDSoW\nMAWcFYJd7gsehcUQRTWHND7S5besqEEPRbf3LSg2tC4zVYCkNnI9wvVJ4nxO\n289C8yTpugeqRh9AbOlka6VWiyANv7tdzMOHqxc+bxkZ1fP6yZIRQCFupqnM\nEPnWvVSIRuEIvC5e2vPV3MzWeVsAZibgedCfVb1dlqzvqAJDFUaV8kJK5BP3\nxv1yoDFyHJ2cNFBrZHh/LK3e/FNa9K8BbwVcs+rWXIaJsxJyK1891SpbveLm\nprAIdwNMXWTIFG81UlD0fFMaXCR59hp9V2g7QjkFtOxaolKOueip5kzMW73I\ns4ryZ8fxDMcsvZMpSUp+JFvv4Hr0lagJTnii7nn6jhtXbxARDswbmUT7vb5a\nxRr6gZ0UN+X/baIBgnVw9iJBXQ+vVmq8OU/g8YWHYX9gxG+fSuRj6uq4pFHh\nOTUXDALonwJENrXBnX3qH1xjH66NZkQrnlkMzVBCOvn7m6Lg37BYfuOQz9hX\nzcORU1qmvraN2R6Uc8F43h37OK0wkTtEQ8aJUYoBtvE3RuPN+n/hM2+TGe3s\neMdV\r\n=ucag\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDxi+72GZk/CxYoNluKg9B4/HPbEUPnNTq+lnjkFjHpKgIhAJRtuK//9NeED/6rMm0P1nl99018+9FkZiUctJaONPRu"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.3_1589841018009_0.39643673002124347"},"_hasShrinkwrap":false},"0.7.4-alpha.1":{"name":"@nandorojo/swr-firestore","version":"0.7.4-alpha.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.4-alpha.1","dist":{"shasum":"3080b5702ab9bddb008200b8f225cb6d525bba64","integrity":"sha512-67U5dUJJxpmkOhSK80k2D4EQefGcTi2H2AIzkKe+oDQ4CyYI1IxbIl00QmXUGaxlplOjUh2i2IyTFMs17PSS9w==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.4-alpha.1.tgz","fileCount":117,"unpackedSize":212484,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJexEInCRA9TVsSAnZWagAAdSwQAI8QGt6vKoDnlMSuvqqn\n+B89c1SHVi+tS5x9hgJIaz/1l6fH3gyWV7q/EE8K8iHRzMis0VFPx44biPXV\nvpcw76EkS4Fu5sKkhv4PlaDWKVoaNcaYOSwb6+Z08Dt2UKySzv92ROQtEyQa\nkKj7zqOrCI19INl+aBIKoP47Poe+xxGGJQvGvobtx44DYzuC5BBrrDrri2ho\nhM1fnB/G+SYGf65JhBZHap3/ggKoyTCNLIN3Jano4UKMiat5WdAmc4bomtKu\nBUAJKPq2Kez6vXpyyV5MKUpOtQ1nDKCVKnDH5Y6MBOdD0+6idgPW+lspI3Eq\n9FgYcQqxXz0lXJ4lo/v8mVCqGT/FCg2DyX+2j5CAJ+aA5skw6O4bydM1tw+B\nLbY1lTrAU0Kf23JMzwonwQDp/PRis1dLi4lHJ+A5Q3qfcfOM86Y5BL22skt+\nApc2yy3C9JgEQ4H/QT9awjkRtJz/hEXGNgt0DdRWaaAUzy1+rU4v26qcDLXP\nesmbHVcoZMg79Gg/2SOCJdpcja/fP96WjWYgDNQdHb0azjuoHqJrr8rkx+cw\nURNWAmfd98iQq0EU7HVd+T/Qzc/5aXYrjsJ4ZAsGLNkWT+hPKrugUs4Yxv+j\nM0GZu+pLnbjURAfp3SqAZBIWzSltEuKJtGyYLPV8FVFieYt86dS1+dZZ0SN6\nDDDB\r\n=Y6No\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDEx8aH+63SEcDFv5tQ19fxfGyakiGGEIbK+RjSwEcghAIgb4c8Bgcn9qybHVgBwZK1dUhuNYCh55o31v+8V1WNEqo="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.4-alpha.1_1589920294499_0.7993052443854631"},"_hasShrinkwrap":false},"0.7.4-alpha.2":{"name":"@nandorojo/swr-firestore","version":"0.7.4-alpha.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.4-alpha.2","dist":{"shasum":"cd97f8018ad04388368c01a466f622e6f97db8f4","integrity":"sha512-oyToPch7RiIkcLBsX02cVy+9A4i/NZaDEaGNMqJiVshjkwFMa9POwq0WtwV0dKDRSInqmX2qKBQBV36GUoaDpw==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.4-alpha.2.tgz","fileCount":117,"unpackedSize":212376,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJexELRCRA9TVsSAnZWagAA25sP/2bUa1+WUyYPpW7N8vp8\n2sSh3fO5/FyR2UbS3dnF5IyskUny7fbxXcqrzwOvavK8akhSm4MdGPxjh1/P\nZBr1BPYLrGaqE83Gve8CeAo6ZzsRk7Ih2U9tpoXx/mp8yyV0H6FwFbhBAlPJ\nCJQQmnfc13scbQA+FsU9Cj7zQf9XVYAo5ficdIflGPYTzQYFbPrnNHts8lTr\n7bg7fiRtV+IRmbAcICNcOP62CL3ekKvQXzpNE+SSDXEG2xf3wvPsdGkhWaXg\nWTWcTtTl6SCq/I56WFLG6lGf2kMJx8QhtshTegtYEes5wEp3us8Y4kS+p4lN\nrxOOQRBzgOQOkTtQEaX14yjWanp3fhL1l0fBj5du1k58DNSNte2vU9GlIxsl\nWJw0Oiqg7rYQOQz5+aznTLVwR+e6ZMiF4XWml0kiDJyHgqFlH4XFEpSDshNj\n/GJXV/PM/yFwsFoDEdqqkI6R7KT8RPvHQ61e70cftj6Ndh4frtw4KwJJgtu/\ny0sjp/dOlpN/X2t7vVmvUPTGPZuCGbElR1mQ79Cw7IvtlvAFmoePeksavOmm\nDV3SJ1uVziUANYIoAv4+dwhe0aTNUiCL3hxfHeaZ79NDwGRg/yDhiZVu7dDb\nrLsphrt/97BPztaNIiCeMkEPxjpp69DqcgeZ9NQj2m94lHaSiAI9cW6iv95X\nAByw\r\n=1jFj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF4n07ee+KZ34jcz9S56LH0/mSUxAGCY5tuNphT70wHuAiAOPtKerFDPDrO7fTfECZpiwvr3c/rLBT0/4H21u9o6FQ=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.4-alpha.2_1589920465521_0.5108517451001333"},"_hasShrinkwrap":false},"0.7.4-alpha.3":{"name":"@nandorojo/swr-firestore","version":"0.7.4-alpha.3","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.4-alpha.3","dist":{"shasum":"df8680d49527bc12fe94742aa30ad6432ff79d65","integrity":"sha512-OqczGd65YQjQ3Hsh2nEb5YPCLw/Gla1Qp/hrJF7Uf4UGV5oPAIq17FxoUKGnHC/UOfXklhazKnvvXVwuNRtjcA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.4-alpha.3.tgz","fileCount":117,"unpackedSize":212392,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJexEL6CRA9TVsSAnZWagAApSIP/jpFdJX/eX8yXfUVMJXv\nvh5Ogi69zLlbV07mNqhiQAbhtQseoUw507Cfkwzc9+LjX7SsEKX9dlhU4D+v\nl4Z8lNBT0OkkAEgfXYu689nIs1LQ3vLXrMR35bX8TAVSpinR5jEsoFLR8CZY\nmU4YllzxDNAxmpktRvuy9u7H0iRAKFwC7wDus10nE57oKbF1YthJuiusfIFg\nxPTvoQ6pedPFyINlgOda8BrB5fNohS04x3nysJl08TSOw7fWBFkw5mv33Ali\ndFbA7uPQ8XjXXMXbnrtgWqNaBFKOKMuwIButc9dc5rptqHbLheQP7Ra1m6aS\nn+AUxO2s0BgZE4IzHvidxgcir0Brq10folJPLVTSItJDpOaExyuhAVqUA8QW\naKAh+7YDu8T3Iwode18LWl/k7JpGRis4DZInZ+u/0C8iQFhjVJBLhs9a9Z6L\nSC3EfwrINXJ6hFQprf6I2FqQk/9li62DeqxByG3tG0x5lTM0ZBdn2RMTrg2c\nw9Ti4gsmkBzrbmuNAVEc5OlZgraS5KChSkZGB++Oh0O9prQwQqkR4lw5+pMz\nzuSdsf6MOJjtqHzFmCfB5NjNQ40KkbDp5uYIYdfz922V2pdv3ELtV/4iwyW/\nlABUkygkegZhVGH4iL86jv6+KANBjhUW8bCBwzG1ZLjokZ5vUnFRw3uJcFKs\n4MZL\r\n=wMcc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCbJpGYtCCX1R9lJWXrAW7VBOgB5IY40PNv+k/3akxniwIhAIag5UOG7zKAFt/caS6sx4vlgEhGu1/rmWgvBd7nIWsE"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.4-alpha.3_1589920506420_0.6665719415112947"},"_hasShrinkwrap":false},"0.7.4-alpha.4":{"name":"@nandorojo/swr-firestore","version":"0.7.4-alpha.4","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.4-alpha.4","dist":{"shasum":"68b754bf799419f9dd20fd136ea12a5ad499cdea","integrity":"sha512-jPlre87IUFmSDdo+77d9GpZJwQEPWNocut8VqzVkzjOUnqSD34z1WOBkhz+o0BnWnQereX2gTiCVUrf0k2kj7A==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.4-alpha.4.tgz","fileCount":117,"unpackedSize":212396,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJexENACRA9TVsSAnZWagAASeYP/R96I+QGJTJLwejiX5Gy\nD73bNsg0ajxRy0WXFo2e6ehWcmDJryv7nQPFGtsWBcNAAD39Dirfo5pio5lM\nQ8csbxUrl3zLc2HiQ+UhrsFU8DkT6OOm4SX/2NZJ0EJKJdtlemNqzOA2cHM6\nz2VM1UIMdKxHkp40vLW3l9x/8TXLwedOcI02g3kfpTc+QJlzidUV62awdKRy\n8w7qmK90BReQRx6yd/2HoU3d74ux7wqkBL+iKAbaJ9IwCraRXPvK4PO/oFuJ\nKtRf2cUhTj8IEUt+dRM3G9+1Uq1at55sFbdj95H6a+oBcdTzHNoZld1OEpip\n6fLaTYwUFODPgWqirX72meSTJKVF8H51WK/0vbCun9MN5k6P5CIdek2v0Cfv\nuMSWzdNkGlSj1wCDSIDSobbICP6DvFbYXrlOP8QXV/q17TNAqiofEW+M+rbk\nt849LufxP3z/mRZrtEiOnNxdyTEXi+iRkF/ZgbNcd9MXe7XcXJ/tovbBUsJL\nMY5AVM7jin0mv6NcDE+tOC/0tZBMPDK9OtTkSXf5hiX3Rt8J9XbgOLXX1MCh\n37UhA0dUNAVxAznqC5HSWxHqvnRIS8GxIYI/qcTV7amglBPeR6EfskLccx22\n11htihjYUt6BfSZu9rYRFmfpYJtLaD354hk0fVbAjDACFUlURYGit6pdmSrH\nKExw\r\n=f9hy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDHiB07nsEB7V2te9ci1PKXPhRAggaahHsSeOBy9UH5+AIgC8yBfwYwsGAk47oIrWg0FXqT82bnbvpE6yby+Jhj9AA="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.4-alpha.4_1589920576414_0.45296671134137045"},"_hasShrinkwrap":false},"0.7.4":{"name":"@nandorojo/swr-firestore","version":"0.7.4","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.4","dist":{"shasum":"1718176dd779a7ec77b4e735360cf2c91843d128","integrity":"sha512-1AH3ORd82QddGtDXEuBNje1jqBu3xcSiRuIqyoYGjuTAPHcTgJre++i1wR/lRYinfYESxwiorpun1E8xF7k1lQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.4.tgz","fileCount":117,"unpackedSize":212388,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJexI/XCRA9TVsSAnZWagAArcoQAIIsdwKZVcR3j2VEi36o\nxjQErzTrmJAoOFVP+Ngx96vRkaj/RQKEqvENxEZ+AVXEsVoR+7VsyINd7biD\neNtNSc6zAoUcLB1md5Sb3OYvnrMA4c34BUDdTh52wtO6EqQntqUjHgSSSqwc\nZnoCJyJTeHfJ3ITiq07mf01vzEVZLIAO1C6YjAj29wNh9dWmp/k3+J2hV4/5\nZ9E1k7lQDtXh8EOtzAHiqQkx+ZKecTbZBvCD/Qc7JFSiaHr9Nyy7hjjIUI9z\nUjn9DSv7F2okDy8p8WdxLATof/Q9dcc8p+n7m5ex5vmcA9Y3JZnUEQO9d5A4\nW+PgbCoHfz4i37DuVe4n0P1OUmFveUvdarUYge1ss1jEYeXetA6R8Oq0NDcc\npahYK0Par9LbArDK7WhnatOEejk8Ypj72TGJyOEIBSmyslVcZFKqCJDVwvXE\n7/j5k/6f17Hd2i7zoLqZsoJhLfbj1pM2DZR+3l8oZNx0V22knWY6OUhuGu3i\nc6zq3ZyraSIcEHpg2ZMEAR8ps2m7VqEi3ClNDHDG6+oXGi/u0tLtYSEKHj6L\nw9lJV8xreqQn8W4QJy0W2QJzhCGLiEBrM3KdU5W2XtUjaOPQnIwDwhRXNB9i\nLcUfUqCnDVOkNP2gl01Ut+s31ifdkBp+1S8iRff4zaNxpdFCv/hr65AmOExL\n8vkk\r\n=sTEO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDTpYAh/L0bMz56QHGtCZ/k21xo41hMi+PrRLQbBqTmXQIgCibCPzNq3gRHhXTKMRcffT7k2VA4KEqPT8tEab4fBoo="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.4_1589940182217_0.19332686742313698"},"_hasShrinkwrap":false},"0.7.5":{"name":"@nandorojo/swr-firestore","version":"0.7.5","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.5","dist":{"shasum":"fbcbaf727cd18c7bd75a5fe8e3b014cb7e4d2854","integrity":"sha512-ivNdACfgNdlgktAxWNzZua87hSaxnLhqmYk9EaHfjNSs4a+QRLhvDlWFG+BFh6IY3PB52ljq/YgLmKQLP3xa1g==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.5.tgz","fileCount":117,"unpackedSize":212575,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1tByCRA9TVsSAnZWagAAqtcP/jNU6HLhXdsm7wTeH4or\nIEy1XXN6dKFK/scoTCQICqpAwL8VcfWxqHf2+07qdCyhG+kl1SOiKtw3BnZl\nGpcmfeAt5qFFXM4nsDvxdLuwO4O4UnTbWtY19Phrz3IjRVMlX8YAzfqOteNd\nChAQQtN5UCEg28VxmWk6Cu2Q3MvfQmyuhJmKjpJXilKXZTfdNWx0HmohoWc2\nFVwgDSh7+C1xqg62HIiv+PBh7sZa11LrilbGWhEYriNrZLNpfyFIWd0W/3zW\n36OaOIWx6rrNHdUzq3eegTeDx0eTGlzLsU7zG9YXm+RYjTv7zsNiGveyC6fj\nXeFTRnHjGlXnWoLcPS5ffOfGbYRqaqjUMZMOrhVXuhtuJThNUZIjP5+DK2OL\nEkVzmvdE8aSCKhxfouH1MfyOzLdVHS57A1CdstqBYew4Lfc1bLNK0QO/Q4yY\nh7XwfNgYryYbh4g5Mzdx+Kq6go99CQ1WD15V4i7A7DaRXB8XNLyAOLjwitb5\nAWcSP4qLfEbbBDE7I25StCi0L0mPYGQMcBnJp+7/N0ozCQTk2Jv/2abDyyop\n1qCNA2tj8l/tK6oHpDI5QZL5KkW9mViRp5SbIg345SDsPPG57khfsUhWCOsQ\nlTqmEu1NrmshAMx39hrm+NG4FgRKNuI6OvnoUFCuVTwx+Nbrap5UQMHq0vUv\nfBix\r\n=asq9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDZj6Xubu/qkRO2cit1GCL6V9r1VAynuE5oQaoBRcOYuAiEA6+zdEL6x+NWHyfEB3qhwuHy7RvNEqeAqYDDiTWGFiYg="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.5_1591136370279_0.16070199509129246"},"_hasShrinkwrap":false},"0.7.6":{"name":"@nandorojo/swr-firestore","version":"0.7.6","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.6","dist":{"shasum":"296aa2ee93d494bfc11e907e6242a478044a414f","integrity":"sha512-sf/aLaVaKqCEpe+iCVtEqa99ojYpnJS1yvG97XbUSM17Xot57lMy4kJ2hAu32bLYlw+9RUIxnzaspT2jxpnL/Q==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.6.tgz","fileCount":117,"unpackedSize":213063,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1tO+CRA9TVsSAnZWagAAQ1IP/jiCUapoMfgt5nSUpBIl\nRNahByqdTCR1lR6RFgd00hzqtIpwHlOWOTdIwZeTUFRQ9mHxAbGO/Wg+xBjg\nJSlJ5b8AtaI2CIqUQQMC0OiKO7S2cd+SLCkSC5XFwAxDdr1+OWDw3Gi9Qbxi\nkTyMOTBRGViNnge282HX+8Ka/Vmf6tLhWlTJlKIk/3WDChzg163x1mTZJx8I\nt44X/1nUTTAvINgFBru/Cdm1mJbK9Cgs7aav4xWGQPDLU+VE1mlwd5/B2Z2y\nA5KMPSDEi3fSly+IeJnbt8g0R4GMWA5PsGrsEXxVx8/x4aneHFG8XhULzZEt\nAk6hyb4285IHaarInL/Tsib3cs0RzW0JWx0DoV4dsi81gYY7vRB89NtPw7ga\nvkeaOEhNPdEpKib200pUbe9KuZ8zmeXBFfLiG9qW4ZAvMrRcXMm1HKEVMWfz\nlKwjwhswPlORnCvuc3VmiKC1nz3dlgvDeftc7Y4pqJmobO9CsAQ3VhXzVU3k\nSGo0Bl9ltA9xhDFO8zZLLKrgdklblxVdlcRiG38VgfOpgrD87Dlrr3WVdRyJ\n41UlTrXs/e6LP5IhR5l4frWTM1CK75ORk0Z+M9AEBfalxEel3gxhQVqCcwpt\nh+zGnt258b5Kg+avXu+gUY4R+NQTzatVUnuhC1qhNYQW8c5w7MoSML4Sp4CL\n24hO\r\n=yXUJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAXs9AxmgHWRNaeJ6fNunK3jc7hzEpjJ+3RB5pjdnPGeAiBLBQT7IjTwWvO1iXq0+QyejKB70duJIbzpF+efMdq7UQ=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.6_1591137213841_0.5939114417484512"},"_hasShrinkwrap":false},"0.7.7":{"name":"@nandorojo/swr-firestore","version":"0.7.7","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.7","dist":{"shasum":"ac047727e2a527e2f548d239be9c38d9c499da8c","integrity":"sha512-Qdxhx3wspe0/vWrO7RJqbegdiazt/2p/BfAdSrFwTJ/8T88FJqMJoVM8SOsdCZo4GqNfmIztp7jQy6GUSNL7tA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.7.tgz","fileCount":117,"unpackedSize":213551,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1tP8CRA9TVsSAnZWagAATK4P/1QCgSQBHHzqZoZq6Kmb\n6VnLz9u7LIj3WT3T9xW5MS84qFqRnX2O0tUNbcQLR6f8CDMtZz+sXBHdfsxT\n4RvZxuAqsB/HdVyoCES3JKDsEUAZh1uVU/fomIgAwPO0ekQYv5WxmbfacmxI\nOW9wmBuDULmVgQTny9Wcmt7A8h0KRwQoyLMLpnDUcpLAwsMiCFixUHhtFVcG\nnhVCiayawCLTIKdemV+NncrkaJP2OMEgvEFFfSoaZLTqocjuPQR5SXowUGwp\n5G1Wz3lqICqfhVSmIsfuml38ueHj3PFxPU/+pkcy/tX/OwCW05No4pn4QPz4\njG/kgJ9dOcwIcfg1fVr4C3Sf2qjRiekvPDhmARA97uR8IC+C6H+Bnz8VYOBF\nqw1pjAG65DERFcs+6G5c0YUPGl4XVBo8jIfev8+eRSW2Jchd/X6/9a/A8qNZ\nrcrR6k/uncoWFRsnsetDNILN0mvS7MA4U0V8XhvKVpx9nLts+1bNOU01dctA\noOsDPmitjyaweET4Gztz3jZKQBytUcULAiGehtUp1DL12DfmiF9JnanuQpqR\nXkZ9F7Ivmu6PYRVITJydbWUGp0dL77XhDAP6JcoOfwdiIeiM60yqkusw3xz8\nVodTTVAVqNYnWcc6hSFEpK9fDShJKsIaxuglp9nGmRqgQZ3ITCHEfUlxhlS/\n0vQu\r\n=rTNp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCCm1ot1BuWv/16YX9BVcHpbTtgzEre9juBUIFvTtY2CgIhANKWjrHytGSmMgh5NLbGHQ5V+kIbScdeJjjkpJk/c/kO"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.7_1591137275721_0.31013085478384195"},"_hasShrinkwrap":false},"0.7.8-alpha.1":{"name":"@nandorojo/swr-firestore","version":"0.7.8-alpha.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.8-alpha.1","dist":{"shasum":"5a77d1f5fd02407f7633a4167096bc66ea526c0b","integrity":"sha512-Gf0vU2KoMPzYMZYfs7k4Wg4/8mPzp8SZfNvJNgfDNE6LUtnr4C2OUvZAH2w1Yr20nwZoKVjG2aedZsSL8JIJdg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.8-alpha.1.tgz","fileCount":117,"unpackedSize":213421,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1ttyCRA9TVsSAnZWagAAbSoP/1J7ZU7T3jXTzoLyMx20\n7fxQCnKqaug9OU4YoFhXtGG00vSfCFXVG183FaDo2lJtBsA4B62eV4xNG0Vi\nPqkahjxI7bQV9oz2zsdqZ3ZrqGIEFuP07h5NCjhUGuy+sg8wdr5FUlIQuFYI\nMtDFtAHYW7XetBwJ7lCkiboRR+iZpbmY5T+17vECm9n5Ron79xflJESaRqPL\nyaUeDAR7breZ2J7lGPmgEfQUSjb/MuNlSFvCZkia6ad4HK6Kiwk8Osz4HsyW\n5ZAV8247WtLwgjd5aMO7sf/u6CiMaGN/L7s8tTEuHF89hA/3qQCXAzoXSiCz\nTZ7ljCnim6oFkto1ouKdz1/BWCz2GCE6GHiC5+4qvzuYxTjZw7fiIHhgBvWj\nLE8JOFrQxOaka9f0XXRE/DKuCDOm7AlIAnI0i15p1LfMI2m+lk797mtz0uF/\nt2JjdfjglhYOGBq1DzrxewvjH6oIAWbQLPQxdbJ4L+D7Y1X7wijo/0wGs/+i\n9RTgDug6XGKOIsUxihmjuw6k15TU3iNUIub59XezmJ7VkSgjexwa3cFX9GfD\nZCjgM61Q8gJS4MO4kD9jpN+DitphAr9fZJzVMYC+S0vUk6SUaZ91oVc+tELd\nV/fQWsTi3nbG6OaaYJDWl9lahVCZJQi8aDP7E4xLtPmPdDoN3N174sNDN7sd\n33mQ\r\n=h7RJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGlVIwJH1KqJkR7XgH2BrjcguHhfVxND/bDiwm4aBAfiAiEA9DizEnk2YCgDVTg0tWZZvHzzWra3nMqwILQhJQ6LzCc="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.8-alpha.1_1591139186309_0.8258016193631894"},"_hasShrinkwrap":false},"0.7.8-alpha.2":{"name":"@nandorojo/swr-firestore","version":"0.7.8-alpha.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\nQuery a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\nSubscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\nMake a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\nPass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\nPass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\nAdd data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\nSet document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.8-alpha.2","dist":{"shasum":"372e8e3c15967b30cd0088d2727f1b7b0ad0de69","integrity":"sha512-R9deqZMDK+cgkdCOgwyqiv5ExDbXnsBVqbLwxokoN/dOb94G9J/ypoKEPoACj9GDqYstBc2cRL9sGcsByxvUKQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.8-alpha.2.tgz","fileCount":117,"unpackedSize":213388,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1tuVCRA9TVsSAnZWagAALAcQAJ2UXm1QK8qU/mwyD4u7\nDJjemgi4P7kvSjwLAWTPeVZhtFXATeE5YLstJmJQUm498YJLNdZhA+CNLJCl\nRlmvbUjFQsNGwypSD26Q609GvIHXXwG9qKU6hnBLtvFACZ7Zt7IMn3a5CdQe\nELCO/kVEAgpADtlzyKGtVI10fL50mS9xG7pPI7zwq/vocd4T6ANa/YbitGC9\nzLs/AKVwottNQIz5Qvap/99BlZ6Qt6m5lMB0vB3ff2QnwFTWIfZAnhwUZTQ9\n1ekxLVhurjFSof/UzkM5YckSzs3dCviFx7HZ9B++501AwkrqZcYORS5HxdtA\nW2DNfsBIHi4bF7r1CnrSBSK2WVjIpuWdgjygPFPZ0Tz5P5fGulxIZgoI22CY\n3QyTuA07x5r8bGW9nq7ne35/UCPl1QiZBaAeiZi/+c6S3c4A0jwh9XrCcOj4\ntaI4+TReqpA7qw0Q9liKLY8t/uLUukMEokG/LddOTSFVIVim+BW7NbdrOZ0f\neSj9hDrWFeEZpJ01weGbXB5ISu1kscr710WryQKEBC3OIkHiXbPp2NS9qH2X\nq31HjgjmEJz5KU+H6vbdFx1va5/cke8LMfJ89LyreXZy+YXe5L3HkyUZNMvv\n7qJbGv/xNg5OE7jvlh2obhZbOk3cFc49/xAMLpIj2Ih6fK2kuTkz72n2iTZa\nu785\r\n=bYOI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDVs+1SjTAqNGAyeMVgotwDc2nWtCWZ5xxNnFRVRjOcKQIhANjTDlgMj8J8oPoGk96dcQ0L3lhbnkwKEMg98dELphQh"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.8-alpha.2_1591139221082_0.6828689679558311"},"_hasShrinkwrap":false},"0.7.8":{"name":"@nandorojo/swr-firestore","version":"0.7.8","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.8","dist":{"shasum":"2719f19cef5633d16fdc881cbd4cfb325e2cb013","integrity":"sha512-p35oCqrWg99UDdwxSDGGgh4S6CVTdlmoZQ9Ka15FipLWjOH2dd1a/jpKYkcYTtaIHn+bF4FDnmp5uvp/nMijew==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.8.tgz","fileCount":117,"unpackedSize":213380,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe1tvrCRA9TVsSAnZWagAAbZ8P/2NmPRwYK6f8USflHFq4\nS1tmPOZoQGxh7VBEKxL4aDNNhuHxekKUZc2kCAblZw/gBi5hsW8Ko8vqaLkY\n28N8JGJNxHLgnVfbw97j1e4gFwS1j2iD9iXp0F5t+p58FkC2EHCf6AcZbWeQ\nMSUDd3OAYdbyqc6Tuf0JhY+S5Wq2YVihPfgD/dUyJSCJKycIJFXfjwwDuIwi\npN7Xk+SercYbWvDZ467upGEEXl5hIHrSYJdVt87DTGROMw4dPsbMJqksfe0K\nAsC44BIQFTFtjf1K4Raore7vDoPJmixhSFy8PoGBSEzUnkC2yLwA1ZeNargi\nrgKO1SLTxEvNXG2uG2X/MbEBSkVEE65CEoqV54DxAWXiXt5mJK1vghcHNwxf\n3mPZH75FzGgqb2oo+pZQYyn3E8pPA0sB6dPJ2ClUY3Oz5qbRa3O3atwbelP5\nC8eAQFMxZPaVqt8mvbd0ePQFMXxFPS+kIOszg5DoVJq3KA6ED3BY5y8uLh2j\nXsT9iwES69UrCTfGuLpTDw9avDLvLMRoCgkY9V8CsRvaPFEAbhAUHsbhJgIF\nL5wxYee4qhJ/dCyErbBmWbVLDhAC8/8VLb2AQN3pVOC9Bwo+vEtDQZIzRQeG\ntyEGdD0HqjnmSow5zKrnNU3+hIBdJBYOFSPrvMGJbLNfv5fl3Cr6mAGix6X9\nlwut\r\n=IKGP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDKLQNrRcx75r3v4Tl491rqffnCmsh6jOIUFkWpGU9MogIgAbMQuGoUnvCZRLto32tP7qDRV12A6eZDDhaQF2ElIB4="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.8_1591139306821_0.922487482595977"},"_hasShrinkwrap":false},"0.7.9-alpha.1":{"name":"@nandorojo/swr-firestore","version":"0.7.9-alpha.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\nexpo install firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n### Use dynamic fields in a request: \nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Paginate a collection: \n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set,    // set a firestore document\n  update, // update a firestore document\n  add,    // add a firestore document to a collection\n  fuego   // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`: \n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n  \nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n\n## `add(path, data)`: \n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n  - Use this **instead** of `firebase.firestore().collection('users').add(data)`\n  \n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n  - `db`: the current firestore collection instance\n  - `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.7.9-alpha.1","dist":{"shasum":"ded622f79eb3b55bfe59a564705f7fa4db1c41f7","integrity":"sha512-AxLpw0e5Cw61nt44zCPdzxBUIVoCXNGcS/721Zf4jNsuNh2LgNr3EePuyR06HbZ9d+nv71dHWH9rRyL5A/5jnA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.7.9-alpha.1.tgz","fileCount":117,"unpackedSize":219957,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe6oSXCRA9TVsSAnZWagAAe6MP/iVfJagDtRvNRNs+PHkp\n1VWdmLYMrnk7hxaKDXJvBS6RU4UcbyIlM3/lgHQK9RQEkUtKpdGDe5QLoI8G\nQq3o3N5bJmN5FwXWGjVY7E3o9NoIuisYJTMPL6FZTmv1belnpVgOe3M2hqJd\nl9OKX+3V1iDifrwLEDgdlqDxwQGarnRLssy6CUWIQBCdqKyhQAhEJHRw38hx\njh4E4chGDZ87O1ANnsQpzX8jvWQXVFglH9j/0HmgxzQI+s75e6wILPwTmiW7\nu3tv+xytDnXWs+aDx+J0DatpSYvmGq9RnX8N4ypvIzGLzaCAT/cL/W5ciBD4\n48w2OR5iq9z7uLX62LGbLd26dinttNe2mgwX5k5DAQVBRDVYjPyII0dw0ZzQ\nfeSrYjvTa2AX3wRk4HJP4nAOP5Ta/HpX45iuLNRlYvzujDHMPg9HD2uQy1n8\njquWV18hk2zQdNDX4m2XlagBmJm3Vcb6SqOlxbtbw8UBPwT5cZKIGI0tUrr3\ny5aFJOoI1WmfTLG9G2L+sXFAblvgqY72eZhJNQvHbqt2gtVLXUzxD3qIrbWK\njbBjXsyRABLsjwvwqw09dEVJMJiiVnr9okQ7doUhgxD17/5Bfx9qsPiyF4s/\niBKRiB55cKn207Q+XZBNqrKL9VF4JsOvrUftI5eHhyiOG7cC0nUmzTSIzajY\nM8gd\r\n=OUxL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGNFRUHcLkkCRQrD1Ys3JOYzqJUMB6U57Hj6nbR/C/pKAiBcDeZMHgIGMfr264qvuZ2lz5mi0/oJ6+pNiz7jt3q6Ag=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.7.9-alpha.1_1592427670552_0.818241906945371"},"_hasShrinkwrap":false},"0.8.0-alpha.1":{"name":"@nandorojo/swr-firestore","version":"0.8.0-alpha.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash":"^4.14.155","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","lodash":"^4.17.15","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n### Use dynamic fields in a request: \nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Paginate a collection: \n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set,    // set a firestore document\n  update, // update a firestore document\n  add,    // add a firestore document to a collection\n  fuego   // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`: \n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n  \nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n\n## `add(path, data)`: \n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n  - Use this **instead** of `firebase.firestore().collection('users').add(data)`\n  \n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n  - `db`: the current firestore collection instance\n  - `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.8.0-alpha.1","dist":{"shasum":"0b8c1b3f9f08b83a1197eb70aefd78604ca44049","integrity":"sha512-OuCKw74Q7mo8o1DU/gEHdxrfW2BDBNzDhZzTAxOW1Z2aoRPlUix9O+Q6z4k3uQWT49a0NTsfig/DOI2sBk4Gkg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.8.0-alpha.1.tgz","fileCount":111,"unpackedSize":223830,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe76tHCRA9TVsSAnZWagAAnzkQAJY9VJwW2jPfVcCFzr0w\nmkxXpTZTFUQhOWvooSuKE6dy/Jm6bvAvWbCp/wBseMNqnX6tBBknpi0Gb0Au\nh8y7jbvBXUu0keW7g5H8v9GAUFFZa0yEfDjGOcHGF01CnmOvTga22DvKcrjg\na6UZuaIP4zrvddXfGvVDoGkv2yQIplHtFQj2eQEaf975v0uPEc/XnFKH2Fan\nUtvN0ba/rVqPhtAc9UWiP/nnCtKudsnH01boN9I+TwSzlQpQuqUjZtEJOvRY\nkoGt0XR39gBVmH41RalZLGDq9zMDjmUAQe6pgXk2fx0FCYPrptOWQpppu37Z\nNc151vcmsSBxXkj/N++Zx+bYvUYJv+wgEw/FtGWIvkD4YZcRvh7RuX2VEOdA\nxbf6ArwlS04x/T9/2/lzZwgRB0gilSHTSp/7fF0HPMpSCqeWyLxibaS6fIdO\nAuAAmyujZGNvJb+jh1Jp+PXLm7L/DtGmqKnz5Sw0AltcUoDDe2lJTuDGVJ+b\n+TBLfoPoF5wrgEPWcPFmgfM1yDsLS2IvLlxkQJI56pm6WoUl5b+nRwGn6Rag\nf/zJ/AhAdYD1YltXbSWOe6A3yA8hbdpuHZiRW0TgORyIKwn4lOy+0T/XoqnB\n4N8D51FyGJqn6pdftGMAWoV0yJznr6WzSpWviD3yRCwpWfkjN33TgffPWQPQ\nTuzl\r\n=97Xm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFDR/Y3BK7n/rkvh7civ8B2OH40r30nZXks12AwwX65AAiApuQy3hkOWuNSECCQ1YCmOWxeVpRQ7OiI+Wt4e+BS7EQ=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.8.0-alpha.1_1592765254817_0.8962038898250351"},"_hasShrinkwrap":false},"0.8.0-alpha.2":{"name":"@nandorojo/swr-firestore","version":"0.8.0-alpha.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash":"^4.14.155","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","lodash":"^4.17.15","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n### Use dynamic fields in a request: \nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Paginate a collection: \n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set,    // set a firestore document\n  update, // update a firestore document\n  add,    // add a firestore document to a collection\n  fuego   // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`: \n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n  \nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n\n## `add(path, data)`: \n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n  - Use this **instead** of `firebase.firestore().collection('users').add(data)`\n  \n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n  - `db`: the current firestore collection instance\n  - `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.8.0-alpha.2","dist":{"shasum":"2f94f57d67bea18207bce90024b44c06d0daf09c","integrity":"sha512-C+9ENmu8PLJ52tME+t1C2eTrWpSSwqMBfQFtMwm8OAqGOwnmlwPPTSSLPzh4J1oGafVthfx2vLaaT7XTVxUtpg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.8.0-alpha.2.tgz","fileCount":111,"unpackedSize":223825,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe76vWCRA9TVsSAnZWagAAKIwQAJh8DdhXiGBwAVAS7vXO\nWiOmg1B2kWEoy3C9I7z6FWsn1rIBGp/lSAXsMZ1Xve9uzAZAWv9ayuQZPwJv\n43NDgjvCT2FUrSkU4zB8UcyGN/Ygbrrtyr0qPf6X0BlMcp13ZvWRe6ZUuOxk\nwIx4O05hyiq/LNvYF6sEm8PvOLnlJf2kmP7i4cQxawmkUCvmy8L5EYDqrG8r\nFCP64MfrHpnyGtHq7CmfOPfVAHjDJXrJJyxV+VhsxU9KMOjnOnJ9JPym+org\nfw+tAJAgoJxwZrg+Q/pnA2DgBp+CgodJgI1i/p2gobdw1rQnc3XrHrl0UuRt\njiLBkq63x7+94nhMfo6Fryce0yRklINWv7ndzsNlMUQ3DDQxTFrqVL1/4Xu0\nnyeVivEhwH0L8YE800O3n3UnCmQHvDClkBSnCA2KvKhowZWR0o7GpCpdXCD3\nikwjTCSniIQWv0C6xIdrfTYqEfM3LMadEbcfdj0YRvK6/tW+IxPs26l9L5qb\nsePuRO/L/APZYC/WSd79Kyv25R90aPzBIm361QlY4PALsbraqSoKgMtEDXKL\nlrgWeqQER1NDTXNbx5A7MZPAztNSb9k+lTRn0YX4HmaQi5hy8j6BAwufv8ZH\nPuRysNfM6CxoebXgQMm5G9OaUGHsVo3eUdLXuVMVGUMWmXcVO8rhhr/VcTO1\nhm3X\r\n=bDNj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGSXiRgSUlhaarh2ncX7gI7L2EhpacXSMIkW3qbpZWhBAiA9uUImnlO7vDMpsKfjI1XUD8RBdiruU+IK63T+p4uqFg=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.8.0-alpha.2_1592765397997_0.8685556513024482"},"_hasShrinkwrap":false},"0.8.0-alpha.3":{"name":"@nandorojo/swr-firestore","version":"0.8.0-alpha.3","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash":"^4.14.155","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","lodash":"^4.17.15","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n  \n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n### Use dynamic fields in a request: \nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Paginate a collection: \n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set,    // set a firestore document\n  update, // update a firestore document\n  add,    // add a firestore document to a collection\n  fuego   // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(\n  path,\n  options\n)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`: \n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n  \nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n\n## `add(path, data)`: \n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n  - Use this **instead** of `firebase.firestore().collection('users').add(data)`\n  \n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n  - `db`: the current firestore collection instance\n  - `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.8.0-alpha.3","dist":{"shasum":"2db56454578e11d44edf9b79e43d87790bb4364d","integrity":"sha512-FN8uq1safw/vc3JMwnM+4dPFq6vdwyHLQgZPdOUQx3Z0720a/osKOacAld/r7hYvjh4A7E7+kOHGmO8GKPo4LQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.8.0-alpha.3.tgz","fileCount":111,"unpackedSize":228854,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe77OwCRA9TVsSAnZWagAAIx0P/j8Azy7GPsS6tmwjeiNQ\n7ItjQUWWQk4A7ktRw8fT6FSRArPEGehc6RNrMYwgiRwoRf97C3iOeTMcWj7d\nU2NfQgV7Mveih8YY05oV0s/X+lhKBGmf+7JG0LZSlCWIB/iH6wqR1+2Iy87l\nkVJqDcysdfZeH9HoF0uMjDD+nBwE96DE7yodC4rWXElwyO2XHiOR2VgDjuvN\n9RBeNPLFZFTs5gqDuquKjQzfceS5iqvzTfNLE/GimC+dXw98YTHy3h9pjIYY\nzmPubrXaLo98G/AAXrOj3UWtA5Kiyk1JsfsXT0e2MUSkvMSvIbkCRdtFAkSP\nRdAmATTCO4j7xR6zp+vcn//xNsVr/PsVP9CrDhSw3kaROsnbqPfT6kFsq3k1\n5Q7jLmZ39iDbqVb0Tti40ENjglq0JfcDi4mrIR3r7fw6QgoZAei8sXLWQTN9\nLsDfHHDFE+NFnCw4ijSKQupdJPUJNlO2cB6oLRC29Fw+DoehlqWh15HqPghF\nPsXjJsIJi4fcgJWJNqK/jQpA0aazXaxsQZnDgzmS5vPUNDroCJu0J28Fuffc\n6irSl/wCwQc23CKjoBBkGEoIzjAODIFgP6crMmCmrw0AOYqGDejbZXf1eLpY\nROrKErWdbZog7G/C4ubRUO7eCXfjHrxv3/l/NJNYyebILUiyffI60Iw8qwZw\nWNhz\r\n=X1L7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICSvDPtepkYhLZtcMWgoJZSY29BM6jPLot4KJ33X2p69AiBQVSOX+uWpXZRN5E72G3kkt7EYCcxKlzXfhp2Uvtm+xw=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.8.0-alpha.3_1592767408425_0.5778438436123017"},"_hasShrinkwrap":false},"0.8.0":{"name":"@nandorojo/swr-firestore","version":"0.8.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash":"^4.14.155","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","lodash":"^4.17.15","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.8.0","dist":{"shasum":"1826f63142ea59ac9e327b769b4b7944080f5ec8","integrity":"sha512-HY7tf5RAwvXmj71Jcmp2kDFDikL1xGwUTKt4uDbmYR+buqutU5m83NNJe6H4bPCoFv9KLBJ8t8t8GHLPknRS3w==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.8.0.tgz","fileCount":111,"unpackedSize":230221,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe77yLCRA9TVsSAnZWagAA9xYP/jNB0VGT/e6y3S8xxH12\nAl4mFmOow3eWpN694VRNW8do/UvsXJZ3zcHKRtwS/644HFE9eDvDBBBphLxj\nh3kmVRTU8fYSG9Bz6vVjxvNmTJIsgD5fEQV08RxjgaCVu8SQKikSb8J7hJBU\nhqbI1k26wkTDlzUcSx6Te8pdb4de+QdCxPW7m87JaWx+lKtLU4aXHj5PQXG4\nYL3ACeD29Y2WUV1qzpHoi7o/PLc1VStsSvz0jSto2ZEDGOwbkO/aCnJw8Lpq\ndtURZCAxm1vaZcK+2EMtzwtS6fr1UQHal/Mli0xdkQ2zjQIP5iCA/r7K2e59\n5OyCuq0QB0/gZqx0f5gWO7C+ME7o80wyrC1XULaniAX1OUNSF76ZYM0U70Qr\n5xvOQvep28Htff3HQjzOSqNmeqoKY1mfgKzmPetCemFfR7LVFFgS5mJZQOcw\nDg4rdALYkIYsE4ery/uWPECesSaxoQAzY56eIIeGFzb7kO9+5Gy/2Ukr8MMI\n4GyYBjK4QvqFyaYwcLbltRGnqy5FepO04JuTCm1n8Gtq8RcIhGNpPfbRvb2u\nBJq0Ssvms9YQMrQHfXtrwW7yN4VI3LjWmPlK3R1Jc78Eq8Q4ceJDLaUYWmWd\nzOl8e14htMNG2OSuOLuPcMPmCBZM0gW4Gijvum0heEXf2oOnTZzxFc/QL8TW\nnMEI\r\n=Al27\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDzG8/LBBX4Wuax3dgEM3tEavSoZ3mMXLZAuEKLssZ2zAIgfcjwX0Qp89KpqiO9iPF+yuzdW2nrgw2waq4gAWkZB2o="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.8.0_1592769675022_0.7929005263104945"},"_hasShrinkwrap":false},"0.8.1":{"name":"@nandorojo/swr-firestore","version":"0.8.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash":"^4.14.155","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","lodash":"^4.17.15","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.8.1","dist":{"shasum":"cd832f8aa5a6200c09f97df4e1b24879ae419307","integrity":"sha512-/Hm4etgcUE61UZMDKN1k3what3QDD96/xuhhXr42aOzZlm+QovVFgAYgIB5ahMj9JphverAwJp/EpFBxkbgKpQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.8.1.tgz","fileCount":111,"unpackedSize":232799,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe77+hCRA9TVsSAnZWagAATu8QAI9Fx6luX9sK6uDedC8a\nGQE6pi3s7ig0r5CZGe43cmmKxm1fBmu6vjYwZJV2dQI3qZYrIbc/7pzO4cjr\nUvGdsnSE51mpNorxdzp4mPcp0JtSBXHgkYK3Dh4+WpACewgr/Qads9zD2FbA\nBUh36w42E9+tHerXybR5JyKFhijDvRUXrR/RDb5COZwwC+f4ZVIGGJKzSJJR\nFaTGD1KGrqKDib4i0vzt2eSfis2twKVZ9K416cO2iRjyvy8UyuvPIjdn1PoG\nrRYZ6dPIJSrc+T0pSYo9oNpxefxW5rkPaCMNVEhchDrpmXzS0Esk6UL9PeEy\nDkj337+zY/EmyBK7Obn2ry9ACW1JPTfQP0v/TQ//Tn40OrESqCZVjVG9R9bj\npM7yJuMbxTFCuc48Q5aBhWf5dtmoaw35WXw1OlqEJiWRtuQCahc3RkGWk6KU\nV6qf56XjQx7vxCoCzDBbYpDrkIpY8Zp2frk/hGUD6Sqh5wfAdtFyVA9nObEM\n+I1Vhrmhaf4rkVYm+fZTEZkD65/s3d7uG2xv7HRD9Z8W9XHSGBoMyq+KHxHQ\nu7u/K4Gi1gLEgjJdD2dQMmAtVcxEmlwl1RZnCVTDnBXz53jwJZ1I39vGO+Cd\nnFpdckt00tcVIQYwSZoryGuCV38ty1mBNLBQqXio1DzhBEJotsYY4lLlm0lX\nBHNq\r\n=uH2t\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC1oxUQ27vxi0+GrpeVInJetcEskRpT5ZfsrVoz8wl5zgIgOZseAzOGDfsZXCe86ejCQBIuUvmT+nbOWXI2mgKtIrs="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.8.1_1592770465306_0.6420775496644959"},"_hasShrinkwrap":false},"0.9.0-alpha.1":{"name":"@nandorojo/swr-firestore","version":"0.9.0-alpha.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash":"^4.14.155","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","lodash":"^4.17.15","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\nUnder the hood, this step initializes firebase for you. No need to call `firebase.initializeApp`.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return data.map((user) => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [['artist', '==', 'Drake'], ['year', '==', '2020']]\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake']\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020'\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true\n  })\n}\n```\n\n### Use dynamic fields in a request:\n\nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Parse date fields in your documents\n\nMagically turn any Firestore timestamps into JS date objects! No more `.toDate()`.\n\nImagine your `user` document schema looks like this:\n\n```typescript\ntype User = {\n  name: string\n  lastUpdated: {\n    date: Date\n  }\n  createdAt: Date\n}\n```\n\nIn order to turn `createdAt` and `lastUpdated.date` into JS objects, just use the `parseDates` field:\n\n**In a document query**\n\n```typescript\nconst { data } = useDocument<User>('user/fernando', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nlet createdAt: Date\nif (data) {\n  // ✅ all good! it's a JS Date now.\n  createdAt = data.createdAt\n}\n```\n\n`data.createdAt` and `data.lastUpdated.date` are both JS dates now!\n\n**In a collection query**\n\n```typescript\nconst { data } = useCollection<User>('user', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nif (data) {\n  data.forEach(document => {\n    document.createdAt // JS date!\n  })\n}\n\n```\n\nFor more explanation on the dates, see [issue #4](https://github.com/nandorojo/swr-firestore/issues/4).\n\n### Paginate a collection:\n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set, // set a firestore document\n  update, // update a firestore document\n  add, // add a firestore document to a collection\n  fuego // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(path, options)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(path, query, options)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando']\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [['name', '==', 'Fernando'], ['isHungry', '==', true]]\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando']\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name'\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc']\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc']\n  ]\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n\n- You can call this when you want to edit your document.\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n- The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`:\n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n## `add(path, data)`:\n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n- Use this **instead** of `firebase.firestore().collection('users').add(data)`\n\n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n\n- `db`: the current firestore collection instance\n- `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.9.0-alpha.1","dist":{"shasum":"a4b6ac20cb58a4a9cfff9311809a87c31a2c53ca","integrity":"sha512-/mgcm4+8ih4itU/bwiAz4qJg8mt2zXX6K4j7v6hqOSl/4aCBoAnlJ6AfInKsL9R96GD6nNBrBZ97XICpNEMzLA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.9.0-alpha.1.tgz","fileCount":111,"unpackedSize":247644,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9RbPCRA9TVsSAnZWagAAGSgP/0hyts+YKuJAx1iwJeq9\nJ21u8oIEAzt7E344emOWCtmAOjR4AWiAPEGhZy9EGeZhYdvB3IBYB5tcaXYO\nFCSG166JSb6ipJPQYETksW7UNTnLF7PQ3f4Qe4j9NOpYmL3cZ8vFDbOGnSi+\nhlXPq2zvgkV3my79LFbXVnmjrZulCPh4SSLKnVRhE34RZw5KXFvV+0ki4yb3\nzPgvry+eho9KW8yG0nSIVqaAAX1UgVh/WISRLIIR14tjLHdyKWwEy4WSvBG3\nX8pxrvCdc5yfIGgAIrjENtoZG2N6Eq+Q+lgRldIDN/DbUvtH+28QnqYAGspM\nXNYucZdyczUY6zbpATCaSUEDet4eMXhIfMibh4teMMbwzdyane1/UdwluL00\nwA5FF3YKD49Zy3xFxkzoC8h1Ab6JBxKCFMnduC64inf3NF7s2WCsw7lYwJEd\nBcStyPEXlasPfutmnQGFnTLm3WKQ64IA3JJMPU5tOuYhiqVnbC/dXzq1Tqy7\nlmMKe8Xx93f+DFvd8LgZsr3MClChr3+NI2K7wijcGojHGL0BfJw4brRkYFAJ\nljXqBXR0jaBT0VUbuxnzTKQLu3Kv05XAcI1AEontpGR7FMRX7S6PUY6/hpV4\n+1IUVHMh6afa8QZO6BNInAcdwA9MnscR2kt8nKPhBotqA1bnHVHmXZNmWKQf\nFda3\r\n=xSLa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHezT+GtMu3Hh99r5p6dW5WoBRRobtlv+48MxGzu5vfbAiA/T2dSYHXuGJC/g3IfIobiLxeQj7z5+Jm9TtXhvdSNqA=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.9.0-alpha.1_1593120463114_0.03964922437182383"},"_hasShrinkwrap":false},"0.9.0-alpha.2":{"name":"@nandorojo/swr-firestore","version":"0.9.0-alpha.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash":"^4.14.155","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","lodash":"^4.17.15","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n```js\nconst { data: songs } = useCollection('songs', {\n  listen: true,\n  limit: 30,\n  where: [\n    ['artist', '==', 'Drake'],\n    ['yearReleased', '>=', '2017']\n  ],\n  orderBy: ['playCount', 'desc']\n})\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n- Server-side rendering (SSR or SSG) with Next.js [(example)](https://github.com/nandorojo/swr-firestore/issues/17)\n- Automatic date parsing (no more `.toDate()`)\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\nUnder the hood, this step initializes firebase for you. No need to call `firebase.initializeApp`.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return data.map((user) => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [['artist', '==', 'Drake'], ['year', '==', '2020']]\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake']\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020'\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true\n  })\n}\n```\n\n### Use dynamic fields in a request:\n\nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Parse date fields in your documents\n\nMagically turn any Firestore timestamps into JS date objects! No more `.toDate()`.\n\nImagine your `user` document schema looks like this:\n\n```typescript\ntype User = {\n  name: string\n  lastUpdated: {\n    date: Date\n  }\n  createdAt: Date\n}\n```\n\nIn order to turn `createdAt` and `lastUpdated.date` into JS objects, just use the `parseDates` field:\n\n**In a document query**\n\n```typescript\nconst { data } = useDocument<User>('user/fernando', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nlet createdAt: Date\nif (data) {\n  // ✅ all good! it's a JS Date now.\n  createdAt = data.createdAt\n}\n```\n\n`data.createdAt` and `data.lastUpdated.date` are both JS dates now!\n\n**In a collection query**\n\n```typescript\nconst { data } = useCollection<User>('user', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nif (data) {\n  data.forEach(document => {\n    document.createdAt // JS date!\n  })\n}\n\n```\n\nFor more explanation on the dates, see [issue #4](https://github.com/nandorojo/swr-firestore/issues/4).\n\n### Paginate a collection:\n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set, // set a firestore document\n  update, // update a firestore document\n  add, // add a firestore document to a collection\n  fuego // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, error, isValidating, mutate } = useDocument(path, options)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(path, query, options)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando']\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [['name', '==', 'Fernando'], ['isHungry', '==', true]]\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando']\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name'\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc']\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc']\n  ]\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n\n- You can call this when you want to edit your document.\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n- The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`:\n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n## `add(path, data)`:\n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n- Use this **instead** of `firebase.firestore().collection('users').add(data)`\n\n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n\n- `db`: the current firestore collection instance\n- `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.9.0-alpha.2","dist":{"shasum":"139f63bda13fbed8c61715e82d0155b5ba934d8d","integrity":"sha512-K+S3M5XQiJ9Mc/GQp6/LU8rfBhSVwxs8+6aSWLVJstuAhOxGSSmd8Zeq7zuF1dh7qSG0sH0NhmB2XRzFlppcrA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.9.0-alpha.2.tgz","fileCount":111,"unpackedSize":247310,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9RktCRA9TVsSAnZWagAAPeAP+QGPbfOp8uKG6+ZHeuwt\nXtuJsMaiCp0Ue9ESCesoVVukVRjIAN0dk1sb8Ydh6QkP5Gh+ugWzz1sE3IHs\nwvZ5enxGJSbN66qCRLpqzFadNWhqRntOZbXILjj/fW+6NJt1VEsLy4pjO/jq\noGELYurVcSRzovqG08Ixi5kE0cgBM/ABwE1hRPAV++fUU9H4urSfgrWpz72b\ntR8vTkUPIMMKfIrPVZNLJvkCmdWjKQ1FcABpLPQApuu/haTHLBe7lsbuVbyb\npW3v0jY35n3YcSc2TKlpHKNTZMwvvP2xivD4TzOhI6HdDKB4+lmz4UPfsdN3\nfko94X2AmAiUQvypn9G3bllfyA0eknp04XcHMQNE1siFmtfOZ46l9RDcVh4n\nljmpZJY+jsDHZTo+wrIV8HpgJ0YwWUTX1L0uYSVuiOEO+GL4txr0uYhZwY5h\nTy9UAyMTAWo3z62jQDUFiMczVp+eFpoz55fmb3agUQEgzYFW63zeiF8g6VkD\nHwyOBv1as5Vp/GyDn0D/wKiSXkG/u293/CHG+5Js2f4olrX54LcmVGDqSD9k\nZkMXOTKxMygDCzpQ23MtKirgO/3UwyGcK4XWpqD+yuFI6MlR4qz3KvsRJHfH\nFDpEmj3fEnu/Bc9N7UF47juOkKB+n23wimK8C4oXc03jNtC5E3/SaN9Nnu7j\n/asQ\r\n=Ok9i\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEg+wUCPL1JgF/FTGzJP2eTdYL8tsozAfZLhvw1ps+C9AiBpS3ujPtaM3bkO0FSWWiY0uAI4wet8UnqqhxXQDrtSMw=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.9.0-alpha.2_1593121068754_0.930881160923694"},"_hasShrinkwrap":false},"0.9.0":{"name":"@nandorojo/swr-firestore","version":"0.9.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash":"^4.14.155","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","lodash":"^4.17.15","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.9.0","dist":{"shasum":"affd59e43ed6eee9cc2c9aa0e30fd97202a6849e","integrity":"sha512-D59+R3VkzPG9gJ3nZLwQUvhM8527F1v0CDwozqRkQrKlc7iCPfu/nrxyfeqM56AB0ih32w5zoOSi8rCTa3cotA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.9.0.tgz","fileCount":111,"unpackedSize":247302,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9RnNCRA9TVsSAnZWagAATlEP/2Nz1E+A2EsM4Q7X0rmE\nThpz0X1dPRMH027Y1zhlbKb8m94Vw515Y5xLQQ+bJdu4kguCSARY60GJ7zK0\nPMFeUA6l/5Yom/F1c0RUapyOv4cS/O7sYZkoRvKm24fi4cHAbDVCHfjw3ERu\nr5B4wefhX+FQ1VItxarHao3NvNDL5QBrfpray6hpDbxZmLd/7oyfJzLl0Yho\nOkxBzaO5QXbI2efRMMfAXyofFR22PnCg7N5ebN5+6i7d5WMul9/0zAf3Wud9\nO+hVGRZvmMqjr9RMZ5N11M89YnvYu59xKTpFe8vzO9ndeGAcswUS7Ow4r2C4\n17s40I2d0V5bXc7lXd9yst9PxXr0pzn4DoZPaEOTHXfYg91cQAh8jTXpMTpw\nTtu2lFHFisD+tZYChZrh+QHoomHsEHjUiABHE/WoGVL1P2Sh9UeUHE1Jq7Mi\nCjYVGeZV/OOfunoXk9WzvaA/89TbMSPnR7AG6P2Epa+RHNJ5z/jdHRlEFvTT\nhhKI9TnB8Z0K5wG8KVm0y2f7fUuCrQSQimg3aCcrtaRWdEFril3uPT2bhQu2\nxL3R3Gmqf6+B8x32sTPHPitxSeehVDd3afXnF3TMQQaZOlDD9bjXslchtWuE\n3hvQwg7DMwFMZvj1yuZFmDYhDpkVajDp18ym474XOE0OJHDewReXyBpyhNp9\nW1Jo\r\n=/BwH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDHrlsKuoUREnAUiVdDtVaxdp6U07/eFW1Bs7cmm1K/KAIhAI+J4Gx+Fs+p2RNGPxgMhQt7V3rCbjZazYCGqKL/BcKt"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.9.0_1593121229210_0.7695515481015767"},"_hasShrinkwrap":false},"0.10.0":{"name":"@nandorojo/swr-firestore","version":"0.10.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash":"^4.14.155","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","lodash":"^4.17.15","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.10.0","dist":{"shasum":"f3b480eba7a5eb613eaff593fb49acaba750f323","integrity":"sha512-jv45G9DyhZi34ANgdx2jmVo9kfcycJGtTVvgmeodfjjS5YaGPs9Qa+Ww4N1ZZUuUc8x1/vjBpPcvJCI31+Fheg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.10.0.tgz","fileCount":111,"unpackedSize":249002,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe+1qBCRA9TVsSAnZWagAAYBsQAI86WVHz5EP1mnwLIx1i\nRZ5FLSuHvoeBqQwUNy7HrP+eRDtqRW36EjUqAou/fvBLMMmsEnuMi51+PRrJ\nxF3soOsQeI34Sox2Ak+jixs9AvUhvYOYcpurniy7LhF+k2g+8xCVDk7iKPFB\nKiruYF26IVOI82+50U1X7Pu4a++RQ4vmQ6wTQURS4OYfnGCbvrTR3/LVqpda\nVbnsBerH3u9bg87EQsViFXLUnUp9n3ctmy+OQz2fHvHXqfIjUIYpwTh7YbYP\ncc30IrHccj6/cMXpyn6PzZLNNqKC7jdB4z1YaICq4UN6XhpKNK/mjoyZ83T0\nZouvf7mdG2VJTSVpfS8P+i2NczzahJ2MPTsDChGrigxy/DchQgU9F7LhA8SL\n4a5yXy5a7Sue0FXHq4ncVchRW5OBgA3UhTsT3HopiR2L4cHcLBPuhh8mtIUb\n48zUmPIbpC4EOLK+GlWUY6q5HOlHCPCaMPJ2uA827Ha8Vu51rZJ+gzUhiU4Q\nPoQL3TaKIGPWw53EqwqZIO03F2iX1MT9tPKV03m1MxEK/xpKCdafzRl6XbFm\ngwhDzdRw+eQ4P0ApWG1yC5aLgdMuSF1GanQpmU8yfYPZm/dpoNQg+H6qagqo\nZQajGD7RIMgtq6mFL/bSTq9cQvGZpkGd97gLavWMWZDZLPnUmVn0qh1kAx84\nUpFY\r\n=+7pF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC+rsywMs3zYLCgUxEd3jiE9NFQWXrbTetu2A2ngwOVEgIhAOSj6+vTPV3iyTmJTLQql2Is0Ru1bSB/h9MWGpHaY5kQ"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.10.0_1593531008805_0.6580420732818759"},"_hasShrinkwrap":false},"0.10.1-alpha.1":{"name":"@nandorojo/swr-firestore","version":"0.10.1-alpha.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash":"^4.14.155","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*","react-native":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","lodash":"^4.17.15","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\n// Get a document\nconst { data } = useDocument('users/fernando')\n```\n\n```js\n// Subscribe to a collection\nconst { data: songs } = useCollection('songs', {\n  listen: true,\n  limit: 30,\n  where: [\n    ['artist', '==', 'Drake'],\n    ['yearReleased', '>=', '2017']\n  ],\n  orderBy: ['playCount', 'desc']\n})\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n- Server-side rendering (SSR or SSG) with Next.js [(example)](https://github.com/nandorojo/swr-firestore/issues/17)\n- Automatic date parsing (no more `.toDate()`)\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\nUnder the hood, this step initializes firebase for you. No need to call `firebase.initializeApp`.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return data.map((user) => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [['artist', '==', 'Drake'], ['year', '==', '2020']]\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake']\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020'\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true\n  })\n}\n```\n\n### Use dynamic fields in a request:\n\nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Parse date fields in your documents\n\nMagically turn any Firestore timestamps into JS date objects! No more `.toDate()`.\n\nImagine your `user` document schema looks like this:\n\n```typescript\ntype User = {\n  name: string\n  lastUpdated: {\n    date: Date\n  }\n  createdAt: Date\n}\n```\n\nIn order to turn `createdAt` and `lastUpdated.date` into JS objects, just use the `parseDates` field:\n\n**In a document query**\n\n```typescript\nconst { data } = useDocument<User>('user/fernando', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nlet createdAt: Date\nif (data) {\n  // ✅ all good! it's a JS Date now.\n  createdAt = data.createdAt\n}\n```\n\n`data.createdAt` and `data.lastUpdated.date` are both JS dates now!\n\n**In a collection query**\n\n```typescript\nconst { data } = useCollection<User>('user', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nif (data) {\n  data.forEach(document => {\n    document.createdAt // JS date!\n  })\n}\n\n```\n\nFor more explanation on the dates, see [issue #4](https://github.com/nandorojo/swr-firestore/issues/4).\n\n### Paginate a collection:\n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set, // set a firestore document\n  update, // update a firestore document\n  add, // add a firestore document to a collection\n  fuego // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, deleteDocument, error, isValidating, mutate } = useDocument(path, options)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n- `deleteDocument()`: Extends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(path, query, options)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando']\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [['name', '==', 'Fernando'], ['isHungry', '==', true]]\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando']\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name'\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc']\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc']\n  ]\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n\n- You can call this when you want to edit your document.\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n- The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`:\n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n## `add(path, data)`:\n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n- Use this **instead** of `firebase.firestore().collection('users').add(data)`\n\n## `deleteDocument(path, ignoreLocalMutations = false)`\n\nExtends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.  \n  - Second argument is a boolean that defaults to false. If `true`, it will not update the local cache, and instead only send delete to Firestore.\n\n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n\n- `db`: the current firestore collection instance\n- `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.10.1-alpha.1","dist":{"shasum":"670fb799e9f299ed1f2349dd0193040f194c2268","integrity":"sha512-QodTCUamd+bCpMpRNZFcv1RBaETNg7OOM2mJ1pMDGaClAhZ3R9ocZIoV4HBq5BsH8kg4/Uyg9hxB2inyOAantw==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.10.1-alpha.1.tgz","fileCount":111,"unpackedSize":258165,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe+1xoCRA9TVsSAnZWagAAVgMP/1FOjsgp1TZi1DXcGUT8\niYGMzCbjEwFwIhHXJrXJetcLpWSjiiotsSS2aLEUJ1Oaf7AmPhmtEJ5k2Rfr\nchcSg/Z3b3JuEcOUGJg+QL6wJpEaa1NQuNTh6kZNQLV3tW98Qi1NEaNCm1vH\nf9BAZ+6aZU9zfovSP91xQKIqUwG4VmP081fVUO1IN9Ehav91kD4I+z+IjUnp\nFpQe60NugVobhOgZ0+EwxqA9SIdut4nVYGpVkMWyn1Ndb3/KiT1swjzQUDfp\nODnB9sgW3E+tscNgoqo3L4EmVRUS0KnzS0YSduVWOmrjFNL4/2QYO8kpyEYW\njtuDn7/DiAZVDfAooyGOuD6EqnpUT+Au1/lIZhi2wMcwkSyjcMa0uXqymTcC\ndW9TO53zyweszD5PqtZOA7i4y1tYSRagYcPVm8inDnQm7eiqMYmihAcyJIg1\npN3bCyXxunbw4Y4RY/JZKBy1JzZvOz5OfMnhhm7IXjZKNPeG8lL8oBi5YbJ+\n3IvrMt3mkMe7DKiPyNXmd5ohvZgDdf3uLoJlX5a+5LyZPt1c3OtZwxTviPgx\nwaIhKh98HMbaYiq99wlqBew3GKkcUvEsNGiyuIVUgh8baunt/mU7TPVF9kFH\nKrNZyfZ78CELeqmYtfKW974Yhr2fnPEhw1Dmx8I9Ydxkrzo429DSudw94FDl\nuT4U\r\n=eIiG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDdtknT0RkGu0aN4zPdyJR/j2/8oIzQthO1PMe/i3I9AgIgaghoUs57PZo01mxvvToPU5ALKcqVYxkC5rW/Zv1h5ro="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.10.1-alpha.1_1593531496568_0.34662752793795604"},"_hasShrinkwrap":false},"0.10.2":{"name":"@nandorojo/swr-firestore","version":"0.10.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"@expo/results":"^1.0.0","lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.10.2","dist":{"shasum":"3ac2b03bb2edcb0b21a6d959371ea99aea3f6133","integrity":"sha512-V6VDdT/Pmtt+lrMUECtmWw345xniW+i8EaNQsqm8DwB2hms3BWoQPe1Ou2TIF21ed7EVJlTypxVJvZUIA4Pj8Q==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.10.2.tgz","fileCount":117,"unpackedSize":271280,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfN/MqCRA9TVsSAnZWagAASncQAItfTf/bXl19RyTR7kzf\nuWWXspCKPo4gJxkKw/A406FXT8fK7xxfoKFftXA6HiVQKICLdAhKU1xhWoU5\nzumB0CnIgU+OHK1g+gaQYXeLvtOTClZ0doXTiL6SvS9/ZGkmBgBtR077r/HM\nRaYV/n07IbpxqiyKaU5ZWlh1XT1VTXW+i14qIRGAH4Gp3K5Y2Qe6EK1nLw3+\n1K1yK+Jkx7mJ+cUm1ssGPsRd6ZW02dtiNYwIMH9H07AzHyfCvKVrzHo9t618\nQoFDGSYjl71iiMg45KMQO4mKhB+Bzy/UlIxCJi9iqAN/4YHy/Ll4quhCBFmr\nft2veDvKXsDwtveraz4qZuSd6hvhErHXCAZOxUe8mKzXd3pm+71320/MDxQ6\nfZU2xrURbkX7Eeu11DaIuNDmMl5i6z/XeBkfUbnqKxlaiXo8cH4skJGhw/68\n1YffpejE/iIEEgmsTtx8b9SdBy2IKJKLz0JDxBzzZIdbiDqVvEva7RNuLIGr\nVi50CSQQ58qgiBwLT4VgxuZUZ7tc+4UEhBPxqCyeZOjIFoxoehcNjd0oz6ER\nNQH4kB/RUT7rAbEeNvOSqlrHg/6weU9MatRJkktZI0UOqphpw39grDlk8OPV\nZJEKuwhNZdyLHG+inWR6WRCquE4LTpKGRi25uUuuZWl1al9hZPm5DitWikg9\nIUQj\r\n=Rv6k\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD/4Hbw+mRWWjhLl/FAf864txy+vnS+mxZPPFMT2UCkCgIhAINNj6DqDaoZmTDBR9rXHP9o3kTybyljeHFmQc9bXgfe"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.10.2_1597502249834_0.7035714689027319"},"_hasShrinkwrap":false},"0.11.0":{"name":"@nandorojo/swr-firestore","version":"0.11.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Offline mode with Expo [(without detaching!)](https://github.com/nandorojo/expo-firestore-offline-persistence/blob/master/README.md#usage-with-nandorojoswr-firestore)\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n- Server-side rendering (SSR or SSG) with Next.js [(example)](https://github.com/nandorojo/swr-firestore/issues/17)\n- Automatic date parsing (no more `.toDate()`)\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\nUnder the hood, this step initializes firebase for you. No need to call `firebase.initializeApp`.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return data.map((user) => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [['artist', '==', 'Drake'], ['year', '==', '2020']]\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake']\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020'\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true\n  })\n}\n```\n\n### Use dynamic fields in a request:\n\nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Parse date fields in your documents\n\nMagically turn any Firestore timestamps into JS date objects! No more `.toDate()`.\n\nImagine your `user` document schema looks like this:\n\n```typescript\ntype User = {\n  name: string\n  lastUpdated: {\n    date: Date\n  }\n  createdAt: Date\n}\n```\n\nIn order to turn `createdAt` and `lastUpdated.date` into JS objects, just use the `parseDates` field:\n\n**In a document query**\n\n```typescript\nconst { data } = useDocument<User>('user/fernando', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nlet createdAt: Date\nif (data) {\n  // ✅ all good! it's a JS Date now.\n  createdAt = data.createdAt\n}\n```\n\n`data.createdAt` and `data.lastUpdated.date` are both JS dates now!\n\n**In a collection query**\n\n```typescript\nconst { data } = useCollection<User>('user', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nif (data) {\n  data.forEach(document => {\n    document.createdAt // JS date!\n  })\n}\n\n```\n\nFor more explanation on the dates, see [issue #4](https://github.com/nandorojo/swr-firestore/issues/4).\n\n### Paginate a collection:\n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set, // set a firestore document\n  update, // update a firestore document\n  add, // add a firestore document to a collection\n  fuego // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, deleteDocument, error, isValidating, mutate } = useDocument(path, options)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n- `deleteDocument()`: Extends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(path, query, options)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando']\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [['name', '==', 'Fernando'], ['isHungry', '==', true]]\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando']\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name'\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc']\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc']\n  ]\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n\n- You can call this when you want to edit your document.\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n- The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`:\n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n## `add(path, data)`:\n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n- Use this **instead** of `firebase.firestore().collection('users').add(data)`\n\n## `deleteDocument(path, ignoreLocalMutations = false)`\n\nExtends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.  \n  - Second argument is a boolean that defaults to false. If `true`, it will not update the local cache, and instead only send delete to Firestore.\n\n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n\n- `db`: the current firestore collection instance\n- `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.11.0","dist":{"shasum":"c56e8b5abcb58db432ecc8faa290a46acbc9f234","integrity":"sha512-5OGX9ehsMmHCp7bIxqBZ+0skhzYr+JIonK+1kM21brIgcVm9SkoBVSwUc0HqgvzlSCaYhawNqRdDJPhjdlPoDA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.11.0.tgz","fileCount":117,"unpackedSize":282796,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfR9bbCRA9TVsSAnZWagAArZ8QAIrUUfWQbFmF3scegczS\n+SfnsBqFJLgeHIwUaebVzF72Vwoj1DRn9PC00tbQfWEjAlVsWCtvpPKcd/xU\nP+CTHGeFyEc6NLTBIZbjbL/pUbaYvOcu5NYnVdTM5/HrJJiCc3K2pkBh9AyX\nmTzLK2Tb4sQ7rSH3BZQLgUWLcsvTXPO5Zxn2Yx50cPjrcjM+0V4kFDensHZy\n5jQ2EeKS55ZP3zAfb9ky9dnOP05rEt4HW00ctItxfaAeolSStPatW2MEfGtw\nTDLRvFENzGiUaZptHzArsHIm9VrxaP8P7XBc5P190YPQAmu1777+t6+qVWjW\nioriyvjPW5XfuICOk4jm1WsfMSZmmDHee2dOsaktuIMo4woXe9zLtQgKAUHX\nygiFem32JvZPWucsDjT0UVlaoXM/ZjVKhM/75YTXy8WbX04x8QGS9VPjk6QQ\nYLW0GVsC22KIZ2+y4bFLx/0ST3shlqnUBS5IK/iykBRdOjqfXNrlbV3IUM9h\n5UtQn+nUcsTL2S5TCzf9gFPMpCZ1WhWdqUOiuGPOvi5Y413tK++nYzoLFkIA\n/P37llmhcdgUw8hZJw7tmgcXLnGUsvTrKd7XbiQ7nHqk+bbXqJbYqYX+fGCL\nfY/34C/4mExbCkxGmx9BwTjiDX+gcnRM9ATge6RqBZyszMmDEW6mjXHHhYmy\niR6+\r\n=fZT/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD7nuz4WzHq0nHON7e9R51RHE6fbU9J1c4GdS0jdfHZDgIgCxx+V0ERPJjvnSUpZ3PrU/LPCUHJq3yeN67MW9tjVQw="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.11.0_1598543579135_0.013509894732136818"},"_hasShrinkwrap":false},"0.11.1":{"name":"@nandorojo/swr-firestore","version":"0.11.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Offline mode with Expo [(without detaching!)](https://github.com/nandorojo/expo-firestore-offline-persistence/blob/master/README.md#usage-with-nandorojoswr-firestore)\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n- Server-side rendering (SSR or SSG) with Next.js [(example)](https://github.com/nandorojo/swr-firestore/issues/17)\n- Automatic date parsing (no more `.toDate()`)\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\nUnder the hood, this step initializes firebase for you. No need to call `firebase.initializeApp`.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return data.map((user) => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [['artist', '==', 'Drake'], ['year', '==', '2020']]\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake']\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020'\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true\n  })\n}\n```\n\n### Use dynamic fields in a request:\n\nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Parse date fields in your documents\n\nMagically turn any Firestore timestamps into JS date objects! No more `.toDate()`.\n\nImagine your `user` document schema looks like this:\n\n```typescript\ntype User = {\n  name: string\n  lastUpdated: {\n    date: Date\n  }\n  createdAt: Date\n}\n```\n\nIn order to turn `createdAt` and `lastUpdated.date` into JS objects, just use the `parseDates` field:\n\n**In a document query**\n\n```typescript\nconst { data } = useDocument<User>('user/fernando', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nlet createdAt: Date\nif (data) {\n  // ✅ all good! it's a JS Date now.\n  createdAt = data.createdAt\n}\n```\n\n`data.createdAt` and `data.lastUpdated.date` are both JS dates now!\n\n**In a collection query**\n\n```typescript\nconst { data } = useCollection<User>('user', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nif (data) {\n  data.forEach(document => {\n    document.createdAt // JS date!\n  })\n}\n\n```\n\nFor more explanation on the dates, see [issue #4](https://github.com/nandorojo/swr-firestore/issues/4).\n\n### Paginate a collection:\n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set, // set a firestore document\n  update, // update a firestore document\n  add, // add a firestore document to a collection\n  fuego // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, deleteDocument, error, isValidating, mutate } = useDocument(path, options)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n- `deleteDocument()`: Extends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(path, query, options)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando']\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [['name', '==', 'Fernando'], ['isHungry', '==', true]]\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando']\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name'\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc']\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc']\n  ]\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n\n- You can call this when you want to edit your document.\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n- The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`:\n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n## `add(path, data)`:\n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n- Use this **instead** of `firebase.firestore().collection('users').add(data)`\n\n## `deleteDocument(path, ignoreLocalMutations = false)`\n\nExtends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.  \n  - Second argument is a boolean that defaults to false. If `true`, it will not update the local cache, and instead only send delete to Firestore.\n\n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n\n- `db`: the current firestore collection instance\n- `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.11.1","dist":{"shasum":"80a5fcc9b1e0dea47040169524d4b8569b79467e","integrity":"sha512-y+smgc6QP+bkPFJlryncqHoU48fNiqbpKoXGtRlR+WEJecAcd1D+6t/ZamJVTbD21IuXe6a6+GyVCmq+4NIEAA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.11.1.tgz","fileCount":117,"unpackedSize":282965,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfWl9UCRA9TVsSAnZWagAAh3EP/0t8ZJnfLXzZ86FH18Ps\n40nwER9xpaML2vLXKornO4h7mblIvkwdPt1Wrup/u4qJUNBkivUUzTF90F8b\naWtwzyr7o0GzPXrx8JwtS0XjEEClwE/wjwSh0qN0VUwz4b+xdact4AyJsGek\nm0I8rAOUjg5wMRufE8tOX6bB1pF2ebzyXkVh8GBVL5pTcLVwxJ5ek6TPsfa/\nDB8UkHllkNKOMSORlTZ4j8pKJtyZxpOJ776VkGTnMXt0HDE6dFtYhGFpZa5D\nInN0HXFoEGP3hqiZtskmvjR+AD9gsmQ4Xn0wH6OGtrI+gaD0Zz670ysiJjiZ\nNxvN5Ehu1vhA0kI6JqMjcgwtIhW3YRZU7Rdbph1ie2ILhcYMk+++GvhpE9ya\nGX9wBz+bTBKOJMfxWtkseeK/qBXqYyYZv4469IVkPPV2hdaJXgjEPDYcUUWe\nYrZXbtBMH0pXtnLS4RkQ0tUA8hPyHbFrxxvaEDYheGB/ZYNQrBZ9bcdGZHGL\nnvSmqazN1sguokIzrXcEIVA56XoUzfgtfWzNFJ5F8RlO0mrq28ULl+yGSu5J\nT+7XT/FDM5hZiZhZHboNoBctJGCu/rSAivFL9PlIFhU1RIPy07P4Yq1hHrM9\nPxc5/BT3cA0/PQe6Lwfzq/if+qiAUrznBPeBwlPkrCXHPeNaY0NRvJhXK16A\nGZLF\r\n=EeGS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFgPLdCpPNTgOOKiCgrVf+NAoj8jffbL0LWmrOnWS7VAAiEA3hjylX6tJozDQdECgNlJTEH9FyOxtSDvbmRzPDqv9ZQ="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.11.1_1599758163555_0.6019924066025863"},"_hasShrinkwrap":false},"0.11.2":{"name":"@nandorojo/swr-firestore","version":"0.11.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.11.2","dist":{"shasum":"2b2a1d77b3b70cc72db60221f89b61d5b08e71db","integrity":"sha512-QbMO6p2O3ndtIX/rI5qbt5C5vhhlNFXjvEm6qfrr8ufucL6Fy66wJhyIImFyHnXVt+bS6V/mMOJCYUbo5SgyWw==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.11.2.tgz","fileCount":117,"unpackedSize":282923,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfWmE9CRA9TVsSAnZWagAAgckP/jb8B77FRT5bZUL6FUgt\nRZi6jrmgw4Igmyu6snJ5dNNp9/Z1isLjofxqNd49r5kzBMr9Id1LjwVJRvsC\nWjVQgOxlN5yeUMmU6j34R7+PNjtNK0caSU2RlLKCciX2D8RMUrWZ6bYoWISi\nZmgvay42P4ZbTBYAtDHkcVz6pMivdwwdPL2jsJzBNkXiBvq8BY6+iMvn2k94\nFyKoKgwyFIFpzy/JTwd1MR7b4A2cEYAmjvYypA+69/NhNwT9s0ADuCuW94p/\n1kJaFnEJJ+dZWxAVDIRUjVVNpnyEuesXkny7CnQPjS2oRJ+ooQVAS3nhWKJh\n4cfni+QSBBQxbtBXB01ZTCp7/6c3Le/2PubDsAvGV13Z7QBovr5x3a3FubnV\nPiqNlmroTaPv3bO8JtESjVlfz1cXduIEDZR9SyaSfw8I9QXDgy/OsD7U1ZPr\n2A3ColZ2k0TyGXHWHwJPdWN/lGL+EGaE2Gv7OPxzVKKmr3+OjVyMQ6iRdDBH\nnNoKlbfaIBM8lIq81SASIA5lR7GhZijlH6bgJg/mnEl012mjlJ0DDjN0ZSlp\nHTiXChLvb3Ds+Zg7hfuWYUFH02zSUa+GRsY6DBWI9gvF0/4NKxnjnOPKfMeh\nTD8qXh/JUCW9ST8loDTjH2LT+uYBeAZSW+ZU9C43lm2IWiHVbWn3HDCanbpf\nuPho\r\n=3VN3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBND+2OZ1GazYBVeSQdKNhJ4ga/NdlQxT5V2aSpwKuJUAiEAs+M6LDAbzOvghn5VBXHkydIl6F0WOCU4GlZInUulhqg="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.11.2_1599758653024_0.9332776555175233"},"_hasShrinkwrap":false},"0.12.0":{"name":"@nandorojo/swr-firestore","version":"0.12.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Offline mode with Expo [(without detaching!)](https://github.com/nandorojo/expo-firestore-offline-persistence/blob/master/README.md#usage-with-nandorojoswr-firestore)\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n- Server-side rendering (SSR or SSG) with Next.js [(example)](https://github.com/nandorojo/swr-firestore/issues/17)\n- Automatic date parsing (no more `.toDate()`)\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\nUnder the hood, this step initializes firebase for you. No need to call `firebase.initializeApp`.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return data.map((user) => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [['artist', '==', 'Drake'], ['year', '==', '2020']]\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake']\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020'\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true\n  })\n}\n```\n\n### Use dynamic fields in a request:\n\nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Parse date fields in your documents\n\nMagically turn any Firestore timestamps into JS date objects! No more `.toDate()`.\n\nImagine your `user` document schema looks like this:\n\n```typescript\ntype User = {\n  name: string\n  lastUpdated: {\n    date: Date\n  }\n  createdAt: Date\n}\n```\n\nIn order to turn `createdAt` and `lastUpdated.date` into JS objects, just use the `parseDates` field:\n\n**In a document query**\n\n```typescript\nconst { data } = useDocument<User>('user/fernando', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nlet createdAt: Date\nif (data) {\n  // ✅ all good! it's a JS Date now.\n  createdAt = data.createdAt\n}\n```\n\n`data.createdAt` and `data.lastUpdated.date` are both JS dates now!\n\n**In a collection query**\n\n```typescript\nconst { data } = useCollection<User>('user', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nif (data) {\n  data.forEach(document => {\n    document.createdAt // JS date!\n  })\n}\n\n```\n\nFor more explanation on the dates, see [issue #4](https://github.com/nandorojo/swr-firestore/issues/4).\n\n### Paginate a collection:\n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set, // set a firestore document\n  update, // update a firestore document\n  fuego // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, deleteDocument, error, isValidating, mutate } = useDocument(path, options)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n- `deleteDocument()`: Extends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(path, query, options)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando']\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [['name', '==', 'Fernando'], ['isHungry', '==', true]]\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando']\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name'\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc']\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc']\n  ]\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n\n- You can call this when you want to edit your document.\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n- The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`:\n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n<!--\n## `add(path, data)`:\n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n- Use this **instead** of `firebase.firestore().collection('users').add(data)`\n-->\n\n## `deleteDocument(path, ignoreLocalMutations = false)`\n\nExtends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.  \n  - Second argument is a boolean that defaults to false. If `true`, it will not update the local cache, and instead only send delete to Firestore.\n\n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n\n- `db`: the current firestore collection instance\n- `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.12.0","dist":{"shasum":"732a5428a387521488ca86a291a846e7624e3f4d","integrity":"sha512-+hcseYT2d6iTH0X23qzXOm8XGsAvRIp4mPdErV5QHjTkqNLg4ty4IN9dkBYJIUNtsME9KLlVzDshs5SHGBqvJA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.12.0.tgz","fileCount":117,"unpackedSize":277836,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfWmy/CRA9TVsSAnZWagAAlhAQAJnQ04CyUBSIO0ckFRmD\nt3oSWPWz9TtUt08tCTbFJFraSs8iaSVE6y+T66Vs//g7WhaP9/Sr4vIiFyJV\n2uEfKqb29bRS2gk/FJOVRTJCFXu/+h7p4Zst6qzdpwUtp1MyQyPrAIy0iZpN\naRT5KK9dwkrzndPW8aaaPIME1oyB3v0U6z3kSRuGr9XIOolnsgqS8LanayB+\nMThmnnCtWlMr+l+jFCPbUA0mLBtB4Hmj0g4+oeXkUjFHWBaQCbVvUXQaOrG7\nEoP7dFB8Lk2XkgMlgy/4Qy95Y5KlvjFcVUS/HZz5wj5rXRvF+Emr+d0WbfC0\nYny1/Ryr7NTuwxkMJ2tDNozAsJAM6KwbkaD0RstShvp4ClF2wZCwf9WKJ8Rw\nGU9EcdnSAMHexBBbRCWhOSgT5tlMHej7rMsOFntZ+X9nTC0EJ9aU9e4W8PVS\nZFhj7bpQywiJRy5TL5sSShKxvvQ782RAw3rkzxHaaach5lJzbMrknaVzr99P\nupZfG05Nr5O8yGuzKhkJ0MIOotznkpfiwrUug5pswwjFi/+Xbjy+SJVeO3hO\n7edNsrychlHFNQahUx9odLEay092uN7ejzAXo2x9pceUeIOjnwkaIQCWgc/g\njBdzjOclKQ1vFvw9a37Fxf3N74cldnn/RNqPCcvAISPxbNycqzfq1+scD7Su\n/9cT\r\n=j2Ci\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDCDpsj2B5E0+3p+aHAmLej+dygZlBEtqrT6zFmOWM75QIgYkQfN8WoknZL7fjCLXpsvdrkt/A5iQIhw1iGZIhdB6A="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.12.0_1599761598671_0.8866658050337455"},"_hasShrinkwrap":false},"0.12.1":{"name":"@nandorojo/swr-firestore","version":"0.12.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Offline mode with Expo [(without detaching!)](https://github.com/nandorojo/expo-firestore-offline-persistence/blob/master/README.md#usage-with-nandorojoswr-firestore)\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n- Server-side rendering (SSR or SSG) with Next.js [(example)](https://github.com/nandorojo/swr-firestore/issues/17)\n- Automatic date parsing (no more `.toDate()`)\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\nUnder the hood, this step initializes firebase for you. No need to call `firebase.initializeApp`.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return data.map((user) => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [['artist', '==', 'Drake'], ['year', '==', '2020']]\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake']\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020'\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true\n  })\n}\n```\n\n### Use dynamic fields in a request:\n\nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Parse date fields in your documents\n\nMagically turn any Firestore timestamps into JS date objects! No more `.toDate()`.\n\nImagine your `user` document schema looks like this:\n\n```typescript\ntype User = {\n  name: string\n  lastUpdated: {\n    date: Date\n  }\n  createdAt: Date\n}\n```\n\nIn order to turn `createdAt` and `lastUpdated.date` into JS objects, just use the `parseDates` field:\n\n**In a document query**\n\n```typescript\nconst { data } = useDocument<User>('user/fernando', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nlet createdAt: Date\nif (data) {\n  // ✅ all good! it's a JS Date now.\n  createdAt = data.createdAt\n}\n```\n\n`data.createdAt` and `data.lastUpdated.date` are both JS dates now!\n\n**In a collection query**\n\n```typescript\nconst { data } = useCollection<User>('user', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nif (data) {\n  data.forEach(document => {\n    document.createdAt // JS date!\n  })\n}\n\n```\n\nFor more explanation on the dates, see [issue #4](https://github.com/nandorojo/swr-firestore/issues/4).\n\n### Paginate a collection:\n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set, // set a firestore document\n  update, // update a firestore document\n  fuego // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, deleteDocument, error, isValidating, mutate } = useDocument(path, options)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n- `deleteDocument()`: Extends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(path, query, options)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando']\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [['name', '==', 'Fernando'], ['isHungry', '==', true]]\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando']\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name'\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc']\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc']\n  ]\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n\n- You can call this when you want to edit your document.\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n- The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`:\n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n<!--\n## `add(path, data)`:\n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n- Use this **instead** of `firebase.firestore().collection('users').add(data)`\n-->\n\n## `deleteDocument(path, ignoreLocalMutations = false)`\n\nExtends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.  \n  - Second argument is a boolean that defaults to false. If `true`, it will not update the local cache, and instead only send delete to Firestore.\n\n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n\n- `db`: the current firestore collection instance\n- `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.12.1","dist":{"shasum":"799961b36f4047a1d09d1325cc666de2d5958eee","integrity":"sha512-6FNq6yq4x78wLBofaZeJR41aBMU86hBkD/TNqRI5p91LFlldbH3tyCwsBa3nVomG9yspRawW/m5JH7CsL6vTaA==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.12.1.tgz","fileCount":117,"unpackedSize":278585,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfWmz/CRA9TVsSAnZWagAAlkEP/iDHn5LYMGe7NLF6GSZQ\nqiDK+XvRB9geqXdiq0ekOvpcSOgUtngwiXAeU+Naf4P9ciwPMP34Rb6WysrY\nXL8Grn3Cql0uv7nWNu7QNwBxzKiCpbm6rVha4ywnEk449U/pLZgniALRuubu\nCOqCtCOHOHK7HFr2kWSA/qAsIPDqoXuCicZKzHhzhPLXhL2X0jYO6ukOO9So\nrmSNB6csdeUPcCa7fGq/9V9lVW/MIT5AUUztmuzYW07f+/zv/IBLBzCvn+EI\nikLPR7OYceyZGWb/NZidn6Mf4DJX9uiok/SfHHyf8y2UJRKzeHwlElRcL6JQ\nRBV0QTaWazDDcVUYn9I4NzLScsDW+Zyee+F2pqfvFp0P+e2gvLhkQZpjXgph\nlfdncgSAEmfuJz5BxpZDKw69FYAvSYFMSlAFUQKN2i5y+7K6U4v7qI29c0J/\nv8on0IG9VAt+ski2HN9ijkpDiFWCbIJIx+dCQOWQhYevqgDIGDDGhf8Cbw04\nNZDJk9DXzLCyD8T6SiK1Nr+Q1TyHzzYSk85ZJIdrtT0xy+/IJ6PerILl4XH8\nzbjy4CmRsjFwqqIEzF0YlEFuTJKf8ltjQ3+cwswqUh6YxZf8uygsgnxgpAV9\nfQwYWKptmi1Gmg/4Ra6Wb4Rl0lpul8CRgTUblwIhYF4EZQOD0qV+y1PDfEHB\nyJCr\r\n=5RDG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDNbFZ65r2JyzUNyorwVRox9yQEYr3PcRoGd5DmerP6PAIgcuVx3MBRfQhhKi1HxNyaZ/qRGcQJsBzJVvtr5q7oyrE="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.12.1_1599761662985_0.6362831262996516"},"_hasShrinkwrap":false},"0.12.2":{"name":"@nandorojo/swr-firestore","version":"0.12.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Offline mode with Expo [(without detaching!)](https://github.com/nandorojo/expo-firestore-offline-persistence/blob/master/README.md#usage-with-nandorojoswr-firestore)\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n- Server-side rendering (SSR or SSG) with Next.js [(example)](https://github.com/nandorojo/swr-firestore/issues/17)\n- Automatic date parsing (no more `.toDate()`)\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\nUnder the hood, this step initializes firebase for you. No need to call `firebase.initializeApp`.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return data.map((user) => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [['artist', '==', 'Drake'], ['year', '==', '2020']]\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake']\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020'\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true\n  })\n}\n```\n\n### Use dynamic fields in a request:\n\nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Parse date fields in your documents\n\nMagically turn any Firestore timestamps into JS date objects! No more `.toDate()`.\n\nImagine your `user` document schema looks like this:\n\n```typescript\ntype User = {\n  name: string\n  lastUpdated: {\n    date: Date\n  }\n  createdAt: Date\n}\n```\n\nIn order to turn `createdAt` and `lastUpdated.date` into JS objects, just use the `parseDates` field:\n\n**In a document query**\n\n```typescript\nconst { data } = useDocument<User>('user/fernando', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nlet createdAt: Date\nif (data) {\n  // ✅ all good! it's a JS Date now.\n  createdAt = data.createdAt\n}\n```\n\n`data.createdAt` and `data.lastUpdated.date` are both JS dates now!\n\n**In a collection query**\n\n```typescript\nconst { data } = useCollection<User>('user', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nif (data) {\n  data.forEach(document => {\n    document.createdAt // JS date!\n  })\n}\n\n```\n\nFor more explanation on the dates, see [issue #4](https://github.com/nandorojo/swr-firestore/issues/4).\n\n### Paginate a collection:\n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set, // set a firestore document\n  update, // update a firestore document\n  fuego // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, deleteDocument, error, isValidating, mutate } = useDocument(path, options)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n- `deleteDocument()`: Extends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(path, query, options)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando']\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [['name', '==', 'Fernando'], ['isHungry', '==', true]]\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando']\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name'\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc']\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc']\n  ]\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n\n- You can call this when you want to edit your document.\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n- The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`:\n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n<!--\n## `add(path, data)`:\n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n- Use this **instead** of `firebase.firestore().collection('users').add(data)`\n-->\n\n## `deleteDocument(path, ignoreLocalMutations = false)`\n\nExtends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.  \n  - Second argument is a boolean that defaults to false. If `true`, it will not update the local cache, and instead only send delete to Firestore.\n\n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n\n- `db`: the current firestore collection instance\n- `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.12.2","dist":{"shasum":"02c719acd768c7a463c5069db816694a1e4015a1","integrity":"sha512-JWF8I6Bld7W8T2bPxiF+krZeF7izqfU2q6BHCIvQPxHKlk387zMrggUrJ0AjsaBIbgz879GVDnuTWTYg2wY/Lg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.12.2.tgz","fileCount":117,"unpackedSize":281035,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfWnMdCRA9TVsSAnZWagAAEUAP/2HDqKANJQ/es7dF/vd5\nI6724aBrN6H21sF/kKvc95u/N8EDRpF+l35e+E97mYywySJ+WgQkqXH1m0ox\nrV8+C8tQahsdGvuLsCIwSIbeieuDQbBZYVXdkUytuvU7vCKJJEoX5FpY2mCI\nnveFwHVsbMCXSoO+/IO0nBclgMDEWNxdYxikGdnyyRCy+TlsuB8vOeUrpctB\ntwhKMctlOYCihfSZ/kdgp1zBCo8hGxgAPStkW0mTMPVfbtn8OTSy7xtFr9bz\nm+a/XQHnvFxQyWTxMV6YPlpulCQYfpxNX4D6VyZeEgd1R+A8G2SzprhFajeR\nvXAecgTj5CTHoOt0B1hOAx8W0D006p6PYDbeN7xR0iPv0kI4+sqc+Y2bcfDF\nH7w40JZFDq2gHzcFH7rD9mBPU35lQgNEolqa1vgSslWNsAWEC7b/+W69fJWp\nsVVf4df2ccoUw5aGlbeeToxrUfXAFmb/rrVC5Zmj+K+Gk4y6XpRrGcuNHuLc\nVLuROW6JWDD5cvJ2quR4QBKzFJL+NDCAaCzLU6k7kT4+gFk2pSQ4m77FARe2\n7VaGjgISRcxxdWSgshG77CUXaOII2flpheS3kcDTIj70PzSFStB3qhMOIJJe\nFVPizK+py9Phq0Nht3PjNJVmyW8iaOq0Z76cAgM9Plnd/RpIpxRiEQ/SGiZL\nM8MM\r\n=0CqW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDrqWbsjCIQYGoBp4gA4CtrelF2q5MyC3PXoReOWQz99wIgJp+RfzjQDgHutxSyYN/dyrQeUjbrORNlo4cyRMTtNc0="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.12.2_1599763228725_0.37234585436580403"},"_hasShrinkwrap":false},"0.13.0":{"name":"@nandorojo/swr-firestore","version":"0.13.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Offline mode with Expo [(without detaching!)](https://github.com/nandorojo/expo-firestore-offline-persistence/blob/master/README.md#usage-with-nandorojoswr-firestore)\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n- Server-side rendering (SSR or SSG) with Next.js [(example)](https://github.com/nandorojo/swr-firestore/issues/17)\n- Automatic date parsing (no more `.toDate()`)\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return <FuegoProvider fuego={fuego}>{/* Your app code here! */}</FuegoProvider>\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\nUnder the hood, this step initializes firebase for you. No need to call `firebase.initializeApp`.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, { listen: true })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return data.map((user) => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [['artist', '==', 'Drake'], ['year', '==', '2020']]\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake']\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020'\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true\n  })\n}\n```\n\n### Use dynamic fields in a request:\n\nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid]\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(user?.favoriteSong ? `songs/${user.favoriteSong}` : null)\n```\n\n### Parse date fields in your documents\n\nMagically turn any Firestore timestamps into JS date objects! No more `.toDate()`.\n\nImagine your `user` document schema looks like this:\n\n```typescript\ntype User = {\n  name: string\n  lastUpdated: {\n    date: Date\n  }\n  createdAt: Date\n}\n```\n\nIn order to turn `createdAt` and `lastUpdated.date` into JS objects, just use the `parseDates` field:\n\n**In a document query**\n\n```typescript\nconst { data } = useDocument<User>('user/fernando', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nlet createdAt: Date\nif (data) {\n  // ✅ all good! it's a JS Date now.\n  createdAt = data.createdAt\n}\n```\n\n`data.createdAt` and `data.lastUpdated.date` are both JS dates now!\n\n**In a collection query**\n\n```typescript\nconst { data } = useCollection<User>('user', {\n  parseDates: ['createdAt', 'lastUpdated.date']\n})\n\nif (data) {\n  data.forEach(document => {\n    document.createdAt // JS date!\n  })\n}\n\n```\n\nFor more explanation on the dates, see [issue #4](https://github.com/nandorojo/swr-firestore/issues/4).\n\n### Paginate a collection:\n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from \"react\";\nimport { fuego, useCollection } from \"@nandorojo/swr-firestore\";\n\nconst collection = \"dump\";\nconst limit = 1;\nconst orderBy = \"text\";\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  );\n\n  const paginate = async () => {\n    if (!data?.length) return;\n\n    const ref = fuego.db.collection(collection);\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get();\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then((d) => {\n        const docs = [];\n        d.docs.forEach((doc) => docs.push({ ...doc.data(), id: doc.id }));\n        return docs;\n      });\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate((state) => [...state, ...moreDocs], false);\n  };\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  );\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set, // set a firestore document\n  update, // update a firestore document\n  fuego // get the firebase instance used by this lib\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst { data, set, update, deleteDocument, error, isValidating, mutate } = useDocument(path, options)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n- `deleteDocument()`: Extends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(path, query, options)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando']\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [['name', '==', 'Fernando'], ['isHungry', '==', true]]\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando']\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name'\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc']\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc']\n  ]\n})\n```\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n\n- You can call this when you want to edit your document.\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n- The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`:\n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n<!--\n## `add(path, data)`:\n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n- Use this **instead** of `firebase.firestore().collection('users').add(data)`\n-->\n\n## `deleteDocument(path, ignoreLocalMutations = false)`\n\nExtends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.  \n  - Second argument is a boolean that defaults to false. If `true`, it will not update the local cache, and instead only send delete to Firestore.\n\n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n\n- `db`: the current firestore collection instance\n- `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.13.0","dist":{"shasum":"89250754b417fe1f12bbcc79b52a0db2dda2cf21","integrity":"sha512-xhE/+FwzUmuB11jZxFxdXz6S/9fTcRZ+QNZe9NkOdQx3QMLo6ewUQrtnGlAbswwfvYoSdABSFq5Q8L/syHLRgQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.13.0.tgz","fileCount":117,"unpackedSize":295920,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfWnXQCRA9TVsSAnZWagAA/LQP+wTMBmxY3NIOxSQcAN7I\nRw+e5p9wSkeq8iRDqP5PNtvjfESWtEx2xAwpLjzVQZatxgnBiTmAttL00VRJ\nsQ1b8FH85myEEIZ9165oJJhJv0jF8eJifzZe81OLY0E/tfw/2YuEXth/akvY\nDjqBN+vAXu6MCaJ2dbHW5SQM7GlA/2lBTn4FyFIn3mUumBXUn36rMpc358Sj\nrQU2W/jmiRuOt6zD2vobDYEJL887fAxoxS+2Qydt38tLfrW+T1RwF1cXaXXn\nCI0Fe4rGpAVsEE5FUjRsSqXCyePh/txbhvStdsJPFhuk9ZQeSUUwNWQw7TaR\ny67o9Mv3CUV5up9d8uiNfGjM+/cfcPwuHSmWnttYSBMRF+g1iLLaLaJF0jCS\nBBcMK1goK1dVaiXXfGmtv/EhFL+Xz5LbjdryOfXHYKKJgB0oIWLAIUSxp+n3\npHZPuw6axI4BHuHagyCmJEl/vD3uicZnb8yDc9rjwsTQoSFcwFw/BNTFGnBZ\nL8aJvL8gKg0zOgPbcC82tLKLnUI3wuTYMC+Uhs4a7Oi4lvCKQNyk9q0VbQ9u\ndEjcd/Tyq6Op7VoKwmtqE8KXhZnwPTnNUsF/Yhp9bAB9tBCtpBc62KMbPsHu\n0t+b0ukLqm2gmLI8ZiwBulxAdUI0rMH64+bmYb38wTNHSfPvZ8aMlfL9PBS1\nl1rN\r\n=8FgW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBuTFGvI+KXXg2bLD+Nwi00ZNDCCELxo7qaDrJ+7h+GKAiEA5zpjnUMeIblM1Ul/9fWWlI1uB44LHnl6nG3qZOKordk="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.13.0_1599763919885_0.30336087007091317"},"_hasShrinkwrap":false},"0.13.1":{"name":"@nandorojo/swr-firestore","version":"0.13.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"readmeFilename":"README.md","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Offline mode with Expo [(without detaching!)](https://github.com/nandorojo/expo-firestore-offline-persistence/blob/master/README.md#usage-with-nandorojoswr-firestore)\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n- Server-side rendering (SSR or SSG) with Next.js [(example)](https://github.com/nandorojo/swr-firestore/issues/17)\n- Automatic date parsing (no more `.toDate()`)\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Sponsor / Shameless plug: Doorman\n\nBesides maintaining this project, I'm currently working on [**Doorman**](https://doorman.cool) – Firebase phone authentication for React Native apps. It comes with fully-baked & customizable UI components, stateful auth hooks, and more.\n\nEven if you don't sign up for Doorman, the library (`react-doorman` or `react-native-doorman`) is free, and has many useful hooks for Firebase auth.\n\n- [Doorman Documentation](https://docs.doorman.cool)\n- [Doorman Website](https://doorman.cool)\n- [Doorman Sign Up](https://doorman.cool)\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>\n      <YourAppHere />\n    </FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\nUnder the hood, this step initializes firebase for you. No need to call `firebase.initializeApp`.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, {\n    listen: true,\n  })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return <Text>Name: {user.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n### Use dynamic fields in a request:\n\nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid],\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(\n  user?.favoriteSong ? `songs/${user.favoriteSong}` : null\n)\n```\n\n### Parse date fields in your documents\n\nMagically turn any Firestore timestamps into JS date objects! No more `.toDate()`.\n\nImagine your `user` document schema looks like this:\n\n```typescript\ntype User = {\n  name: string\n  lastUpdated: {\n    date: Date\n  }\n  createdAt: Date\n}\n```\n\nIn order to turn `createdAt` and `lastUpdated.date` into JS objects, just use the `parseDates` field:\n\n**In a document query**\n\n```typescript\nconst { data } = useDocument<User>('user/fernando', {\n  parseDates: ['createdAt', 'lastUpdated.date'],\n})\n\nlet createdAt: Date\nif (data) {\n  // ✅ all good! it's a JS Date now.\n  createdAt = data.createdAt\n}\n```\n\n`data.createdAt` and `data.lastUpdated.date` are both JS dates now!\n\n**In a collection query**\n\n```typescript\nconst { data } = useCollection<User>('user', {\n  parseDates: ['createdAt', 'lastUpdated.date'],\n})\n\nif (data) {\n  data.forEach(document => {\n    document.createdAt // JS date!\n  })\n}\n```\n\nFor more explanation on the dates, see [issue #4](https://github.com/nandorojo/swr-firestore/issues/4).\n\n### Paginate a collection:\n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from 'react'\nimport { fuego, useCollection } from '@nandorojo/swr-firestore'\n\nconst collection = 'dump'\nconst limit = 1\nconst orderBy = 'text'\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  )\n\n  const paginate = async () => {\n    if (!data?.length) return\n\n    const ref = fuego.db.collection(collection)\n\n    // get the last document in our current query\n    // ideally we could pass just a doc ID, but firestore requires the doc snapshot\n    const startAfterDocument = await ref.doc(data[data.length - 1].id).get()\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then(d => {\n        const docs = []\n        d.docs.forEach(doc => docs.push({ ...doc.data(), id: doc.id }))\n        return docs\n      })\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate(state => [...state, ...moreDocs], false)\n  }\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  )\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set, // set a firestore document\n  update, // update a firestore document\n  fuego, // get the firebase instance used by this lib\n  getCollection, // prefetch a collection, without being hooked into SWR or React\n  getDocument, // prefetch a document, without being hooked into SWR or React\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst {\n  data,\n  set,\n  update,\n  deleteDocument,\n  error,\n  isValidating,\n  mutate,\n} = useDocument(path, options)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n  - `ignoreFirestoreDocumentSnapshotField = true`. See elaboration below.\n  - `parseDates`: An array of string keys that correspond to dates in your document. [Example](#parse-date-fields-in-your-documents).\n\n##### `ignoreFirestoreDocumentSnapshotField`\n\nIf `true`, docs returned in `data` will not include the firestore `__snapshot` field. If `false`, it will include a `__snapshot` field. This lets you access the document snapshot, but makes the document not JSON serializable.\n\nBy default, it ignores the `__snapshot` field. This makes it easier for newcomers to use `JSON.stringify` without weird errors. You must explicitly set it to `false` to use it.\n\n```js\n// include the firestore document snapshots\nconst { data } = useDocument('users/fernando', {\n  ignoreFirestoreDocumentSnapshotField: false,\n})\n\nif (data) {\n  const path = data.__snapshot.ref.path\n}\n```\n\nThe `__snapshot` field is the exact snapshot returned by Firestore.\n\nSee Firestore's [snapshot docs](https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot) for more.\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n- `deleteDocument()`: Extends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n- `ignoreFirestoreDocumentSnapshotField = true`: If `true`, docs returned in `data` will not include the firestore `__snapshot` field. If `false`, it will include a `__snapshot` field. This lets you access the document snapshot, but makes the document not JSON serializable.\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n##### `ignoreFirestoreDocumentSnapshotField`\n\nIf `true`, docs returned in `data` will not include the firestore `__snapshot` field. If `false`, it will include a `__snapshot` field. This lets you access the document snapshot, but makes the document not JSON serializable.\n\nBy default, it ignores the `__snapshot` field. This makes it easier for newcomers to use `JSON.stringify` without weird errors. You must explicitly set it to `false` to use it.\n\n```js\n// include the firestore document snapshots\nconst { data } = useCollection('users', {\n  ignoreFirestoreDocumentSnapshotField: false,\n})\n\nif (data) {\n  data.forEach(document => {\n    const path = document?.__snapshot.ref.path\n  })\n}\n```\n\nThe `__snapshot` field is the exact snapshot returned by Firestore.\n\nSee Firestore's [snapshot docs](https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot) for more.\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n\n- You can call this when you want to edit your document.\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n- The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`:\n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n<!--\n## `add(path, data)`:\n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n- Use this **instead** of `firebase.firestore().collection('users').add(data)`\n-->\n\n## `deleteDocument(path, ignoreLocalMutations = false)`\n\nExtends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n\n- It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.\n- Second argument is a boolean that defaults to false. If `true`, it will not update the local cache, and instead only send delete to Firestore.\n\n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n\n- `db`: the current firestore collection instance\n- `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n## `getDocument(path, options?)`\n\nIf you don't want to use `useDocument` in a component, you can use this function outside of the React scope.\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n- `options`\n  - `ignoreFirestoreDocumentSnapshotField = true`. If `false`, it will return a `__snapshot` field too.\n  - `parseDates`: An array of string keys that correspond to dates in your document. [Example](#parse-date-fields-in-your-documents).\n\n### Returns\n\nA promise with the firestore doc and some useful fields. See the [useDocument](#useDocument) `data` return type for more info.\n\n## `getCollection(path, query?, options?)`\n\nIf you don't want to use `useCollection` in a component, you can use this function outside of the React scope.\n\n### Arguments\n\n- **`path` required** The unique collection path for your Firestore collection.\n  - `ignoreFirestoreDocumentSnapshotField = true`. If `false`, it will return a `__snapshot` field too.\n  - `parseDates`: An array of string keys that correspond to dates in your document. [Example](#parse-date-fields-in-your-documents).\n- `query` refer to the second argument of [`useCollection`](#useCollection).\n- `options`\n  - `ignoreFirestoreDocumentSnapshotField = true`. If `false`, it will return a `__snapshot` field too in each document.\n  - `parseDates`: An array of string keys that correspond to dates in your documents. [Example](#parse-date-fields-in-your-documents).\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.13.1","dist":{"shasum":"e6470881e9d4d69dcdd7248a9aee8eba7079d66f","integrity":"sha512-scMSGUh2jfHAe3v5tcYydAr4sp1LbBhloIhOGQjEXEqMjcx2MacbRVuHJkstnzIFnSVAAZ4QlHGsG9tSfswLbw==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.13.1.tgz","fileCount":117,"unpackedSize":302393,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfWn8xCRA9TVsSAnZWagAAtSEP/iwFQ9V0PTeR8qdol5pL\nMISvh9sSGgVibA+pxO/GG+SAIjhquurc1kenr4fnQ1tMpd8YPzNtfiKYSVJw\n+TFfDYxncjsIBFEqo+xt5BiyvUaBK02I112R92ETCXBpJ4U+AdCiR/kJ3D5u\nDSeIeng2CAgaCt18WvCr8lyvQ5VjijsCw+ovWk3CZYw9B4WK8ajzXRTPdS1m\nCFPoWzo/gzHUVVHlEWV59UGVyfNQ5VkoXEgvk+ufgJG3Zk5vcUf6GoArhpUN\nswyVW8eF1nuzdxM3+6idTw/1ncLJ9yYGzgpcgI4niNthQTlf9tT+F5IGmxBh\ngKrZcNlIv7DR5fh92upTpG3JLWiki17dX/fMCLX7y1uM1IBPmZZqeULMwAek\n3g1r1rtDktepuZJwTlU2qdIaunNpEXdILbR6zDCaOCTs/0Om8XUOkJzTqZMR\nbmIMMQQK1BOBaL5BzZc4WLHuEGajhTuN/2zEQbjG7U5m4BZ/Ry7ARW2bgHHo\n6hcnAKmzreoWVtyLshkB9LSUORDd3/hJIavzonWwiEUqrNvnK5GAOBopoZNB\ndhqqIWVFjbq1Zud8YUBadUGsdDLZtQnXB7Ms9iLJu6dPbKzvX4kQTkOn4Xin\nDbdO7TO7rP4KvnjnCwEUkjjcl2y1M61OIgY8OJD64LRCH0mtqpmvx7cGs4/G\nK8fG\r\n=qfOK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIATYHEzF/liMNy+SgySOp1OPaPgA3eYfDWGUS3N61ebkAiA1rGs8kmLE8DmnGS6fgVmjR3uRHtfzNRY1LAgmxjXEyg=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.13.1_1599766321350_0.9498027061189684"},"_hasShrinkwrap":false},"0.13.2":{"name":"@nandorojo/swr-firestore","version":"0.13.2","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.13.2","dist":{"shasum":"8be1544144dc992e7f19a57e5bbfe145ce5f96fa","integrity":"sha512-YTUT2F+fT6Ov7aZxcixF60bqAZ0/GM2oLVg1VjizNeyOIiA2iUKJrYErgZDFUaOVJa+6b/fk9A3m5B+P02KHSw==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.13.2.tgz","fileCount":117,"unpackedSize":302393,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfWn/WCRA9TVsSAnZWagAAu6kP/jQA93yKhNxG8iwQNGMQ\ng2y4/XSjQ2tDjhsIOzYypCE1KknCMeSB8IEcfhgPjuPtX8yT7fXktcFiBg4I\n4GslFAOd7YgsOSVzTLm2RJXsKkDXx//OzMemjLy1PqTa+tR6nkA0TuIWUp+1\na4g+pBI0vLKQ9yL8h84H39UOJJ+3PvfJdtoK3ETyMXly09/91Ecemq/FDwvl\n4e7VKH1Q8p0puSmIAY2PaQ8FMrTyM4/PD4RGreHhKkiDSAiJleZuSgSkeDeP\nQq4zKAYZbTh9fQxfXFRG0SzT+by+UMwO36q0Ep0mrb3HQrUM9nM2ubCNcww6\npzDCLjrVilnVXwxKiGujMcRIxPHXtrKmXW057wpg5E6TyVcoCFRYGgxBTcMb\nSvQp7W8HLw03Na87SbkXE256KD9tMtLPyQvMapfBRaZheKr2dSFoLeU8a2lo\nx3VmeET40nx0eoUF21Q8AOhIjcn7Q2ei22hkZ7KqsHXJLayY1WFYPfnFx6i/\nuXevFb5A2LlfcEcV3y+Oa0ytkvzZoRqfOyTuffWrtPr0DcQhLt/PsTjXaf1+\nAm7UF9y6rfeOy0Mtkb2vo9C6vyOldRWh/CmlBUqiLJIF6LyGDkDN8VyK0wqg\n4Cxdu44DADStwIS2j12GMqgIe5ouTZjS3xufplL5OzCaulprKsvLS6fIl993\nuVAg\r\n=819m\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC0a/NBROPTto2V4mixw5qwtpB1BMvSokwfb9v65WxcyAiBRBsfyacOLY//KpIx6aUC5kIywQfE/4qPSOCHgk85tsg=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.13.2_1599766485947_0.0028581609769513516"},"_hasShrinkwrap":false},"0.14.0":{"name":"@nandorojo/swr-firestore","version":"0.14.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.14.0","dist":{"shasum":"5bb53d294a2458c4f6bda1e2bcc55886ef6c1e58","integrity":"sha512-qyxfrZGN9e/YNaA8+ClNNhf9PflBfv4i4LFFfimixxnPWekuO7iltvHzUVNTI47TMPcLQ9Q6MGSCIVNthPwexw==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.14.0.tgz","fileCount":117,"unpackedSize":307934,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfh6pPCRA9TVsSAnZWagAA+DgQAJOK0ncXdntkLRALjllA\nfUXv6hIKMe9rHsa2TtUT/UJ9M+N5bRDx06/BuXCMW6HYb2XRz4ZF1MEPg6ud\nMtu0r2XReHJBXFR1t3wbfLWGAhrTjB/PF7yckRPFmk3P03le2TKFu6XBiI8X\nOJAfrbX+Fjidj+bfkokAUIGedY+TAXuFgeOVqgz1zVWaU56aELr+lMXz6jfD\nlTd7JKlYnEg10LBaq64Myw+xDBCO1pgSgQncz+Ff+243jvGHyiuUmvr+bWjY\nEGMzYB0OO5Z+O8vVXWXhhmoIu+0xI9ofoqVW0W5krpW2tUMWAxlJiLbbWhgP\nbwOIjQw3Rmcsc7hzUIlDLMLh4f0RQvTnD9PUWZrHEvmT6NE9E7p5L5DwuutW\no1mT5R1hTOdQ4Wjr2lk2AvRk4i/daVlSO9xj2sDFt8LA0Ggs1U4GtadIg9SJ\nlUWToFaFfeWnAbDthx+Ubyp1BnrX8HQH3PWpncDH+QX7zoGr/iG3uZciSlTt\n0WVVs71SfTyHcEYMjanpB+CX0q6DvMg4mwIRpsASb5QG3Gl9nHsJySqUJ/92\n1zHuSOT5EWMr0uixwIDAMhndz4l3PpHGiBSs+GY/wf5Xna7At8fpZfEw2q7n\nB940F26IyrzHGGlEzZmSJ2m4CafvDOYFkTG9kxnJD/fdlq6N9tjwJ7e5i0B/\nYdaH\r\n=au0l\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDA45aNQHkK6cusGpd5r6GwnZtySq2LjiLlpsov3IKuRQIhAJpUPsaA9h+2UIaKdxigYQP880fo4tOYkJcMEO5YTCQJ"}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.14.0_1602726478222_0.06263828211778955"},"_hasShrinkwrap":false},"0.14.1":{"name":"@nandorojo/swr-firestore","version":"0.14.1","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^3.7.5"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.14.1","dist":{"shasum":"e203da0db96ea37f82e7eacc1a603fa5ef417745","integrity":"sha512-jT/ZrK3UJU6tTJD0DZnPJ4Y7LbZ8VN6BWkcglsdgx+JzJiiNtpwEzL4qx7CXtOMK1pVZVRqdvRo/U4m0L2pPDg==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.14.1.tgz","fileCount":117,"unpackedSize":312864,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfh6uwCRA9TVsSAnZWagAATjEQAIqJVOCmT/56C/ex1nbz\nv4E31EvajfhcosIF+TDrc3WXzUw5OREnlsfVZnoOAnf0d8zxzfGaCUBF8szV\nFd4zzg0vgJO12ptTPP6xhacHbDWiYwfZaFo3YVn7Y5/ySjcYYt0jsuSjTmmV\n9gDuqdAidEgOYTi8NFv4OIoMOa3naTyQrbuc6aiDq8/o9KZCHq4ewfCMuRxW\nXYszrCxHB43SFkZPrUxSbzSiVb++/eWrFTeK24Ov2LIuLcmI9K5bjJ7F9mIF\nc4ilCafGnCQXDTkagJI2DmEavDggwGIdhy8NdTz9uk3rTtYL2N8nG886U372\nDF9aO4ZgVNZYXYb83ZQL0ROchgzaRMHvOTB2M+9U6TJCQIylmBYYtHuJZvpR\ndkJV5mD+0cuYw1tIIuNH3NDnTq1MZOlPihZ0T+7JfBOK/0rx79Mbk7+N+6tv\nQLrtCM3pw0B42oeBtuC69ExXs4L9uI5XstHmQJXcn9aQO0d6/DJFyskkEONJ\n3vd1zxvi4gMiwmFXOkaK8VNyKAhd0XxpT0pnKV8cs1aifNFnSF1RVUsGha5u\nu5V4NYrN62Wj2mWieWvSWejHaXn/SdMntAoZOkKreEk2G4gRZ+XBOqLDUm2j\niR3kOLtyvI6+/iWel/7UgNU6KdW1s/GV8kglShd4nXysIOWrYNJZm3DU9VgL\nYrWs\r\n=NTEO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHiUdmTE81KtIW+kxAWQVSMvYR2+TuYnfgbHbW8mRqPfAiAUCvSCgRXW3N7/pOwkTk5JLsL63fi4mbbvEcS2xxiJig=="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.14.1_1602726832393_0.173740578785609"},"_hasShrinkwrap":false},"0.16.0":{"name":"@nandorojo/swr-firestore","version":"0.16.0","description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","main":"lib/commonjs/index.js","module":"lib/module/index.js","types":"lib/typescript/index.d.ts","react-native":"src/index.tsx","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","prepare":"bob build","release":"release-it","example":"yarn --cwd example","pods":"cd example/ios && node -e \"process.exit(require('os').platform() === 'darwin')\" || pod install","bootstrap":"yarn example && yarn && yarn pods"},"keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"license":"MIT","bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"homepage":"https://github.com/nandorojo/swr-firestore#readme","devDependencies":{"@commitlint/config-conventional":"^8.3.4","@firebase/firestore-types":"^1.10.1","@react-native-community/bob":"^0.10.1","@react-native-community/eslint-config":"^0.0.7","@release-it/conventional-changelog":"^1.1.0","@types/jest":"^25.1.2","@types/lodash.get":"^4.4.6","@types/lodash.set":"^4.3.6","@types/react":"^16.9.19","@types/react-native":"0.61.10","commitlint":"^8.3.4","eslint":"^6.8.0","eslint-config-nando":"^1.0.9","eslint-config-prettier":"^6.10.0","eslint-plugin-prettier":"^3.1.2","firebase":"^7.14.1","jest":"^25.1.0","prettier":"^1.19.1","react":"~16.9.0","react-native":"~0.61.5","release-it":"^12.6.3","typescript":"^4.1.0-dev.20201015"},"peerDependencies":{"react":"*"},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"yarn lint && yarn typescript"}},"eslintIgnore":["node_modules/","lib/"],"release-it":{"git":{"commitMessage":"chore: release %s","tagName":"v%s"},"npm":{"publish":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":"angular"}}},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"dependencies":{"lodash.get":"^4.4.2","lodash.set":"^4.3.2","swr":"^0.2.0"},"licenseText":"MIT License\n\nCopyright (c) 2020 Fernando Rojo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@nandorojo/swr-firestore@0.16.0","dist":{"shasum":"e85ac4abdeb2b7f00e6b5251acb75e36fae2dd2f","integrity":"sha512-nl5ZN9Gpkf+lQaMwrlw4H2I6vThZaV0jg5Y9Gqt6WhQjC3aaWDwAWbvZ1WkSc65lxpK+NaK3uWCN/7gHh8SbhQ==","tarball":"https://registry.npmjs.org/@nandorojo/swr-firestore/-/swr-firestore-0.16.0.tgz","fileCount":117,"unpackedSize":313335,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfnYP1CRA9TVsSAnZWagAATxMP/1zZG8Y6UVUydUgIdsW9\nOD1wBQNNmO1N3U0ZXqMsAjR200TySIsUYZ4hDMRE+EAiyQUUWUG685FFAdv5\njtkDv6vqKNACCuGMxkW6xqyaiXPjPoy+yUa0Eoir8nLlJQFNYoyZklzuF9pO\nmYQqFVI58pPArXRSWf+eHyLTQ1rzfAu4uWz9BEBGbXG6bmd1dQg4uaIKrMhJ\nkjl6wk2E0SRbalKo5gVNuI8PIVIxYcuotx1e5iPuA8ipNrvzpjN/FTLxYyIl\ntKduuCsOQC3YaxNKhfkuWb8EsT29x1IgoAqkH6IjR3AMmqf9hL477WP32oZj\nkLWzLk0V9lZj0fxrW3G7xpvGkVTP7hB8QcwnxhKPqQslY5pPXmAlWp8QBkBL\nxAIkJI4iZSDdeLRAzwZlEykubl++r3BCyGzsnK/v+SKY3b8HM3PzfeZHi6kR\ntapLIaKYTs8p2XhxdB+Xu5pWi6xXeze9cNO6eXGBkfKJfY/tnjYu9QOIio6O\n1NaBQr1VeoAVy1/Htl1RwvaPCxykgwfX5AL+qtMX5rev7BcYigMGudt0Av+U\nQfM+8QDxKaAWZ/Of8L5Y1aD3WsVCYkZ1xhnn1mWxkquaPgLKmhFiptZ8N+5g\nEZ3PeGlwg3TaoPvPBhlUzHjNsQzAtvztrhZDH6G1+iw7xlbH9n8IPl1mleLV\nR4R/\r\n=cGuW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCsNgaFCH4BrBWxKc1hpSKv8Mu6RkG+0rd3c1W+4xf65wIgAOstuugIDc/wRHj6AwH6Pt8bPeqkKHQS/OJETwluHqY="}]},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"_npmUser":{"name":"fernandorojo","email":"fernando@basement.social"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swr-firestore_0.16.0_1604158451579_0.868746300007597"},"_hasShrinkwrap":false}},"time":{"created":"2020-04-22T01:51:05.254Z","0.0.1":"2020-04-22T01:51:05.639Z","modified":"2022-04-06T07:26:13.715Z","0.0.2":"2020-04-22T03:45:28.572Z","0.0.3":"2020-04-22T05:23:40.624Z","0.0.4":"2020-04-22T05:42:22.573Z","0.0.5":"2020-04-22T06:04:07.880Z","0.1.0":"2020-04-24T01:35:02.298Z","0.1.1":"2020-04-24T02:36:54.847Z","0.1.1-listen-key":"2020-04-24T17:55:56.138Z","0.1.2-listen-key":"2020-04-25T00:54:54.568Z","0.2.0":"2020-04-25T00:56:16.255Z","0.2.1":"2020-04-25T01:19:36.408Z","0.2.2":"2020-04-29T17:15:35.610Z","0.3.0":"2020-04-29T17:26:50.110Z","0.4.0":"2020-05-01T18:24:20.365Z","0.4.1":"2020-05-01T18:25:38.238Z","0.4.2":"2020-05-01T18:26:31.174Z","0.4.3":"2020-05-01T18:31:19.238Z","0.4.4":"2020-05-01T18:32:08.702Z","0.4.5":"2020-05-01T18:37:48.779Z","0.4.6":"2020-05-01T18:44:53.618Z","0.4.7":"2020-05-01T18:45:41.759Z","0.4.8":"2020-05-03T20:38:40.739Z","0.5.0":"2020-05-03T20:41:37.995Z","0.6.0-alpha.1":"2020-05-06T21:29:01.357Z","0.6.0-alpha.2":"2020-05-06T21:29:36.813Z","0.6.0-alpha.3":"2020-05-06T22:07:41.250Z","0.6.1":"2020-05-07T18:11:28.773Z","0.6.2":"2020-05-07T18:50:41.869Z","0.7.0-alpha.1":"2020-05-08T01:24:23.795Z","0.7.0-alpha.2":"2020-05-08T01:38:53.307Z","0.7.0-alpha.3":"2020-05-08T01:46:24.471Z","0.7.0-alpha.4":"2020-05-14T20:29:30.154Z","0.7.0-alpha.5":"2020-05-17T04:36:56.820Z","0.7.0-alpha.6":"2020-05-17T15:14:25.385Z","0.7.0":"2020-05-18T22:09:36.817Z","0.7.1":"2020-05-18T22:11:36.257Z","0.7.2":"2020-05-18T22:25:21.661Z","0.7.3":"2020-05-18T22:30:18.173Z","0.7.4-alpha.1":"2020-05-19T20:31:34.635Z","0.7.4-alpha.2":"2020-05-19T20:34:25.626Z","0.7.4-alpha.3":"2020-05-19T20:35:06.576Z","0.7.4-alpha.4":"2020-05-19T20:36:16.516Z","0.7.4":"2020-05-20T02:03:02.480Z","0.7.5":"2020-06-02T22:19:30.431Z","0.7.6":"2020-06-02T22:33:34.010Z","0.7.7":"2020-06-02T22:34:35.873Z","0.7.8-alpha.1":"2020-06-02T23:06:26.474Z","0.7.8-alpha.2":"2020-06-02T23:07:01.200Z","0.7.8":"2020-06-02T23:08:27.022Z","0.7.9-alpha.1":"2020-06-17T21:01:10.728Z","0.8.0-alpha.1":"2020-06-21T18:47:34.972Z","0.8.0-alpha.2":"2020-06-21T18:49:58.204Z","0.8.0-alpha.3":"2020-06-21T19:23:28.596Z","0.8.0":"2020-06-21T20:01:15.217Z","0.8.1":"2020-06-21T20:14:25.433Z","0.9.0-alpha.1":"2020-06-25T21:27:43.277Z","0.9.0-alpha.2":"2020-06-25T21:37:48.915Z","0.9.0":"2020-06-25T21:40:29.342Z","0.10.0":"2020-06-30T15:30:08.963Z","0.10.1-alpha.1":"2020-06-30T15:38:16.666Z","0.10.2":"2020-08-15T14:37:30.038Z","0.11.0":"2020-08-27T15:52:59.237Z","0.11.1":"2020-09-10T17:16:03.824Z","0.11.2":"2020-09-10T17:24:13.210Z","0.12.0":"2020-09-10T18:13:18.883Z","0.12.1":"2020-09-10T18:14:23.159Z","0.12.2":"2020-09-10T18:40:28.942Z","0.13.0":"2020-09-10T18:52:00.073Z","0.13.1":"2020-09-10T19:32:01.560Z","0.13.2":"2020-09-10T19:34:46.142Z","0.14.0":"2020-10-15T01:47:58.609Z","0.14.1":"2020-10-15T01:53:52.555Z","0.16.0":"2020-10-31T15:34:11.790Z"},"maintainers":[{"name":"fernandorojo","email":"fernando@basement.social"}],"description":"SWR React hooks for Firestore, that you can actually use in production, on every screen.","homepage":"https://github.com/nandorojo/swr-firestore#readme","keywords":["react-native","ios","android"],"repository":{"type":"git","url":"https://github.com/nandorojo/swr-firestore"},"author":{"name":"Fernando Rojo","email":"frojo@sas.upenn.edu","url":"https://github.com/nandorojo"},"bugs":{"url":"https://github.com/nandorojo/swr-firestore/issues"},"license":"MIT","readme":"# SWR + Firestore\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\n**It's that easy.**\n\n🔥 This library provides the hooks you need for querying Firestore, that you can actually use in production, on every screen.\n\n⚡️ It aims to be **the fastest way to use Firestore in a React app,** both from a developer experience and app performance perspective.\n\n🍕 This library is built on top [useSWR](https://swr.now.sh), meaning you get all of its awesome benefits out-of-the-box.\n\nYou can now fetch, add, and mutate Firestore data with zero boilerplate.\n\n## Features\n\n- Shared state / cache between collection and document queries [(instead of Redux??)](#shared-global-state-between-documents-and-collections)\n- Works with both **React** and **React Native**.\n- Offline mode with Expo [(without detaching!)](https://github.com/nandorojo/expo-firestore-offline-persistence/blob/master/README.md#usage-with-nandorojoswr-firestore)\n- Blazing fast\n- `set`, `update`, and `add` update your global cache, instantly\n- TypeScript-ready [(see docs)](#typescript-support)\n- Realtime subscriptions [(example)](#simple-examples)\n- Prevent memory leaks from Firestore subscriptions\n- No more parsing `document.data()` from Firestore requests\n- Server-side rendering (SSR or SSG) with Next.js [(example)](https://github.com/nandorojo/swr-firestore/issues/17)\n- Automatic date parsing (no more `.toDate()`)\n\n...along with the features touted by Vercel's incredible [SWR](https://github.com/zeit/swr#introduction) library:\n\n_\"With SWR, components will get a stream of data updates constantly and automatically. Thus, the **UI will be always fast and reactive**.\"_\n\n- Transport and protocol agnostic data fetching\n- Fast page navigation\n- Revalidation on focus\n- Interval polling\n- Request deduplication\n- Local mutation\n- Pagination\n- TypeScript ready\n- SSR support\n- Suspense mode\n- Minimal API\n\n## Installation\n\n```sh\nyarn add @nandorojo/swr-firestore\n\n# or\nnpm install @nandorojo/swr-firestore\n```\n\nInstall firebase:\n\n```sh\n# if you're using expo:\nexpo install firebase\n\n# if you aren't using expo:\nyarn add firebase\n# or\nnpm i firebase\n```\n\n## Set up\n\nIn the root of your app, **create an instance of Fuego** and pass it to the **FuegoProvider**.\n\nIf you're using `next.js`, this goes in your `pages/_app.js` file.\n\n`App.js`\n\n```jsx\nimport React from 'react'\nimport 'firebase/firestore'\nimport 'firebase/auth'\nimport { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'\n\nconst firebaseConfig = {\n  // put yours here\n}\n\nconst fuego = new Fuego(firebaseConfig)\n\nexport default function App() {\n  return (\n    <FuegoProvider fuego={fuego}>\n      <YourAppHere />\n    </FuegoProvider>\n  )\n}\n```\n\nMake sure to create your `Fuego` instance outside of the component. The only argument `Fuego` takes is your firebase `config` variable.\n\nUnder the hood, this step initializes firebase for you. No need to call `firebase.initializeApp`.\n\n## Basic Usage\n\n_Assuming you've already completed the setup..._\n\n### Subscribe to a document\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function User() {\n  const user = { id: 'Fernando' }\n  const { data, update, error } = useDocument(`users/${user.id}`, {\n    listen: true,\n  })\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return <Text>Name: {data.name}</Text>\n}\n```\n\n### Get a collection\n\n```js\nimport React from 'react'\nimport { useCollection } from '@nandorojo/swr-firestore'\nimport { Text } from 'react-native'\n\nexport default function UserList() {\n  const { data, update, error } = useCollection(`users`)\n\n  if (error) return <Text>Error!</Text>\n  if (!data) return <Text>Loading...</Text>\n\n  return data.map(user => <Text key={user.id}>{user.name}</Text>)\n}\n```\n\n`useDocument` accepts a document `path` as its first argument here. `useCollection` works similarly.\n\n## Simple examples\n\n### Query a users collection:\n\n```typescript\nconst { data } = useCollection('users')\n```\n\n### Subscribe for real-time updates:\n\n```typescript\nconst { data } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n### Make a complex collection query:\n\n```typescript\nconst { data } = useCollection('users', {\n  where: ['name', '==', 'fernando'],\n  limit: 10,\n  orderBy: ['age', 'desc'],\n  listen: true,\n})\n```\n\n### Pass options from SWR to your document query:\n\n```typescript\n// pass SWR options\nconst { data } = useDocument('albums/nothing-was-the-same', {\n  shouldRetryOnError: false,\n  onSuccess: console.log,\n  loadingTimeout: 2000,\n})\n```\n\n### Pass options from SWR to your collection query:\n\n```typescript\n// pass SWR options\nconst { data } = useCollection(\n  'albums',\n  {\n    listen: true,\n    // you can pass multiple where conditions if you want\n    where: [\n      ['artist', '==', 'Drake'],\n      ['year', '==', '2020'],\n    ],\n  },\n  {\n    shouldRetryOnError: false,\n    onSuccess: console.log,\n    loadingTimeout: 2000,\n  }\n)\n```\n\n### Add data to your collection:\n\n```typescript\nconst { data, add } = useCollection('albums', {\n  where: ['artist', '==', 'Drake'],\n})\n\nconst onPress = () => {\n  // calling this will automatically update your global cache & Firestore\n  add({\n    title: 'Dark Lane Demo Tapes',\n    artist: 'Drake',\n    year: '2020',\n  })\n}\n```\n\n### Set document data:\n\n```typescript\nconst { data, set, update } = useDocument('albums/dark-lane-demo-tapes')\n\nconst onReleaseAlbum = () => {\n  // calling this will automatically update your global cache & Firestore\n  set(\n    {\n      released: true,\n    },\n    { merge: true }\n  )\n\n  // or you could call this:\n  update({\n    released: true,\n  })\n}\n```\n\n### Use dynamic fields in a request:\n\nIf you pass `null` as the collection or document key, the request won't send.\n\nOnce the key is set to a string, the request will send.\n\n**Get list of users who have you in their friends list**\n\n```typescript\nimport { useDoormanUser } from 'react-doorman'\n\nconst { uid } = useDoormanUser()\nconst { data } = useCollection(uid ? 'users' : null, {\n  where: ['friends', 'array-contains', uid],\n})\n```\n\n**Get your favorite song**\n\n```typescript\nconst me = { id: 'fernando' }\n\nconst { data: user } = useDocument<{ favoriteSong: string }>(`users/${me.id}`)\n\n// only send the request once the user.favoriteSong exists!\nconst { data: song } = useDocument(\n  user?.favoriteSong ? `songs/${user.favoriteSong}` : null\n)\n```\n\n### Parse date fields in your documents\n\nMagically turn any Firestore timestamps into JS date objects! No more `.toDate()`.\n\nImagine your `user` document schema looks like this:\n\n```typescript\ntype User = {\n  name: string\n  lastUpdated: {\n    date: Date\n  }\n  createdAt: Date\n}\n```\n\nIn order to turn `createdAt` and `lastUpdated.date` into JS objects, just use the `parseDates` field:\n\n**In a document query**\n\n```typescript\nconst { data } = useDocument<User>('user/fernando', {\n  parseDates: ['createdAt', 'lastUpdated.date'],\n})\n\nlet createdAt: Date\nif (data) {\n  // ✅ all good! it's a JS Date now.\n  createdAt = data.createdAt\n}\n```\n\n`data.createdAt` and `data.lastUpdated.date` are both JS dates now!\n\n**In a collection query**\n\n```typescript\nconst { data } = useCollection<User>('user', {\n  parseDates: ['createdAt', 'lastUpdated.date'],\n})\n\nif (data) {\n  data.forEach(document => {\n    document.createdAt // JS date!\n  })\n}\n```\n\nFor more explanation on the dates, see [issue #4](https://github.com/nandorojo/swr-firestore/issues/4).\n\n### Access a document's Firestore snapshot\n\nIf you set `ignoreFirestoreDocumentSnapshotField` to `false`, you can access the `__snapshot` field.\n\n```js\nconst { data } = useDocument('users/fernando', {\n  ignoreFirestoreDocumentSnapshotField: false, // default: true\n})\n\nif (data) {\n  const id = data?.__snapshot.id\n}\n```\n\nYou can do the same for `useCollection` and `useCollectionGroup`. The snapshot will be on each item in the `data` array.\n\n### Paginate a collection:\n\nVideo [here](https://imgur.com/a/o9AlI4N).\n\n```typescript\nimport React from 'react'\nimport { fuego, useCollection } from '@nandorojo/swr-firestore'\n\nconst collection = 'dump'\nconst limit = 1\nconst orderBy = 'text'\n\nexport default function Paginate() {\n  const { data, mutate } = useCollection<{ text: string }>(\n    collection,\n    {\n      limit,\n      orderBy,\n      // 🚨 this is required to get access to the snapshot!\n      ignoreFirestoreDocumentSnapshotField: false,\n    },\n    {\n      // this lets us update the local cache + paginate without interruptions\n      revalidateOnFocus: false,\n      refreshWhenHidden: false,\n      refreshWhenOffline: false,\n      refreshInterval: 0,\n    }\n  )\n\n  const paginate = async () => {\n    if (!data?.length) return\n\n    const ref = fuego.db.collection(collection)\n\n    // get the snapshot of last document we have right now in our query\n    const startAfterDocument = data[data.length - 1].__snapshot\n\n    // get more documents, after the most recent one we have\n    const moreDocs = await ref\n      .orderBy(orderBy)\n      .startAfter(startAfterDocument)\n      .limit(limit)\n      .get()\n      .then(d => {\n        const docs = []\n        d.docs.forEach(doc => docs.push({ ...doc.data(), id: doc.id }))\n        return docs\n      })\n\n    // mutate our local cache, adding the docs we just added\n    // set revalidate to false to prevent SWR from revalidating on its own\n    mutate(state => [...state, ...moreDocs], false)\n  }\n\n  return data ? (\n    <div>\n      {data.map(({ id, text }) => (\n        <div key={id}>{text}</div>\n      ))}\n      <button onClick={paginate}>paginate</button>\n    </div>\n  ) : (\n    <div>Loading...</div>\n  )\n}\n```\n\n## Query Documents\n\nYou'll rely on `useDocument` to query documents.\n\n```js\nimport React from 'react'\nimport { useDocument } from '@nandorojo/swr-firestore'\n\nconst user = { id: 'Fernando' }\nexport default () => {\n  const { data, error } = useDocument(`users/${user.id}`)\n}\n```\n\nIf you want to set up a listener (or, in Firestore-speak, `onSnapshot`) just set `listen` to `true`.\n\n```js\nconst { data, error } = useDocument(`users/${user.id}`, { listen: true })\n```\n\n# API\n\n## Imports\n\n```typescript\nimport {\n  useDocument,\n  useCollection,\n  useCollectionGroup, // 👋 new!\n  revalidateDocument,\n  revalidateCollection,\n  // these all update BOTH Firestore & the local cache ⚡️\n  set, // set a firestore document\n  update, // update a firestore document\n  fuego, // get the firebase instance used by this lib\n  getCollection, // prefetch a collection, without being hooked into SWR or React\n  getDocument, // prefetch a document, without being hooked into SWR or React\n} from '@nandorojo/swr-firestore'\n```\n\n## `useDocument(path, options)`\n\n```js\nconst {\n  data,\n  set,\n  update,\n  deleteDocument,\n  error,\n  isValidating,\n  mutate,\n} = useDocument(path, options)\n```\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n  - `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n  - This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n- `options` _(optional)_ A dictionary with added options for the query. Takes the folowing values:\n  - `listen = false`: If `true`, sets up a listener for this document that updates whenever it changes.\n  - You can also pass any of the [options available from `useSWR`](https://github.com/zeit/swr#options).\n  - `ignoreFirestoreDocumentSnapshotField = true`. See elaboration below.\n  - `parseDates`: An array of string keys that correspond to dates in your document. [Example](#parse-date-fields-in-your-documents).\n\n##### `ignoreFirestoreDocumentSnapshotField`\n\nIf `true`, docs returned in `data` will not include the firestore `__snapshot` field. If `false`, it will include a `__snapshot` field. This lets you access the document snapshot, but makes the document not JSON serializable.\n\nBy default, it ignores the `__snapshot` field. This makes it easier for newcomers to use `JSON.stringify` without weird errors. You must explicitly set it to `false` to use it.\n\n```js\n// include the firestore document snapshots\nconst { data } = useDocument('users/fernando', {\n  ignoreFirestoreDocumentSnapshotField: false,\n})\n\nif (data) {\n  const path = data.__snapshot.ref.path\n}\n```\n\nThe `__snapshot` field is the exact snapshot returned by Firestore.\n\nSee Firestore's [snapshot docs](https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot) for more.\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `set(data, SetOptions?)`: Extends the `firestore` document `set` function.\n  - You can call this when you want to edit your document.\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n  - The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n- `update(data)`: Extends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n- `deleteDocument()`: Extends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n  - It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.\n- `unsubscribe()` A function that, when called, unsubscribes the Firestore listener.\n  - The function can be null, so make sure to check that it exists before calling it.\n  - **Note**: This is not necessary to use. `useDocument` already unmounts the listener for you. This is only intended if you want to unsubscribe on your own.\n\nThe dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n\n## `useCollection(path, query, options)`\n\n```js\nconst { data, add, error, isValidating, mutate } = useCollection(\n  path,\n  query,\n  options\n)\n```\n\n### Arguments\n\n- **`path`** required string, path to collection.\n- `query` optional dictionary with Firestore query details\n- `options` SWR options [(see SWR docs)](https://github.com/zeit/swr#options)\n\n#### `path`\n\n**`path` required** The unique document path for your Firestore document.\n\n- `string` | `null`. If `null`, the request will not be sent. This is useful if you want to get a user document, but the user ID hasn't loaded yet, for instance.\n- This follows the same pattern as the `key` argument in `useSWR`. See the [SWR docs](https://github.com/zeit/swr#conditional-fetching) for more. Functions are not currently supported for this argument.\n\n#### `query`\n\n_(optional)_ Dictionary that accepts any of the following optional values:\n\n- `listen = false`: if true, will set up a real-time listener that automatically updates.\n- `limit`: number that limits the number of documents\n- [`where`](#where): filter documents by certain conditions based on their fields\n- [`orderBy`](#orderBy): sort documents by their fields\n- `startAt`: number to start at\n- `endAt`: number to end at\n- `startAfter`: number to start after\n- `endBefore`: number to end before\n- `ignoreFirestoreDocumentSnapshotField = true`: If `true`, docs returned in `data` will not include the firestore `__snapshot` field. If `false`, it will include a `__snapshot` field. This lets you access the document snapshot, but makes the document not JSON serializable.\n\n##### `where`\n\nCan be an array, or an array of arrays.\n\nEach array follows this outline: `['key', 'comparison-operator', 'value']`. This is pulled directly from Firestore's [where pattern](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).\n\n```js\n// get all users whoses name are Fernando\nuseCollection('users', {\n  where: ['name', '==', 'Fernando'],\n})\n\n// get all users whose names are Fernando & who are hungry\nuseCollection('users', {\n  where: [\n    ['name', '==', 'Fernando'],\n    ['isHungry', '==', true],\n  ],\n})\n\n// get all users whose friends array contains Fernando\nuseCollection('users', {\n  where: ['friends', 'array-contains', 'Fernando'],\n})\n```\n\n##### `orderBy`\n\nCan be a string, array, or an array of arrays.\n\nEach array follows this outline: `['key', 'desc' | 'asc']`. This is pulled directly from Firestore's [orderBy pattern](https://firebase.google.com/docs/firestore/query-data/order-limit-data).\n\n```js\n// get users, ordered by name\nuseCollection('users', {\n  orderBy: 'name',\n})\n\n// get users, ordered by name in descending order\nuseCollection('users', {\n  orderBy: ['name', 'desc'],\n})\n\n// get users, ordered by name in descending order & hunger in ascending order\nuseCollection('users', {\n  orderBy: [\n    ['name', 'desc'], //\n    ['isHungry', 'asc'],\n  ],\n})\n```\n\n##### `ignoreFirestoreDocumentSnapshotField`\n\nIf `true`, docs returned in `data` will not include the firestore `__snapshot` field. If `false`, it will include a `__snapshot` field. This lets you access the document snapshot, but makes the document not JSON serializable.\n\nBy default, it ignores the `__snapshot` field. This makes it easier for newcomers to use `JSON.stringify` without weird errors. You must explicitly set it to `false` to use it.\n\n```js\n// include the firestore document snapshots\nconst { data } = useCollection('users', {\n  ignoreFirestoreDocumentSnapshotField: false,\n})\n\nif (data) {\n  data.forEach(document => {\n    const path = document?.__snapshot.ref.path\n  })\n}\n```\n\nThe `__snapshot` field is the exact snapshot returned by Firestore.\n\nSee Firestore's [snapshot docs](https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot) for more.\n\n#### `options`\n\n_(optional)_ A dictionary with added options for the request. See the [options available from SWR](https://github.com/zeit/swr#options).\n\n### Return values\n\nReturns a dictionary with the following values:\n\n- `add(data)`: Extends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n  - It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function provided by Firestore.\n\nThe returned dictionary also includes the following [from `useSWR`](https://github.com/zeit/swr#return-values):\n\n- `data`: data for the given key resolved by fetcher (or undefined if not loaded)\n- `error`: error thrown by fetcher (or undefined)\n- `isValidating`: if there's a request or revalidation loading\n- `mutate(data?, shouldRevalidate?)`: function to mutate the cached data\n- `unsubscribe()` A function that, when called, unsubscribes the Firestore listener.\n  - The function can be null, so make sure to check that it exists before calling it.\n  - **Note**: This is not necessary to use. `useCollection` already unmounts the listener for you. This is only intended if you want to unsubscribe on your own.\n\n## `useCollectionGroup(path, query, options)`\n\nFollows an identical API as `useCollection`, except that it leverages Firestore's collection group query for merging subcollections with the same name.\n\nTo see how to use it, follow the instructions from [`useCollection`](#useCollection).\n\nSee the Firestore [docs on collecttion groups](https://firebase.google.com/docs/firestore/query-data/queries) to learn more.\n\n## `set(path, data, SetOptions?)`\n\nExtends the `firestore` document `set` function.\n\n- You can call this when you want to edit your document.\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular Firestore `set` function.\n- The second argument is the same as the second argument for [Firestore `set`](https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document).\n\nThis is useful if you want to `set` a document in a component that isn't connected to the `useDocument` hook.\n\n## `update(path, data)`:\n\nExtends the Firestore document [`update` function](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `set` function.\n\nThis is useful if you want to `update` a document in a component that isn't connected to the `useDocument` hook.\n\n<!--\n## `add(path, data)`:\n\nExtends the Firestore document [`add` function](https://firebase.google.com/docs/firestore/manage-data/add-data).\n\n- It also updates the local cache using SWR's `mutate`. This will prove highly convenient over the regular `add` function.\n- Use this **instead** of `firebase.firestore().collection('users').add(data)`\n-->\n\n## `deleteDocument(path, ignoreLocalMutations = false)`\n\nExtends the Firestore document [`delete` function](https://firebase.google.com/docs/firestore/manage-data/delete-data).\n\n- It also updates the local cache using SWR's `mutate` by deleting your document from this query and all collection queries that have fetched this document. This will prove highly convenient over the regular `delete` function from Firestore.\n- Second argument is a boolean that defaults to false. If `true`, it will not update the local cache, and instead only send delete to Firestore.\n\n## `revalidateDocument(path)`\n\nRefetch a document from Firestore, and update the local cache. Useful if you want to update a given document without calling the connected `revalidate` function from use `useDocument` hook.\n\n- Only argument is the Firestore document path (ex: `users/Fernando`)\n\n## `revalidateCollection(path)`\n\nRefetch a collection query from Firestore, and update the local cache. Useful if you want to update a given collection without calling the connected `revalidate` function from use `useCollection` hook.\n\n- Only argument is the Firestore document path (ex: `users`)\n- **Note** Calling `revalidateCollection` will update _all_ collection queries. If you're paginating data for a given collection, you probably won't want to use this function for that collection.\n\n## `fuego`\n\nThe current firebase instance used by this library. Exports the following fields:\n\n- `db`: the current firestore collection instance\n- `auth`: the `firebase.auth` variable.\n\n```js\nimport { fuego } from '@nandorojo/swr-firestore'\n\nfuego.db.doc('users/Fernando').get()\n\nfuego.auth().currentUser?.uid\n```\n\n## `getDocument(path, options?)`\n\nIf you don't want to use `useDocument` in a component, you can use this function outside of the React scope.\n\n### Arguments\n\n- **`path` required** The unique document path for your Firestore document.\n- `options`\n  - `ignoreFirestoreDocumentSnapshotField = true`. If `false`, it will return a `__snapshot` field too.\n  - `parseDates`: An array of string keys that correspond to dates in your document. [Example](#parse-date-fields-in-your-documents).\n\n### Returns\n\nA promise with the firestore doc and some useful fields. See the [useDocument](#useDocument) `data` return type for more info.\n\n## `getCollection(path, query?, options?)`\n\nIf you don't want to use `useCollection` in a component, you can use this function outside of the React scope.\n\n### Arguments\n\n- **`path` required** The unique collection path for your Firestore collection.\n  - `ignoreFirestoreDocumentSnapshotField = true`. If `false`, it will return a `__snapshot` field too.\n  - `parseDates`: An array of string keys that correspond to dates in your document. [Example](#parse-date-fields-in-your-documents).\n- `query` refer to the second argument of [`useCollection`](#useCollection).\n- `options`\n  - `ignoreFirestoreDocumentSnapshotField = true`. If `false`, it will return a `__snapshot` field too in each document.\n  - `parseDates`: An array of string keys that correspond to dates in your documents. [Example](#parse-date-fields-in-your-documents).\n\n# Features\n\n## TypeScript Support\n\nCreate a model for your `typescript` types, and pass it as a generic to `useDocument` or `useCollection`.\n\n### useDocument\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string, an `exists` boolean, and `hasPendingWrites` boolean.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useDocument<User>('users/fernando')\n\nif (data) {\n  const {\n    id, // string\n    name, // string\n    exists, // boolean\n    hasPendingWrites, // boolean\n  } = data\n}\n\nconst id = data?.id //  string | undefined\nconst name = data?.name // string | undefined\nconst exists = data?.exists // boolean | undefined\nconst hasPendingWrites = data?.hasPendingWrites // boolean | undefind\n```\n\n### useCollection\n\nThe `data` item will include your TypeScript model (or `null`), and will also include an `id` string.\n\n```typescript\ntype User = {\n  name: string\n}\n\nconst { data } = useCollection<User>('users')\n\nif (data) {\n  data.forEach(({ id, name }) => {\n    // ...\n  })\n}\n```\n\n## Shared global state between documents and collections\n\nA great feature of this library is shared data between documents and collections. Until now, this could only be achieved with something like a verbose Redux set up.\n\nSo, what does this mean exactly?\n\nSimply put, any documents pulled from a Firestore request will update the global cache.\n\n**To make it clear, let's look at an example.**\n\nImagine you query a `user` document from Firestore:\n\n```js\nconst { data } = useDocument('users/fernando')\n```\n\nAnd pretend that this document's `data` returns the following:\n\n```json\n{ \"id\": \"fernando\", \"isHungry\": false }\n```\n\n_Remember that `isHungry` is `false` here ^_\n\nNow, let's say you query the `users` collection anywhere else in your app:\n\n```js\nconst { data } = useCollection('users')\n```\n\nAnd pretend that this collection's `data` returns the following:\n\n```json\n[\n  { \"id\": \"fernando\", \"isHungry\": true },\n  {\n    //...\n  }\n]\n```\n\nWhoa, `isHungry` is now true. But what happens to the original document query? Will we have stale data?\n\n**Answer:** It will automatically re-render with the new data!\n\n`swr-firestore` uses document `id` fields to sync any collection queries with existing document queries across your app.\n\nThat means that **if you somehow fetch the same document twice, the latest version will update everywhere.**\n\n## License\n\nMIT\n","readmeFilename":"README.md"}