@graphql-box/worker-client 5.4.5 → 5.4.7

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@graphql-box/worker-client",
3
3
  "description": "The GraphQL Box web worker client module.",
4
- "version": "5.4.5",
4
+ "version": "5.4.7",
5
5
  "author": "Dylan Aubrey",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/badbatch/graphql-box",
@@ -41,18 +41,22 @@
41
41
  "iterall": "^1.3.0",
42
42
  "lodash-es": "^4.17.21",
43
43
  "uuid": "^11.0.3",
44
- "@graphql-box/core": "5.4.1",
45
- "@graphql-box/helpers": "5.4.1"
44
+ "@graphql-box/core": "5.4.2",
45
+ "@graphql-box/helpers": "5.4.2"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "graphql": "<17",
49
- "@graphql-box/client": "5.4.1"
49
+ "@graphql-box/cache-manager": "5.4.3",
50
+ "@graphql-box/client": "5.4.3",
51
+ "@graphql-box/request-parser": "5.4.2"
50
52
  },
51
53
  "devDependencies": {
52
54
  "cts-types": "^0.0.8",
53
55
  "del-cli": "^6.0.0",
54
56
  "graphql": "^16.9.0",
55
- "@graphql-box/client": "5.4.1"
57
+ "@graphql-box/cache-manager": "5.4.3",
58
+ "@graphql-box/request-parser": "5.4.2",
59
+ "@graphql-box/client": "5.4.3"
56
60
  },
57
61
  "keywords": [
58
62
  "client",
package/src/main.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  import { type CoreWorker } from '@cachemap/core-worker';
2
+ import { type CacheManagerDef } from '@graphql-box/cache-manager';
2
3
  import {
3
4
  type DebugManagerDef,
4
5
  type PartialRequestContext,
5
6
  type PartialRequestResult,
7
+ type PartialResponseData,
6
8
  REQUEST_RESOLVED,
9
+ type RawResponseDataWithMaybeCacheMetadata,
7
10
  type RequestContext,
8
11
  type RequestOptions,
9
12
  SUBSCRIPTION_RESOLVED,
@@ -17,6 +20,7 @@ import {
17
20
  isPlainObject,
18
21
  rehydrateCacheMetadata,
19
22
  } from '@graphql-box/helpers';
23
+ import { type RequestParserDef } from '@graphql-box/request-parser';
20
24
  import { EventEmitter } from 'eventemitter3';
21
25
  import { OperationTypeNode } from 'graphql';
22
26
  import { isError } from 'lodash-es';
@@ -34,8 +38,26 @@ import {
34
38
  } from './types.ts';
35
39
 
36
40
  export class WorkerClient {
37
- private static _getMessageContext({ hasDeferOrStream = false, requestID }: RequestContext): MessageContext {
38
- return { hasDeferOrStream, requestID };
41
+ private static _getMessageContext({
42
+ hasDeferOrStream = false,
43
+ operation,
44
+ requestID,
45
+ }: RequestContext): MessageContext {
46
+ return { hasDeferOrStream, operation, requestID };
47
+ }
48
+
49
+ private static _resolve(
50
+ { cacheMetadata, ...rest }: PartialResponseData,
51
+ options: RequestOptions,
52
+ { requestID }: RequestContext,
53
+ ): PartialRequestResult {
54
+ const result: PartialRequestResult = { ...rest, requestID };
55
+
56
+ if (options.returnCacheMetadata && cacheMetadata) {
57
+ result._cacheMetadata = cacheMetadata;
58
+ }
59
+
60
+ return result;
39
61
  }
40
62
 
41
63
  private _onMessage = ({ data }: MessageEvent<MessageResponsePayload>): void => {
@@ -92,16 +114,35 @@ export class WorkerClient {
92
114
  stats: { endTime: this._debugManager.now() },
93
115
  });
94
116
 
117
+ if (context.operation === OperationTypeNode.QUERY && pending.requestData && pending.options && pending.context) {
118
+ void this._cacheManager.cacheQuery(
119
+ pending.requestData,
120
+ undefined,
121
+ // Need to look at what type guards can be put in place
122
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
123
+ response as RawResponseDataWithMaybeCacheMetadata,
124
+ pending.options,
125
+ pending.context,
126
+ );
127
+ }
128
+
95
129
  pending.resolve(response);
96
130
  }
97
131
  };
98
132
 
133
+ /**
134
+ * This cache instance does not actually store anything itself,
135
+ * it is for communicating with the worker cache that the worker
136
+ * client is using within the worker.
137
+ */
99
138
  private _cache: CoreWorker;
139
+ private _cacheManager: CacheManagerDef;
100
140
  private _debugManager: DebugManagerDef | null;
101
141
  private _eventEmitter: EventEmitter;
102
142
  private _experimentalDeferStreamSupport: boolean;
103
143
  private _messageQueue: MessageRequestPayload[] = [];
104
144
  private _pending: PendingTracker = new Map();
145
+ private _requestParser: RequestParserDef;
105
146
  private _worker: Worker | undefined;
106
147
 
107
148
  constructor(options: UserOptions) {
@@ -115,6 +156,14 @@ export class WorkerClient {
115
156
  errors.push(new ArgsError('@graphql-box/worker-client expected options.cache.'));
116
157
  }
117
158
 
159
+ if (!('cacheManager' in options)) {
160
+ errors.push(new ArgsError('@graphql-box/worker-client expected options.cacheManager.'));
161
+ }
162
+
163
+ if (!('requestParser' in options)) {
164
+ errors.push(new ArgsError('@graphql-box/worker-client expected options.requestParser.'));
165
+ }
166
+
118
167
  if (!options.lazyWorkerInit && !('worker' in options)) {
119
168
  errors.push(new ArgsError('@graphql-box/worker-client expected options.worker.'));
120
169
  }
@@ -124,9 +173,11 @@ export class WorkerClient {
124
173
  }
125
174
 
126
175
  this._cache = options.cache;
176
+ this._cacheManager = options.cacheManager;
127
177
  this._debugManager = options.debugManager ?? null;
128
178
  this._eventEmitter = new EventEmitter();
129
179
  this._experimentalDeferStreamSupport = options.experimentalDeferStreamSupport ?? false;
180
+ this._requestParser = options.requestParser;
130
181
 
131
182
  if (typeof options.worker === 'function') {
132
183
  Promise.resolve(options.worker())
@@ -148,12 +199,16 @@ export class WorkerClient {
148
199
  return this._cache;
149
200
  }
150
201
 
202
+ get cacheManager(): CacheManagerDef {
203
+ return this._cacheManager;
204
+ }
205
+
151
206
  public async mutate(request: string, options: RequestOptions = {}, context: PartialRequestContext = {}) {
152
207
  return this._request(request, options, this._getRequestContext(OperationTypeNode.MUTATION, request, context));
153
208
  }
154
209
 
155
210
  public async query(request: string, options: RequestOptions = {}, context: PartialRequestContext = {}) {
156
- return this._request(request, options, this._getRequestContext(OperationTypeNode.QUERY, request, context));
211
+ return this._query(request, options, this._getRequestContext(OperationTypeNode.QUERY, request, context));
157
212
  }
158
213
 
159
214
  public async request(request: string, options: RequestOptions = {}, context: PartialRequestContext = {}) {
@@ -201,12 +256,59 @@ export class WorkerClient {
201
256
  };
202
257
  }
203
258
 
259
+ private async _query(
260
+ request: string,
261
+ options: RequestOptions,
262
+ context: RequestContext,
263
+ ): Promise<PartialRequestResult | AsyncIterableIterator<PartialRequestResult | undefined>> {
264
+ try {
265
+ const { ast, request: updateRequest } = this._requestParser.updateRequest(request, options, context);
266
+ const requestData = { ast, hash: hashRequest(updateRequest), request: updateRequest };
267
+ const checkResult = await this._cacheManager.checkQueryResponseCacheEntry(requestData.hash, options, context);
268
+
269
+ if (checkResult) {
270
+ return WorkerClient._resolve(checkResult, options, context);
271
+ }
272
+
273
+ return await new Promise((resolve: PendingResolver) => {
274
+ if (this._worker) {
275
+ this._worker.postMessage({
276
+ context: WorkerClient._getMessageContext(context),
277
+ method: REQUEST,
278
+ options,
279
+ request,
280
+ type: GRAPHQL_BOX,
281
+ });
282
+ } else {
283
+ this._messageQueue.push({
284
+ context: WorkerClient._getMessageContext(context),
285
+ method: REQUEST,
286
+ options,
287
+ request,
288
+ type: GRAPHQL_BOX,
289
+ });
290
+ }
291
+
292
+ this._pending.set(context.requestID, { context, options, requestData, resolve });
293
+ });
294
+ } catch (error) {
295
+ const confirmedError = isError(error)
296
+ ? error
297
+ : new Error('@graphql-box/worker-client request had an unexpected error.');
298
+
299
+ return { errors: [confirmedError], requestID: context.requestID };
300
+ }
301
+ }
302
+
204
303
  private _releaseMessageQueue(): void {
205
304
  if (!this._worker) {
206
305
  throw new Error('A worker is required for the WorkerClient to work correctly.');
207
306
  }
208
307
 
209
- for (const message of this._messageQueue) {
308
+ const messageQueue = [...this._messageQueue];
309
+ this._messageQueue = [];
310
+
311
+ for (const message of messageQueue) {
210
312
  this._worker.postMessage(message);
211
313
  }
212
314
  }
package/src/types.ts CHANGED
@@ -1,17 +1,26 @@
1
1
  import { type CoreWorker } from '@cachemap/core-worker';
2
+ import { type CacheManagerDef } from '@graphql-box/cache-manager';
2
3
  import { type Client } from '@graphql-box/client';
3
4
  import {
4
5
  type DebugManagerDef,
5
6
  type PartialRawFetchData,
6
7
  type PartialRequestResult,
8
+ type RequestContext,
9
+ type RequestData,
7
10
  type RequestOptions,
8
11
  } from '@graphql-box/core';
12
+ import { type RequestParserDef } from '@graphql-box/request-parser';
13
+ import { type OperationTypeNode } from 'graphql';
9
14
 
10
15
  export interface UserOptions {
11
16
  /**
12
17
  * The cache.
13
18
  */
14
19
  cache: CoreWorker;
20
+ /**
21
+ * The curried function to initialize the cache manager.
22
+ */
23
+ cacheManager: CacheManagerDef;
15
24
  /**
16
25
  * The debug manager.
17
26
  */
@@ -26,6 +35,10 @@ export interface UserOptions {
26
35
  * initialise the worker after the constructor.
27
36
  */
28
37
  lazyWorkerInit?: boolean;
38
+ /**
39
+ * The curried function to initialzie the request parser.
40
+ */
41
+ requestParser: RequestParserDef;
29
42
  /**
30
43
  * The web worker instance.
31
44
  */
@@ -39,6 +52,9 @@ export type PendingResolver = (
39
52
  ) => void;
40
53
 
41
54
  export interface PendingData {
55
+ context?: RequestContext;
56
+ options?: RequestOptions;
57
+ requestData?: RequestData;
42
58
  resolve: PendingResolver;
43
59
  }
44
60
 
@@ -61,6 +77,7 @@ export interface MessageResponsePayload {
61
77
 
62
78
  export interface MessageContext {
63
79
  hasDeferOrStream: boolean;
80
+ operation: OperationTypeNode;
64
81
  requestID: string;
65
82
  }
66
83