├── .gitignore ├── .npmignore ├── README.md ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── context │ ├── Context.ts │ └── SuspenseQueryProvider.tsx ├── decorators │ ├── decorateWithId.ts │ └── decorateWithPromise.ts ├── hooks │ └── useSuspenseQuery.tsx ├── index.ts ├── promise-manager │ ├── manage-value-in-store.ts │ ├── queries-store.ts │ └── throw-promise.ts └── types │ └── types.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /dist -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | src -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apollo Client - useSuspenseQuery 2 | 3 | ## How to use 4 | 5 | ```shell script 6 | $ npm install @brainly/use-suspense-query 7 | ``` 8 | 9 | To use hook in your app you have to provide apollo client via. `SuspenseQueryProvider` i.e: 10 | ```jsx 11 | import { SuspenseQueryProvider } from 'use-suspense-query'; 12 | 13 | const apolloClient = new ApolloClient({ 14 | link, 15 | cache 16 | }); 17 | 18 | export function App() { 19 | return ( 20 | 21 |
22 | 23 |
24 |
25 | ); 26 | } 27 | ``` 28 | 29 | Now you're able to use hook in your app. Example usage: 30 | ```jsx 31 | import { qgl } from '@apollo/client'; 32 | import { useSuspenseQuery } from 'use-suspense-query'; 33 | 34 | const myQuery = gql` 35 | query getSth($id: ID!) { 36 | data(id: $id) { 37 | sth 38 | } 39 | } 40 | ` 41 | 42 | function DataComponent() { 43 | const data = useSuspenseQuery(myQuery, { 44 | variables: { 45 | id: '1234' 46 | } 47 | }); 48 | 49 | return (
display {data} here
); 50 | } 51 | 52 | export function App() { 53 | return ( 54 | 55 | 56 | 57 | ) 58 | } 59 | ``` 60 | 61 | ### Hook API 62 | ```jsx 63 | useSuspenseQuery(query: GraphqlQuery, options: Options): Response of ApolloClient.query() 64 | ``` 65 | 66 | ### Hook Options 67 | 68 | | Option | Description | Type | 69 | | ------------- |:-------------:| -----:| 70 | | variables | query variables | Object | 71 | | fetchPolicy | fetch policy option passing to ApolloClient fetchPolicy field | String | 72 | | uniqueKey | In default that key is generated based on variables and query, but to be sure that your request is totally unique, you should pass this field with some unique value - recommended to add uniqueKey! | String | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@brainly/use-suspense-query", 3 | "version": "1.0.3", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@rollup/pluginutils": { 8 | "version": "3.0.10", 9 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.0.10.tgz", 10 | "integrity": "sha512-d44M7t+PjmMrASHbhgpSbVgtL6EFyX7J4mYxwQ/c5eoaE6N2VgCgEcWVzNnwycIloti+/MpwFr8qfw+nRw00sw==", 11 | "dev": true, 12 | "requires": { 13 | "@types/estree": "0.0.39", 14 | "estree-walker": "^1.0.1", 15 | "picomatch": "^2.2.2" 16 | } 17 | }, 18 | "@types/estree": { 19 | "version": "0.0.39", 20 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", 21 | "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", 22 | "dev": true 23 | }, 24 | "@types/node": { 25 | "version": "14.0.13", 26 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", 27 | "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==", 28 | "dev": true 29 | }, 30 | "@types/prop-types": { 31 | "version": "15.7.3", 32 | "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", 33 | "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" 34 | }, 35 | "@types/react": { 36 | "version": "16.9.35", 37 | "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.35.tgz", 38 | "integrity": "sha512-q0n0SsWcGc8nDqH2GJfWQWUOmZSJhXV64CjVN5SvcNti3TdEaA3AH0D8DwNmMdzjMAC/78tB8nAZIlV8yTz+zQ==", 39 | "requires": { 40 | "@types/prop-types": "*", 41 | "csstype": "^2.2.0" 42 | } 43 | }, 44 | "@types/resolve": { 45 | "version": "0.0.8", 46 | "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", 47 | "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", 48 | "dev": true, 49 | "requires": { 50 | "@types/node": "*" 51 | } 52 | }, 53 | "builtin-modules": { 54 | "version": "3.1.0", 55 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", 56 | "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", 57 | "dev": true 58 | }, 59 | "commondir": { 60 | "version": "1.0.1", 61 | "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", 62 | "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", 63 | "dev": true 64 | }, 65 | "csstype": { 66 | "version": "2.6.10", 67 | "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.10.tgz", 68 | "integrity": "sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w==" 69 | }, 70 | "estree-walker": { 71 | "version": "1.0.1", 72 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", 73 | "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", 74 | "dev": true 75 | }, 76 | "find-cache-dir": { 77 | "version": "3.3.1", 78 | "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", 79 | "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", 80 | "dev": true, 81 | "requires": { 82 | "commondir": "^1.0.1", 83 | "make-dir": "^3.0.2", 84 | "pkg-dir": "^4.1.0" 85 | } 86 | }, 87 | "find-up": { 88 | "version": "4.1.0", 89 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 90 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 91 | "dev": true, 92 | "requires": { 93 | "locate-path": "^5.0.0", 94 | "path-exists": "^4.0.0" 95 | } 96 | }, 97 | "fs-extra": { 98 | "version": "8.1.0", 99 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 100 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 101 | "dev": true, 102 | "requires": { 103 | "graceful-fs": "^4.2.0", 104 | "jsonfile": "^4.0.0", 105 | "universalify": "^0.1.0" 106 | } 107 | }, 108 | "fsevents": { 109 | "version": "2.1.3", 110 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 111 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 112 | "dev": true, 113 | "optional": true 114 | }, 115 | "graceful-fs": { 116 | "version": "4.2.4", 117 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 118 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", 119 | "dev": true 120 | }, 121 | "is-module": { 122 | "version": "1.0.0", 123 | "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", 124 | "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", 125 | "dev": true 126 | }, 127 | "is-reference": { 128 | "version": "1.2.0", 129 | "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.0.tgz", 130 | "integrity": "sha512-ZVxq+5TkOx6GQdnoMm2aRdCKADdcrOWXLGzGT+vIA8DMpqEJaRk5AL1bS80zJ2bjHunVmjdzfCt0e4BymIEqKQ==", 131 | "dev": true, 132 | "requires": { 133 | "@types/estree": "0.0.44" 134 | }, 135 | "dependencies": { 136 | "@types/estree": { 137 | "version": "0.0.44", 138 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.44.tgz", 139 | "integrity": "sha512-iaIVzr+w2ZJ5HkidlZ3EJM8VTZb2MJLCjw3V+505yVts0gRC4UMvjw0d1HPtGqI/HQC/KdsYtayfzl+AXY2R8g==", 140 | "dev": true 141 | } 142 | } 143 | }, 144 | "js-tokens": { 145 | "version": "4.0.0", 146 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 147 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 148 | "dev": true 149 | }, 150 | "jsonfile": { 151 | "version": "4.0.0", 152 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 153 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 154 | "dev": true, 155 | "requires": { 156 | "graceful-fs": "^4.1.6" 157 | } 158 | }, 159 | "locate-path": { 160 | "version": "5.0.0", 161 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 162 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 163 | "dev": true, 164 | "requires": { 165 | "p-locate": "^4.1.0" 166 | } 167 | }, 168 | "loose-envify": { 169 | "version": "1.4.0", 170 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 171 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 172 | "dev": true, 173 | "requires": { 174 | "js-tokens": "^3.0.0 || ^4.0.0" 175 | } 176 | }, 177 | "magic-string": { 178 | "version": "0.25.7", 179 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", 180 | "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", 181 | "dev": true, 182 | "requires": { 183 | "sourcemap-codec": "^1.4.4" 184 | } 185 | }, 186 | "make-dir": { 187 | "version": "3.1.0", 188 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 189 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 190 | "dev": true, 191 | "requires": { 192 | "semver": "^6.0.0" 193 | } 194 | }, 195 | "object-assign": { 196 | "version": "4.1.1", 197 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 198 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 199 | "dev": true 200 | }, 201 | "p-limit": { 202 | "version": "2.3.0", 203 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 204 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 205 | "dev": true, 206 | "requires": { 207 | "p-try": "^2.0.0" 208 | } 209 | }, 210 | "p-locate": { 211 | "version": "4.1.0", 212 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 213 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 214 | "dev": true, 215 | "requires": { 216 | "p-limit": "^2.2.0" 217 | } 218 | }, 219 | "p-try": { 220 | "version": "2.2.0", 221 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 222 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 223 | "dev": true 224 | }, 225 | "path-exists": { 226 | "version": "4.0.0", 227 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 228 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 229 | "dev": true 230 | }, 231 | "path-parse": { 232 | "version": "1.0.6", 233 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 234 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 235 | "dev": true 236 | }, 237 | "picomatch": { 238 | "version": "2.2.2", 239 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 240 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 241 | "dev": true 242 | }, 243 | "pkg-dir": { 244 | "version": "4.2.0", 245 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 246 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 247 | "dev": true, 248 | "requires": { 249 | "find-up": "^4.0.0" 250 | } 251 | }, 252 | "prop-types": { 253 | "version": "15.7.2", 254 | "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", 255 | "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", 256 | "dev": true, 257 | "requires": { 258 | "loose-envify": "^1.4.0", 259 | "object-assign": "^4.1.1", 260 | "react-is": "^16.8.1" 261 | } 262 | }, 263 | "ramda": { 264 | "version": "0.27.0", 265 | "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.0.tgz", 266 | "integrity": "sha512-pVzZdDpWwWqEVVLshWUHjNwuVP7SfcmPraYuqocJp1yo2U1R7P+5QAfDhdItkuoGqIBnBYrtPp7rEPqDn9HlZA==" 267 | }, 268 | "react": { 269 | "version": "16.13.1", 270 | "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", 271 | "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==", 272 | "dev": true, 273 | "requires": { 274 | "loose-envify": "^1.1.0", 275 | "object-assign": "^4.1.1", 276 | "prop-types": "^15.6.2" 277 | } 278 | }, 279 | "react-is": { 280 | "version": "16.13.1", 281 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", 282 | "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", 283 | "dev": true 284 | }, 285 | "resolve": { 286 | "version": "1.15.1", 287 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", 288 | "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", 289 | "dev": true, 290 | "requires": { 291 | "path-parse": "^1.0.6" 292 | } 293 | }, 294 | "rollup": { 295 | "version": "2.11.2", 296 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.11.2.tgz", 297 | "integrity": "sha512-pJT6mfH+/gh1sOWyNMAWxjbYGL5x2AfsaR0SWLRwq2e7vxOKt/0mBjtYDTVYF8JXxVzmnuDzA+EpsPLWt/oyrg==", 298 | "dev": true, 299 | "requires": { 300 | "fsevents": "~2.1.2" 301 | } 302 | }, 303 | "rollup-plugin-commonjs": { 304 | "version": "10.1.0", 305 | "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", 306 | "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", 307 | "dev": true, 308 | "requires": { 309 | "estree-walker": "^0.6.1", 310 | "is-reference": "^1.1.2", 311 | "magic-string": "^0.25.2", 312 | "resolve": "^1.11.0", 313 | "rollup-pluginutils": "^2.8.1" 314 | }, 315 | "dependencies": { 316 | "estree-walker": { 317 | "version": "0.6.1", 318 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", 319 | "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", 320 | "dev": true 321 | } 322 | } 323 | }, 324 | "rollup-plugin-node-resolve": { 325 | "version": "5.2.0", 326 | "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", 327 | "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", 328 | "dev": true, 329 | "requires": { 330 | "@types/resolve": "0.0.8", 331 | "builtin-modules": "^3.1.0", 332 | "is-module": "^1.0.0", 333 | "resolve": "^1.11.1", 334 | "rollup-pluginutils": "^2.8.1" 335 | } 336 | }, 337 | "rollup-plugin-typescript2": { 338 | "version": "0.27.1", 339 | "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.27.1.tgz", 340 | "integrity": "sha512-RJl77Bbj1EunAQDC3dK/O2HWuSUX3oJbRGzyLoS5o9W4Hs1Nix3Gavqj1Lzs5Y6Ff4H2xXfmZ1WWUQCYocSbzQ==", 341 | "dev": true, 342 | "requires": { 343 | "@rollup/pluginutils": "^3.0.8", 344 | "find-cache-dir": "^3.3.1", 345 | "fs-extra": "8.1.0", 346 | "resolve": "1.15.1", 347 | "tslib": "1.11.2" 348 | } 349 | }, 350 | "rollup-pluginutils": { 351 | "version": "2.8.2", 352 | "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", 353 | "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", 354 | "dev": true, 355 | "requires": { 356 | "estree-walker": "^0.6.1" 357 | }, 358 | "dependencies": { 359 | "estree-walker": { 360 | "version": "0.6.1", 361 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", 362 | "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", 363 | "dev": true 364 | } 365 | } 366 | }, 367 | "semver": { 368 | "version": "6.3.0", 369 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 370 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 371 | "dev": true 372 | }, 373 | "sourcemap-codec": { 374 | "version": "1.4.8", 375 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 376 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 377 | "dev": true 378 | }, 379 | "tslib": { 380 | "version": "1.11.2", 381 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.2.tgz", 382 | "integrity": "sha512-tTSkux6IGPnUGUd1XAZHcpu85MOkIl5zX49pO+jfsie3eP0B6pyhOlLXm3cAC6T7s+euSDDUUV+Acop5WmtkVg==", 383 | "dev": true 384 | }, 385 | "typescript": { 386 | "version": "3.9.3", 387 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.3.tgz", 388 | "integrity": "sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ==", 389 | "dev": true 390 | }, 391 | "universalify": { 392 | "version": "0.1.2", 393 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 394 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 395 | "dev": true 396 | }, 397 | "uuid": { 398 | "version": "8.1.0", 399 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.1.0.tgz", 400 | "integrity": "sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg==" 401 | } 402 | } 403 | } 404 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@brainly/use-suspense-query", 3 | "version": "1.0.3", 4 | "description": "", 5 | "main": "dist/index.js", 6 | "module": "dist/index.es.js", 7 | "homepage": "https://github.com/Fasosnql/use-suspense-query", 8 | "files": [ 9 | "dist" 10 | ], 11 | "types": "dist/index.d.ts", 12 | "scripts": { 13 | "build": "rollup -c" 14 | }, 15 | "author": "Przemyslaw Nowak ", 16 | "license": "MIT", 17 | "dependencies": { 18 | "@types/react": "^16.9.35", 19 | "ramda": "^0.27.0", 20 | "uuid": "^8.1.0" 21 | }, 22 | "peerDependencies": { 23 | "apollo-client": "^2.6.0", 24 | "graphql": "*", 25 | "react": "^16.8.0" 26 | }, 27 | "devDependencies": { 28 | "react": "^16.13.1", 29 | "rollup": "^2.11.2", 30 | "rollup-plugin-commonjs": "^10.1.0", 31 | "rollup-plugin-node-resolve": "^5.2.0", 32 | "rollup-plugin-typescript2": "^0.27.1", 33 | "typescript": "^3.9.3" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from 'rollup-plugin-typescript2'; 2 | import commonjs from 'rollup-plugin-commonjs' 3 | import resolve from 'rollup-plugin-node-resolve'; 4 | import pkg from './package.json'; 5 | 6 | export default { 7 | input: 'src/index.ts', 8 | output: [ 9 | { 10 | file: pkg.main, 11 | format: 'cjs', 12 | }, 13 | { 14 | file: pkg.module, 15 | format: 'es', 16 | }, 17 | ], 18 | external: [ 19 | ...Object.keys(pkg.dependencies || {}), 20 | ...Object.keys(pkg.peerDependencies || {}), 21 | ], 22 | plugins: [ 23 | typescript({ 24 | typescript: require('typescript'), 25 | }), 26 | resolve() 27 | ], 28 | } 29 | -------------------------------------------------------------------------------- /src/context/Context.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export default React.createContext(null); -------------------------------------------------------------------------------- /src/context/SuspenseQueryProvider.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import ApolloClientContext from './Context'; 3 | 4 | export function SuspenseQueryProvider({ client, children }) { 5 | return {children} 6 | } 7 | -------------------------------------------------------------------------------- /src/decorators/decorateWithId.ts: -------------------------------------------------------------------------------- 1 | const uuidv5 = require('uuid/v5') 2 | 3 | const uuidNamespace = uuidv5('suspense.queries.utils', uuidv5.DNS); 4 | export function decorateWithId(apolloClient, query, options) { 5 | return {apolloClient, query, options, id: uuidv5(`${query?.loc?.source?.body},${JSON.stringify(options?.variables)},${options?.uniqueKey}`, uuidNamespace)}; 6 | } -------------------------------------------------------------------------------- /src/decorators/decorateWithPromise.ts: -------------------------------------------------------------------------------- 1 | export function decorateWithPromise([error, {apolloClient, id, options, query}, result]) { 2 | if (error) { 3 | console.error(error); 4 | return [null, null, null]; 5 | } 6 | 7 | if (result) { 8 | return [null, null, result]; 9 | } 10 | 11 | return [id, apolloClient.query({ 12 | query, 13 | variables: options?.variables || {}, 14 | fetchPolicy: options?.variables || 'cache-first' 15 | })] 16 | } -------------------------------------------------------------------------------- /src/hooks/useSuspenseQuery.tsx: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react'; 2 | import ApolloClientContext from '../context/Context'; 3 | import {Options} from "../types/types"; 4 | import {decorateWithPromise} from "../decorators/decorateWithPromise"; 5 | import {manageValueInStore} from "../promise-manager/manage-value-in-store"; 6 | import {decorateWithId} from "../decorators/decorateWithId"; 7 | import {throwPromise} from "../promise-manager/throw-promise"; 8 | 9 | const compose = require("ramda/src/compose"); 10 | 11 | export function useSuspenseQuery(query: any, options?: Options) { 12 | const apolloClient = useContext(ApolloClientContext); 13 | 14 | const [id, promise, result] = compose( 15 | decorateWithPromise, 16 | manageValueInStore, 17 | decorateWithId 18 | )( 19 | apolloClient, 20 | query, 21 | options 22 | ); 23 | 24 | if (result) { 25 | return result; 26 | } else { 27 | return throwPromise(promise, id); 28 | } 29 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { SuspenseQueryProvider } from './context/SuspenseQueryProvider'; 2 | export { useSuspenseQuery } from './hooks/useSuspenseQuery'; -------------------------------------------------------------------------------- /src/promise-manager/manage-value-in-store.ts: -------------------------------------------------------------------------------- 1 | import { queriesStore } from './queries-store'; 2 | 3 | export function manageValueInStore(args): [boolean | Error, any, any?] { 4 | // @ts-ignore 5 | const indexQueryInStore = queriesStore.findIndex(query => query.id === args.id); 6 | const queryInStore = queriesStore[indexQueryInStore]; 7 | 8 | if (queryInStore && queryInStore.status !== 'pending') { 9 | queriesStore.splice(indexQueryInStore, 1); 10 | if (queryInStore.status === 'error') { 11 | return [new Error(queryInStore.result.toString()), {}]; 12 | } else if (queryInStore.status === 'success') { 13 | return [false, {}, queryInStore.result]; 14 | } 15 | } else { 16 | queriesStore.push({ 17 | id: args.id, 18 | status: 'pending', 19 | result: null 20 | }) 21 | } 22 | 23 | return [false, args]; 24 | } -------------------------------------------------------------------------------- /src/promise-manager/queries-store.ts: -------------------------------------------------------------------------------- 1 | export interface QueryStore { 2 | id: string; 3 | status: string; 4 | result: any; 5 | } 6 | 7 | export const queriesStore: QueryStore[] = []; -------------------------------------------------------------------------------- /src/promise-manager/throw-promise.ts: -------------------------------------------------------------------------------- 1 | import { queriesStore } from "./queries-store"; 2 | 3 | export function throwPromise(promise, id) { 4 | // @ts-ignore 5 | const elementIndex = queriesStore.findIndex(query => query.id === id); 6 | const element = queriesStore[elementIndex]; 7 | 8 | if (!element) { 9 | return null; 10 | } 11 | 12 | throw promise 13 | .then( 14 | result => { 15 | element.status = 'success'; 16 | element.result = result; 17 | }, 18 | error => { 19 | element.status = "error"; 20 | element.result = JSON.stringify(error); 21 | } 22 | ) 23 | .catch(e => { 24 | element.status = "error"; 25 | element.result = JSON.stringify(e); 26 | }); 27 | } -------------------------------------------------------------------------------- /src/types/types.ts: -------------------------------------------------------------------------------- 1 | type FetchPolicy = 'cache-first' | 'network-only' | 'cache-only' | 'no-cache' | 'standby'; 2 | 3 | export interface Options { 4 | variables?: any; 5 | fetchPolicy?: FetchPolicy; 6 | uniqueKey?: string; 7 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "es2015", 4 | "lib": [ "es2015", "dom", "es7" ], 5 | "jsx": "react", 6 | "allowSyntheticDefaultImports": true, 7 | "declaration": true, 8 | "declarationDir": "./dist", 9 | "noImplicitAny": false, 10 | "outDir": "./dist", 11 | "target": "es5" 12 | }, 13 | "include": [ 14 | "src/**/*" 15 | ] 16 | } --------------------------------------------------------------------------------