Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | 15x 15x 15x 15x 15x 27x 27x 27x 27x 27x 27x 27x 27x 1x 27x 3x 3x 3x 3x 27x 23x 2x 23x 23x 15x 15x 4x 15x 13x 13x 13x 13x 2x 2x 2x 2x 17x 17x 17x 17x 23x 23x 23x 27x 27x 26x 26x 26x 26x 26x 17x 16x 26x 15x | import mitt from 'mitt' import { graphqlFetchOptions } from './graphqlFetchOptions' import { hashObject } from './hashObject' import { GraphQLCache, GraphQLCacheKey, GraphQLCacheValue, GraphQLFetchOptions } from '../index' const { on, off, emit } = mitt() /** * A lightweight GraphQL client that caches queries and mutations. * @kind class * @name GraphQL * @param {object} [options={}] Options. * @param {GraphQLCache} [options.cache={}] Cache to import; usually from a server side render. * @param {GraphQLCache} [options.cacheWrapper={}] wrapper cacheValue * @see [`reportCacheErrors`]{@link reportCacheErrors} to setup error reporting. * @example <caption>Construct a GraphQL client.</caption> * ```js * import { GraphQL } from 'graphql-svelte' * * const graphql = new GraphQL() * ``` */ export class GraphQL { constructor({ cache = {}, cacheWrapper}: any = {}) { this.cache = cache this.cacheWrapper = cacheWrapper } /** * wrapper for cache * @kind function * @name GraphQL#cacheWrapper * @example```ts * import { writable } from 'svelte/store' * * this.cacheWrapper(cacheValue) * ``` */ cacheWrapper: Function /** * Adds an event listener. * @kind function * @name GraphQL#on * @param {string} type Event type. * @param {Function} handler Event handler. * @see [`reportCacheErrors`]{@link reportCacheErrors} can be used with this to setup error reporting. */ on = on /** * Removes an event listener. * @kind function * @name GraphQL#off * @param {string} type Event type. * @param {Function} handler Event handler. */ off = off /** * Emits an event with details to listeners. * @param {string} type Event type. * @param {*} [details] Event details. * @ignore */ emit = emit /** * Cache of loaded GraphQL operations. You probably don’t need to interact * with this unless you’re implementing a server side rendering framework. * @kind member * @name GraphQL#cache * @type {GraphQLCache} * @example <caption>Export cache as JSON.</caption> * ```js * const exportedCache = JSON.stringify(graphql.cache) * ``` * @example <caption>Example cache JSON.</caption> * ```json * { * "a1bCd2": { * "data": { * "viewer": { * "name": "Jayden Seric" * } * } * } * } * ``` */ cache: GraphQLCache /** * A map of loading GraphQL operations. You probably don’t need to interact * with this unless you’re implementing a server side rendering framework. * @name GraphQL#operations */ operations: Record<GraphQLCacheKey, Promise<GraphQLCacheValue>> = {} /** * Signals that [GraphQL cache]{@link GraphQL#cache} subscribers such as the * operation. Emits a [`GraphQL`]{@link GraphQL} instance `reload` event. * @kind function * @name GraphQL#reload * @param {GraphQLCacheKey} [exceptCacheKey] A [GraphQL cache]{@link GraphQL#cache} [key]{@link GraphQLCacheKey} for cache to exempt from reloading. * @example <caption>Reloading the [GraphQL cache]{@link GraphQL#cache}.</caption> * ```js * graphql.reload() * ``` */ reload = (exceptCacheKey: GraphQLCacheKey) => { this.emit('reload', { exceptCacheKey }) } /** * Resets the [GraphQL cache]{@link GraphQL#cache}, useful when a user logs * out. Emits a [`GraphQL`]{@link GraphQL} instance `reset` event. * @kind function * @name GraphQL#reset * @param {GraphQLCacheKey} [exceptCacheKey] A [GraphQL cache]{@link GraphQL#cache} [key]{@link GraphQLCacheKey} for cache to exempt from deletion. Useful for resetting cache after a mutation, preserving the mutation cache. * @example <caption>Resetting the [GraphQL cache]{@link GraphQL#cache}.</caption> * ```js * graphql.reset() * ``` */ reset = (exceptCacheKey: string) => { let cacheKeys = Object.keys(this.cache) exceptCacheKey ? cacheKeys = cacheKeys.filter((hash) => hash !== exceptCacheKey) : '' cacheKeys.forEach((cacheKey) => delete this.cache[cacheKey]) // Emit cache updates after the entire cache has been updated, so logic in // listeners can assume cache for all queries is fresh and stable. this.emit('reset', { exceptCacheKey }) } /** * Fetches a GraphQL operation. * @param {GraphQLFetchOptions} fetchOptions URL and options for [`fetch`](https://developer.mozilla.org/docs/Web/API/Fetch_API). * @param {GraphQLCacheKey} cacheKey [GraphQL cache]{@link GraphQL#cache} [key]{@link GraphQLCacheKey}. * @returns {Promise<GraphQLCacheValue>} A promise that resolves the [GraphQL cache]{@link GraphQL#cache} [value]{@link GraphQLCacheValue}. * @ignore */ fetch = ({ url, ...options }: GraphQLFetchOptions, cacheKey: GraphQLCacheKey): Promise<GraphQLCacheValue> => { let fetchResponse: any const fetcher = typeof fetch === 'function' ? fetch : () => Promise.reject( new Error('Global fetch API or polyfill unavailable.') ) const cacheValue: any = {} const cacheValuePromise = fetcher(url, options) .then( (response) => { fetchResponse = response if (!response.ok) cacheValue.httpError = { status: response.status, statusText: response.statusText, } return response.json().then( ({ errors, data }) => { // JSON parse ok. if (!errors && !data) cacheValue.parseError = 'Malformed payload.' if (errors) cacheValue.graphQLErrors = errors if (data) cacheValue.data = data }, ({ message }) => { // JSON parse error. cacheValue.parseError = message } ) }, ({ message }) => { cacheValue.fetchError = message } ) .then(() => { // Cache the operation. this.cache[cacheKey] = this.cacheWrapper ? this.cacheWrapper(cacheValue):cacheValue // Clear the loaded operation. delete this.operations[cacheKey]; this.emit('cache', { cacheKey, cacheValue, // May be undefined if there was a fetch error. response: fetchResponse, }) return cacheValue }) this.operations[cacheKey] = cacheValuePromise this.emit('fetch', { cacheKey, cacheValuePromise }) return cacheValuePromise } /** * Loads or reuses an already loading GraphQL operation in * [GraphQL operations]{@link GraphQL#operations}. Emits a * [`GraphQL`]{@link GraphQL} instance `fetch` event if an already loading * operation isn’t reused, and a `cache` event once it’s loaded into the * [GraphQL cache]{@link GraphQL#cache}. * @kind function * @name GraphQL#operate * @param {object} options Options. * @param {GraphQLOperation} options.operation GraphQL operation. * @param {GraphQLFetchOptionsOverride} [options.fetchOptionsOverride] Overrides default GraphQL operation [`fetch` options]{@link GraphQLFetchOptions}. * @param {boolean} [options.reloadOnLoad=false] Should a [GraphQL reload]{@link GraphQL#reload} happen after the operation loads, excluding the loaded operation cache. * @param {boolean} [options.resetOnLoad=false] Should a [GraphQL reset]{@link GraphQL#reset} happen after the operation loads, excluding the loaded operation cache. * @returns {GraphQLOperationLoading} Loading GraphQL operation details. * */ operate = ({ operation, fetchOptionsOverride, reloadOnLoad, resetOnLoad }: any) => { if (reloadOnLoad && resetOnLoad) throw new Error('operate() options “reloadOnLoad” and “resetOnLoad” can’t both be true.') const fetchOptions = graphqlFetchOptions(operation) fetchOptionsOverride && fetchOptionsOverride(fetchOptions) const cacheKey = hashObject(fetchOptions) const cacheValuePromise = // Use an identical existing request or… this.operations[cacheKey] || // …make a fresh request. this.fetch(fetchOptions, cacheKey) // Potential edge-case issue: Multiple identical queries with resetOnLoad // enabled will cause excessive resets. cacheValuePromise.then(() => { if (reloadOnLoad) this.reload(cacheKey) else if (resetOnLoad) this.reset(cacheKey) }) return { cacheKey, cacheValue: this.cache[cacheKey], cacheValuePromise, } } } |