graphql-persisted 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/GraphQLQueryCache.d.ts +46 -2
- package/cjs/GraphQLQueryCache.js +205 -216
- package/cjs/graphqlHooks.js +10 -2
- package/cjs/types.d.ts +1 -1
- package/mjs/GraphQLQueryCache.d.ts +46 -2
- package/mjs/GraphQLQueryCache.js +204 -216
- package/mjs/graphqlHooks.js +10 -2
- package/mjs/types.d.ts +1 -1
- package/package.json +2 -2
package/mjs/GraphQLQueryCache.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
var _GraphQLQueryCache_instances, _GraphQLQueryCache_fetcher, _GraphQLQueryCache_endpoint, _GraphQLQueryCache_persistedOperations, _GraphQLQueryCache_persistedDocuments, _GraphQLQueryCache_configMeta, _GraphQLQueryCache_subscribedQueries, _GraphQLQueryCache_inFlight, _GraphQLQueryCache_cacheStore, _GraphQLQueryCache_runtimeCache, _GraphQLQueryCache_queryInvalidation, _GraphQLQueryCache_mutationInvalidation, _GraphQLQueryCache_effectsIssued, _GraphQLQueryCache_getKey, _GraphQLQueryCache_executeOperation, _GraphQLQueryCache_getMeta, _GraphQLQueryCache_fetch, _GraphQLQueryCache_shouldRefetchQuery, _GraphQLQueryCache_gcOperations;
|
|
2
|
-
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
|
|
3
1
|
import isEqual from 'lodash.isequal';
|
|
4
2
|
import { graphqlNormalize } from 'graphql-normalize';
|
|
5
3
|
import { produce } from 'immer';
|
|
@@ -11,67 +9,38 @@ import { variableObject, variableString } from './helpers';
|
|
|
11
9
|
*/
|
|
12
10
|
export class GraphQLQueryCache {
|
|
13
11
|
constructor(config) {
|
|
14
|
-
_GraphQLQueryCache_instances.add(this);
|
|
15
|
-
/**
|
|
16
|
-
* If an alterative fetch is provided, we will use that for operations
|
|
17
|
-
* Otherwise we'll use the native 'fetch'
|
|
18
|
-
*/
|
|
19
|
-
_GraphQLQueryCache_fetcher.set(this, void 0);
|
|
20
|
-
/**
|
|
21
|
-
* GraphQL API endpoint
|
|
22
|
-
* @default /graphql
|
|
23
|
-
*/
|
|
24
|
-
_GraphQLQueryCache_endpoint.set(this, void 0);
|
|
25
|
-
// A mapping of OperationName -> Operation Hash. The operation hash is sent to the
|
|
26
|
-
// server when we issue a query
|
|
27
|
-
_GraphQLQueryCache_persistedOperations.set(this, void 0);
|
|
28
|
-
// Mapping of persisted documents
|
|
29
|
-
_GraphQLQueryCache_persistedDocuments.set(this, void 0);
|
|
30
|
-
// A mapping of metadata between the config string and normalized metadata shape
|
|
31
|
-
_GraphQLQueryCache_configMeta.set(this, void 0);
|
|
32
12
|
// All queries we are "subscribed to", meaning that we React to any changes
|
|
33
13
|
// when there are updates to the cache.
|
|
34
|
-
|
|
35
|
-
// All "in-flight" fetches, to deduplicate fetches that are already in-flight
|
|
36
|
-
// for an operation
|
|
37
|
-
);
|
|
14
|
+
this._subscribedQueries = {};
|
|
38
15
|
// All "in-flight" fetches, to deduplicate fetches that are already in-flight
|
|
39
16
|
// for an operation
|
|
40
|
-
|
|
41
|
-
// Immutable object containing the normalized cache of all data
|
|
42
|
-
// as well as all operations we're tracking within the application
|
|
43
|
-
);
|
|
44
|
-
// Immutable object containing the normalized cache of all data
|
|
45
|
-
// as well as all operations we're tracking within the application
|
|
46
|
-
_GraphQLQueryCache_cacheStore.set(this, void 0);
|
|
17
|
+
this._inFlight = {};
|
|
47
18
|
// Keeps track of all the operations that have been issued in the application,
|
|
48
19
|
// as well as the metadata indicating the TTL / polling / invalidation / refetch
|
|
49
20
|
// logic necessary to keep things up to date
|
|
50
|
-
|
|
51
|
-
_GraphQLQueryCache_queryInvalidation.set(this, void 0);
|
|
52
|
-
_GraphQLQueryCache_mutationInvalidation.set(this, void 0);
|
|
21
|
+
this._runtimeCache = {};
|
|
53
22
|
/**
|
|
54
23
|
* A list of all "effects" that have run, used to keep track of
|
|
55
24
|
*/
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
25
|
+
this._effectsIssued = []; // TODO: Include subscriptions
|
|
26
|
+
this._fetcher = config.fetcher;
|
|
27
|
+
this._endpoint = config.endpoint || `/graphql`;
|
|
28
|
+
this._persistedOperations = config.persistedOperations;
|
|
29
|
+
this._persistedDocuments = config.persistedDocuments;
|
|
30
|
+
this._configMeta = unwrapMeta(config.meta);
|
|
31
|
+
this._queryInvalidation = config.queryInvalidation ?? {};
|
|
32
|
+
this._mutationInvalidation = config.mutationInvalidation ?? {};
|
|
33
|
+
this._cacheStore = produce(config.hydratedCache ?? {
|
|
65
34
|
meta: {},
|
|
66
35
|
fields: {},
|
|
67
36
|
operations: {},
|
|
68
|
-
}, noop)
|
|
37
|
+
}, noop);
|
|
69
38
|
}
|
|
70
39
|
/**
|
|
71
40
|
* Invalidates a query by name or predicate fn
|
|
72
41
|
*/
|
|
73
42
|
invalidateQuery(toInvalidate) {
|
|
74
|
-
produce(
|
|
43
|
+
produce(this._runtimeCache, () => {
|
|
75
44
|
//
|
|
76
45
|
});
|
|
77
46
|
}
|
|
@@ -79,7 +48,7 @@ export class GraphQLQueryCache {
|
|
|
79
48
|
* Invalidates a query by name or predicate fn
|
|
80
49
|
*/
|
|
81
50
|
refetchQuery(toRefetch) {
|
|
82
|
-
produce(
|
|
51
|
+
produce(this._runtimeCache, () => {
|
|
83
52
|
//
|
|
84
53
|
});
|
|
85
54
|
}
|
|
@@ -88,7 +57,7 @@ export class GraphQLQueryCache {
|
|
|
88
57
|
* to rehydrate the Client
|
|
89
58
|
*/
|
|
90
59
|
toJSON() {
|
|
91
|
-
const { fields, operations, meta } =
|
|
60
|
+
const { fields, operations, meta } = this._cacheStore;
|
|
92
61
|
return {
|
|
93
62
|
fields,
|
|
94
63
|
operations: operations,
|
|
@@ -102,7 +71,7 @@ export class GraphQLQueryCache {
|
|
|
102
71
|
// queryName: Q,
|
|
103
72
|
// variable: SerializedVariables | GraphQLQuery.OperationVariables[Q]
|
|
104
73
|
// ) {
|
|
105
|
-
// // Object.values(this
|
|
74
|
+
// // Object.values(this._cacheStore.operations).find((o) => {
|
|
106
75
|
// // return o.operationType === 'query' && o
|
|
107
76
|
// // })
|
|
108
77
|
// }
|
|
@@ -126,19 +95,19 @@ export class GraphQLQueryCache {
|
|
|
126
95
|
*/
|
|
127
96
|
readQuery(args) {
|
|
128
97
|
const { queryName, variables, options } = args;
|
|
129
|
-
const key =
|
|
130
|
-
const op =
|
|
98
|
+
const key = this._getKey(queryName, variables);
|
|
99
|
+
const op = this._cacheStore.operations[key];
|
|
131
100
|
if (op) {
|
|
132
101
|
return op;
|
|
133
102
|
}
|
|
134
103
|
// If we don't have metadata, we can't know how to read the query
|
|
135
104
|
// from the cache
|
|
136
|
-
const meta =
|
|
105
|
+
const meta = this._getMeta(queryName);
|
|
137
106
|
const { result } = graphqlNormalize({
|
|
138
107
|
action: 'read',
|
|
139
108
|
variableValues: typeof variables === 'string' ? JSON.parse(variables) : variables,
|
|
140
109
|
meta: meta,
|
|
141
|
-
cache:
|
|
110
|
+
cache: this._cacheStore.fields,
|
|
142
111
|
isEqual,
|
|
143
112
|
});
|
|
144
113
|
return {
|
|
@@ -173,9 +142,9 @@ export class GraphQLQueryCache {
|
|
|
173
142
|
preloadQuery(queryName, options) {
|
|
174
143
|
const { blockIfStale = true } = options;
|
|
175
144
|
const variables = variableString(options.variables ?? {});
|
|
176
|
-
const sha256Hash =
|
|
145
|
+
const sha256Hash = this._persistedOperations[queryName];
|
|
177
146
|
const key = `${sha256Hash}:${variables}`;
|
|
178
|
-
const operation =
|
|
147
|
+
const operation = this._cacheStore.operations[key];
|
|
179
148
|
// TODO: Give an option to eager return if we already have the operation but it's stale
|
|
180
149
|
if (!operation || operation.stale) {
|
|
181
150
|
const inFlight = this.fetchQuery({ queryName, variables: variables, options: {} });
|
|
@@ -184,23 +153,27 @@ export class GraphQLQueryCache {
|
|
|
184
153
|
return operation;
|
|
185
154
|
}
|
|
186
155
|
fetchQuery(args) {
|
|
187
|
-
return
|
|
156
|
+
return this._executeOperation('query', args.queryName, args.variables, args.options);
|
|
188
157
|
}
|
|
189
158
|
/**
|
|
190
159
|
* Executes a mutation, returning the result of that mutation
|
|
191
160
|
*/
|
|
192
161
|
async executeMutation(mutationName, variables, options = {}) {
|
|
193
|
-
return
|
|
162
|
+
return this._executeOperation('mutation', mutationName, variables, options);
|
|
194
163
|
}
|
|
195
164
|
/**
|
|
196
165
|
* Executes a query, returning the result of that query
|
|
197
166
|
*/
|
|
198
167
|
async executeQuery(queryName, variables) {
|
|
199
|
-
return
|
|
168
|
+
return this._executeOperation('query', queryName, variables);
|
|
200
169
|
}
|
|
201
170
|
async executeSubscription() {
|
|
202
171
|
throw new Error('Not yet supported');
|
|
203
172
|
}
|
|
173
|
+
_getKey(operationName, variables) {
|
|
174
|
+
const sha256Hash = this._persistedOperations[operationName];
|
|
175
|
+
return `${sha256Hash}:${variableString(variables)}`;
|
|
176
|
+
}
|
|
204
177
|
/**
|
|
205
178
|
* "Subscribes" to a query, meaning that when there are updates to fields in the
|
|
206
179
|
* field cache, we'll re-materialize the known value of the query. We'll also
|
|
@@ -209,201 +182,216 @@ export class GraphQLQueryCache {
|
|
|
209
182
|
subscribeToQuery(args) {
|
|
210
183
|
var _a;
|
|
211
184
|
const { queryName, queryResult, variables, onUpdate, options } = args;
|
|
212
|
-
const key =
|
|
213
|
-
const queries = ((_a =
|
|
185
|
+
const key = this._getKey(queryName, variables);
|
|
186
|
+
const queries = ((_a = this._subscribedQueries)[key] ?? (_a[key] = []));
|
|
214
187
|
queries.push(args);
|
|
215
188
|
// Now that the component is subscribed, we can begin fetching,
|
|
216
189
|
// refetching, and otherwise managing the query
|
|
217
190
|
if (!queryResult) {
|
|
218
|
-
|
|
191
|
+
this.readOrFetchQuery(args);
|
|
219
192
|
}
|
|
220
193
|
else if (options.ttl) {
|
|
221
194
|
//
|
|
222
195
|
}
|
|
223
|
-
// this.fetchQuery(args)
|
|
224
196
|
return () => {
|
|
225
197
|
queries.splice(queries.indexOf(args), 1);
|
|
226
198
|
};
|
|
227
199
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
variables: operationVariables,
|
|
245
|
-
extensions: {
|
|
246
|
-
persistedQuery: { version: 1, sha256Hash },
|
|
247
|
-
},
|
|
248
|
-
});
|
|
249
|
-
__classPrivateFieldGet(this, _GraphQLQueryCache_inFlight, "f")[key] = operationInFlight;
|
|
250
|
-
const operationResult = await operationInFlight.finally(() => {
|
|
251
|
-
delete __classPrivateFieldGet(this, _GraphQLQueryCache_inFlight, "f")[key];
|
|
252
|
-
});
|
|
253
|
-
if (operationResult.fetchError) {
|
|
254
|
-
return operationResult;
|
|
255
|
-
}
|
|
256
|
-
const meta = operationResult.extensions?.['graphqlNormalizeMeta'] ??
|
|
257
|
-
__classPrivateFieldGet(this, _GraphQLQueryCache_instances, "m", _GraphQLQueryCache_getMeta).call(this, operationName);
|
|
258
|
-
// Ensure we have metadata to be able to normalize the operation in our cache
|
|
259
|
-
if (!meta) {
|
|
260
|
-
throw new MissingMetaError(operationName);
|
|
261
|
-
}
|
|
262
|
-
const lastCache = __classPrivateFieldGet(this, _GraphQLQueryCache_cacheStore, "f");
|
|
263
|
-
__classPrivateFieldSet(this, _GraphQLQueryCache_cacheStore, produce(__classPrivateFieldGet(this, _GraphQLQueryCache_cacheStore, "f"), (c) => {
|
|
264
|
-
const currentResult = c.operations[key];
|
|
265
|
-
const { added, modified, result } = graphqlNormalize({
|
|
266
|
-
action: 'write',
|
|
267
|
-
operationResult,
|
|
268
|
-
meta,
|
|
269
|
-
cache: c.fields,
|
|
270
|
-
variableValues: operationVariables,
|
|
271
|
-
currentResult,
|
|
272
|
-
isEqual,
|
|
200
|
+
async _executeOperation(operationType, operationName, variables) {
|
|
201
|
+
const sha256Hash = this._persistedOperations[operationName];
|
|
202
|
+
const key = this._getKey(operationName, variables);
|
|
203
|
+
const operationVariables = variableObject(variables);
|
|
204
|
+
assertOperationHash(sha256Hash, operationType, operationName);
|
|
205
|
+
const inFlight = this._inFlight[key];
|
|
206
|
+
if (operationType === 'query' && inFlight) {
|
|
207
|
+
return inFlight;
|
|
208
|
+
}
|
|
209
|
+
const operationInFlight = this._fetch({
|
|
210
|
+
query: '',
|
|
211
|
+
operationName,
|
|
212
|
+
variables: operationVariables,
|
|
213
|
+
extensions: {
|
|
214
|
+
persistedQuery: { version: 1, sha256Hash },
|
|
215
|
+
},
|
|
273
216
|
});
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
217
|
+
this._inFlight[key] = operationInFlight;
|
|
218
|
+
const operationResult = await operationInFlight.finally(() => {
|
|
219
|
+
delete this._inFlight[key];
|
|
220
|
+
});
|
|
221
|
+
if (operationResult.fetchError) {
|
|
222
|
+
return operationResult;
|
|
223
|
+
}
|
|
224
|
+
const meta = operationResult.extensions?.['graphqlNormalizeMeta'] ??
|
|
225
|
+
this._getMeta(operationName);
|
|
226
|
+
// Ensure we have metadata to be able to normalize the operation in our cache
|
|
227
|
+
if (!meta) {
|
|
228
|
+
throw new MissingMetaError(operationName);
|
|
229
|
+
}
|
|
230
|
+
const lastCache = this._cacheStore;
|
|
231
|
+
this._cacheStore = produce(this._cacheStore, (c) => {
|
|
232
|
+
const currentResult = c.operations[key];
|
|
233
|
+
const { added, modified, result } = graphqlNormalize({
|
|
234
|
+
action: 'write',
|
|
235
|
+
operationResult,
|
|
278
236
|
meta,
|
|
279
|
-
|
|
237
|
+
cache: c.fields,
|
|
280
238
|
variableValues: operationVariables,
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
239
|
+
currentResult,
|
|
240
|
+
isEqual,
|
|
241
|
+
});
|
|
242
|
+
//
|
|
243
|
+
if (operationType === 'query' && (added || modified)) {
|
|
244
|
+
c.operations[key] = {
|
|
245
|
+
stale: false,
|
|
246
|
+
meta,
|
|
247
|
+
operationName,
|
|
248
|
+
variableValues: operationVariables,
|
|
249
|
+
data: result,
|
|
250
|
+
errors: operationResult.errors,
|
|
251
|
+
extensions: operationResult.extensions,
|
|
252
|
+
operationType: operationType,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
// If we've modified anything in the cache, we also need to update any
|
|
256
|
+
// mounted queries
|
|
257
|
+
if (modified) {
|
|
258
|
+
for (const [k, val] of Object.entries(c.operations)) {
|
|
259
|
+
if (k === key || val.operationType !== 'query') {
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
//
|
|
263
|
+
if (val.data) {
|
|
264
|
+
const { result } = graphqlNormalize({
|
|
265
|
+
action: 'read',
|
|
266
|
+
currentResult: val.data,
|
|
267
|
+
cache: c.fields,
|
|
268
|
+
meta: val.meta,
|
|
269
|
+
variableValues: val.variableValues,
|
|
270
|
+
});
|
|
271
|
+
if (result !== val) {
|
|
272
|
+
val.data = result;
|
|
273
|
+
}
|
|
305
274
|
}
|
|
306
275
|
}
|
|
307
276
|
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
277
|
+
});
|
|
278
|
+
// If this was a mutation, we need to go through and determine if we need to mark
|
|
279
|
+
// any Queries as "stale", or eagerly refetch any of the queries
|
|
280
|
+
if (operationType === 'mutation') {
|
|
281
|
+
const toInvalidate = new Set();
|
|
282
|
+
const mutationName = operationName;
|
|
283
|
+
const mutationFn = this._mutationInvalidation?.[mutationName];
|
|
284
|
+
for (const [operationKey, operation] of Object.entries(this._cacheStore.operations)) {
|
|
285
|
+
if (operation.operationType !== 'query') {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const queryName = operation.operationName;
|
|
289
|
+
const queryVariables = operation.variableValues;
|
|
290
|
+
const queryFn = this._queryInvalidation[queryName];
|
|
291
|
+
if (queryFn?.(mutationName, operationVariables, queryVariables)) {
|
|
292
|
+
toInvalidate.add(operationKey);
|
|
293
|
+
}
|
|
294
|
+
if (mutationFn?.(queryName, queryVariables, operationVariables)) {
|
|
295
|
+
toInvalidate.add(operationKey);
|
|
296
|
+
}
|
|
325
297
|
}
|
|
326
|
-
if (
|
|
327
|
-
|
|
298
|
+
if (toInvalidate.size) {
|
|
299
|
+
this._cacheStore = produce(this._cacheStore, (o) => {
|
|
300
|
+
for (const key of toInvalidate) {
|
|
301
|
+
const op = o.operations[key];
|
|
302
|
+
if (op)
|
|
303
|
+
op.stale = true;
|
|
304
|
+
}
|
|
305
|
+
});
|
|
328
306
|
}
|
|
329
307
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}), "f");
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
// If we've updated any operations, we need to update any subscribed components
|
|
341
|
-
if (lastCache.operations !== __classPrivateFieldGet(this, _GraphQLQueryCache_cacheStore, "f").operations) {
|
|
342
|
-
for (const [key, val] of Object.entries(__classPrivateFieldGet(this, _GraphQLQueryCache_cacheStore, "f").operations)) {
|
|
343
|
-
if (__classPrivateFieldGet(this, _GraphQLQueryCache_cacheStore, "f").operations[key] !== lastCache.operations[key]) {
|
|
344
|
-
if (__classPrivateFieldGet(this, _GraphQLQueryCache_subscribedQueries, "f")[key]) {
|
|
345
|
-
__classPrivateFieldGet(this, _GraphQLQueryCache_subscribedQueries, "f")[key]?.forEach((o) => o.onUpdate(val));
|
|
308
|
+
// If we've updated any operations, we need to update any subscribed components
|
|
309
|
+
if (lastCache.operations !== this._cacheStore.operations) {
|
|
310
|
+
for (const [key, val] of Object.entries(this._cacheStore.operations)) {
|
|
311
|
+
if (this._cacheStore.operations[key] !== lastCache.operations[key]) {
|
|
312
|
+
if (this._subscribedQueries[key]) {
|
|
313
|
+
this._subscribedQueries[key]?.forEach((o) => o.onUpdate(val));
|
|
314
|
+
}
|
|
346
315
|
}
|
|
347
316
|
}
|
|
348
317
|
}
|
|
318
|
+
if (operationType === 'query') {
|
|
319
|
+
return this._cacheStore.operations[key];
|
|
320
|
+
}
|
|
321
|
+
return operationResult;
|
|
349
322
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
if (!meta) {
|
|
357
|
-
throw new MissingMetaError(opName);
|
|
323
|
+
_getMeta(opName) {
|
|
324
|
+
const meta = this._cacheStore.meta[opName] ?? this._configMeta?.[opName];
|
|
325
|
+
if (!meta) {
|
|
326
|
+
throw new MissingMetaError(opName);
|
|
327
|
+
}
|
|
328
|
+
return meta;
|
|
358
329
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
330
|
+
/**
|
|
331
|
+
* Handles "fetch", ensuring we catch network errors and handle non-200
|
|
332
|
+
* responses properly so we're able to forward these on in a normalized fashion
|
|
333
|
+
*/
|
|
334
|
+
async _fetch(body) {
|
|
335
|
+
let result;
|
|
336
|
+
try {
|
|
337
|
+
result = await this._makeFetch(body);
|
|
338
|
+
if (result.status === 200) {
|
|
339
|
+
const json = (await result.json());
|
|
340
|
+
return json;
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
return {
|
|
344
|
+
fetchError: {
|
|
345
|
+
name: 'ResponseError',
|
|
346
|
+
message: await result.text(),
|
|
347
|
+
status: result.status,
|
|
348
|
+
statusText: result.statusText,
|
|
349
|
+
},
|
|
350
|
+
};
|
|
351
|
+
}
|
|
378
352
|
}
|
|
379
|
-
|
|
353
|
+
catch (e) {
|
|
354
|
+
const error = e instanceof Error ? e : new Error(String(e));
|
|
380
355
|
return {
|
|
381
356
|
fetchError: {
|
|
382
|
-
name:
|
|
383
|
-
message:
|
|
384
|
-
|
|
385
|
-
|
|
357
|
+
name: error.name,
|
|
358
|
+
message: error.message,
|
|
359
|
+
stack: error.stack,
|
|
360
|
+
status: result?.status,
|
|
361
|
+
statusText: result?.statusText,
|
|
386
362
|
},
|
|
387
363
|
};
|
|
388
364
|
}
|
|
389
365
|
}
|
|
390
|
-
|
|
391
|
-
const
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
stack: error.stack,
|
|
397
|
-
status: result?.status,
|
|
398
|
-
statusText: result?.statusText,
|
|
366
|
+
_makeFetch(body) {
|
|
367
|
+
const reqInit = {
|
|
368
|
+
method: 'POST',
|
|
369
|
+
body: JSON.stringify(body),
|
|
370
|
+
headers: {
|
|
371
|
+
'content-type': 'application/json',
|
|
399
372
|
},
|
|
400
373
|
};
|
|
374
|
+
if (this._fetcher) {
|
|
375
|
+
return this._fetcher(this._endpoint, reqInit);
|
|
376
|
+
}
|
|
377
|
+
return fetch(this._endpoint, reqInit);
|
|
401
378
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
379
|
+
/**
|
|
380
|
+
* Determine whether we should refetch the query based on the
|
|
381
|
+
* current value of the query, and the options passed to the query
|
|
382
|
+
*/
|
|
383
|
+
_shouldRefetchQuery() {
|
|
384
|
+
//
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* "Garbage collection" for existing operations. If they have
|
|
388
|
+
* a TTL or are invalidated by other operations, and aren't mounted,
|
|
389
|
+
* then we can go ahead and sweep out any data we might have for them
|
|
390
|
+
*/
|
|
391
|
+
_gcOperations() {
|
|
392
|
+
//
|
|
393
|
+
}
|
|
394
|
+
}
|
|
407
395
|
function unwrapMeta(meta) {
|
|
408
396
|
if (!meta)
|
|
409
397
|
return meta;
|
package/mjs/graphqlHooks.js
CHANGED
|
@@ -62,6 +62,7 @@ export function usePersistedQuery(queryName, options) {
|
|
|
62
62
|
// or it is refetched
|
|
63
63
|
useEffect(() => {
|
|
64
64
|
return cache.subscribeToQuery({
|
|
65
|
+
queryResult,
|
|
65
66
|
queryName,
|
|
66
67
|
variables: variableString,
|
|
67
68
|
onUpdate: setQueryResult,
|
|
@@ -86,8 +87,15 @@ export function useLazyPersistedQuery(query) {
|
|
|
86
87
|
const [fetched, setIsFetched] = useState(false);
|
|
87
88
|
const [loading, setIsLoading] = useState(false);
|
|
88
89
|
const loadQuery = useCallback((variables) => {
|
|
89
|
-
return new Promise((resolve) => {
|
|
90
|
-
cache.readOrFetchQuery({
|
|
90
|
+
return new Promise((resolve, reject) => {
|
|
91
|
+
const result = cache.readOrFetchQuery({
|
|
92
|
+
queryName: query,
|
|
93
|
+
variables: serializeVariables(variables),
|
|
94
|
+
options: {},
|
|
95
|
+
});
|
|
96
|
+
// if ('then' in result && typeof result.then === 'function') {
|
|
97
|
+
// Promise.resolve(result).then(resolve, reject)
|
|
98
|
+
// }
|
|
91
99
|
});
|
|
92
100
|
}, [cache, query]);
|
|
93
101
|
const errors = undefined;
|
package/mjs/types.d.ts
CHANGED
|
@@ -167,7 +167,7 @@ export interface SubscribeToQueryArgs<Q extends keyof GraphQLQuery.QueryRegistry
|
|
|
167
167
|
/**
|
|
168
168
|
* The result of readQuery, used to check whether the query is stale
|
|
169
169
|
*/
|
|
170
|
-
queryResult?:
|
|
170
|
+
queryResult?: GraphQLOperationResult<Q>;
|
|
171
171
|
/**
|
|
172
172
|
* Invoked when the values for this query are updated
|
|
173
173
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphql-persisted",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "WIP: An Opinionated GraphQL Query Library, with a focus on fully persisted queries",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"graphql",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"tslib": "^2.5.0",
|
|
32
|
-
"graphql-normalize": "^0.2.
|
|
32
|
+
"graphql-normalize": "^0.2.2",
|
|
33
33
|
"lodash.isequal": "^4.5.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|