urql-computed-exchange-plus 1.0.3

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.
Files changed (64) hide show
  1. package/.editorconfig +9 -0
  2. package/.eslintrc.js +58 -0
  3. package/.importsortrc +6 -0
  4. package/.prettierrc +12 -0
  5. package/CHANGELOG.md +50 -0
  6. package/LICENSE +24 -0
  7. package/README.md +367 -0
  8. package/jest.config.js +19 -0
  9. package/jest.integration.config.js +14 -0
  10. package/jest.performance.config.js +19 -0
  11. package/lib/async-computed.d.ts +16 -0
  12. package/lib/async-computed.js +68 -0
  13. package/lib/async-computed.js.map +1 -0
  14. package/lib/computed-exchange.d.ts +5 -0
  15. package/lib/computed-exchange.js +24 -0
  16. package/lib/computed-exchange.js.map +1 -0
  17. package/lib/create-entity.d.ts +2 -0
  18. package/lib/create-entity.js +7 -0
  19. package/lib/create-entity.js.map +1 -0
  20. package/lib/create-modern-entity.d.ts +2 -0
  21. package/lib/create-modern-entity.js +10 -0
  22. package/lib/create-modern-entity.js.map +1 -0
  23. package/lib/directive-utils.d.ts +6 -0
  24. package/lib/directive-utils.js +125 -0
  25. package/lib/directive-utils.js.map +1 -0
  26. package/lib/index.d.ts +6 -0
  27. package/lib/index.js +23 -0
  28. package/lib/index.js.map +1 -0
  29. package/lib/merge-entities.d.ts +2 -0
  30. package/lib/merge-entities.js +35 -0
  31. package/lib/merge-entities.js.map +1 -0
  32. package/lib/resolve-data.d.ts +2 -0
  33. package/lib/resolve-data.js +152 -0
  34. package/lib/resolve-data.js.map +1 -0
  35. package/lib/set-utils.d.ts +5 -0
  36. package/lib/set-utils.js +27 -0
  37. package/lib/set-utils.js.map +1 -0
  38. package/lib/tsconfig.tsbuildinfo +1 -0
  39. package/lib/types/augmented-operation-result.d.ts +6 -0
  40. package/lib/types/augmented-operation-result.js +3 -0
  41. package/lib/types/augmented-operation-result.js.map +1 -0
  42. package/lib/types/augmented-operation.d.ts +6 -0
  43. package/lib/types/augmented-operation.js +3 -0
  44. package/lib/types/augmented-operation.js.map +1 -0
  45. package/lib/types/entity.d.ts +13 -0
  46. package/lib/types/entity.js +3 -0
  47. package/lib/types/entity.js.map +1 -0
  48. package/lib/types/index.d.ts +4 -0
  49. package/lib/types/index.js +21 -0
  50. package/lib/types/index.js.map +1 -0
  51. package/lib/types/node-with-directives.d.ts +2 -0
  52. package/lib/types/node-with-directives.js +3 -0
  53. package/lib/types/node-with-directives.js.map +1 -0
  54. package/lib/types.d.ts +68 -0
  55. package/lib/types.js +18 -0
  56. package/lib/types.js.map +1 -0
  57. package/package.json +77 -0
  58. package/test/integration/computed-exchange.test.ts +541 -0
  59. package/test/performance/large-dataset.test.ts +66 -0
  60. package/test/utils/index.ts +2 -0
  61. package/test/utils/run-query.ts +15 -0
  62. package/test/utils/simple-mock-fetch.ts +75 -0
  63. package/tsconfig.build.json +4 -0
  64. package/tsconfig.json +29 -0
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "urql-computed-exchange-plus",
3
+ "version": "1.0.3",
4
+ "description": "URQL exchange to allow computed properties in GraphQL queries. Maintained fork with updated dependencies.",
5
+ "keywords": [
6
+ "urql",
7
+ "graphql",
8
+ "computed",
9
+ "exchange",
10
+ "resolver"
11
+ ],
12
+ "license": "MIT",
13
+ "main": "lib/index.js",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/royalcala/urql-computed-exchange-plus"
17
+ },
18
+ "scripts": {
19
+ "clean": "rimraf lib/",
20
+ "build": "tsc",
21
+ "build:watch": "tsc -w",
22
+ "test": "jest",
23
+ "test:watch": "jest --watch",
24
+ "test:integration": "jest --config ./jest.integration.config.js",
25
+ "test:integration:watch": "jest --config ./jest.integration.config.js --watch",
26
+ "test:performance": "jest --config ./jest.performance.config.js --testTimeout=15000",
27
+ "test:all": "npm test && npm run test:integration && npm run test:performance",
28
+ "lint": "eslint src --ext .ts",
29
+ "lint:fix": "eslint src --ext .ts --fix",
30
+ "release": "npm run test:all && npm run build && npm publish",
31
+ "release:patch": "npm version patch && npm run release",
32
+ "release:minor": "npm version minor && npm run release",
33
+ "release:major": "npm version major && npm run release",
34
+ "prepublishOnly": "npm run test:all && npm run build",
35
+ "prepare": "husky install"
36
+ },
37
+ "lint-staged": {
38
+ "*.{ts,tsx}": [
39
+ "eslint --ext ts,tsx --format node_modules/eslint-formatter-pretty -c .eslintrc.js --max-warnings=0",
40
+ "prettier --write"
41
+ ]
42
+ },
43
+ "peerDependencies": {
44
+ "graphql": "^15.0.0 || ^16.0.0",
45
+ "urql": "^3.0.0 || ^4.0.0 || ^5.0.0",
46
+ "wonka": "^6.0.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/jest": "^30.0.0",
50
+ "@types/lodash": "^4.17.21",
51
+ "@types/react": "^18.0.0",
52
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
53
+ "@typescript-eslint/parser": "^8.0.0",
54
+ "eslint": "^9.0.0",
55
+ "eslint-formatter-pretty": "^7.0.0",
56
+ "eslint-plugin-jest": "^29.0.0",
57
+ "fraql": "^1.2.1",
58
+ "graphql": "^16.0.0",
59
+ "graphql-tag": "^2.12.6",
60
+ "husky": "^9.0.0",
61
+ "import-sort-style-module": "^6.0.0",
62
+ "jest": "^30.0.0",
63
+ "lint-staged": "^16.0.0",
64
+ "prettier": "^3.0.0",
65
+ "prettier-plugin-import-sort": "^0.0.7",
66
+ "react": "^18.0.0",
67
+ "rimraf": "^6.0.0",
68
+ "ts-jest": "^29.0.0",
69
+ "typescript": "^5.0.0",
70
+ "urql": "^5.0.0",
71
+ "wonka": "^6.0.0"
72
+ },
73
+ "dependencies": {
74
+ "fclone": "^1.0.11",
75
+ "graphql-anywhere": "^4.2.6"
76
+ }
77
+ }
@@ -0,0 +1,541 @@
1
+ import gql from 'fraql';
2
+ import { Client, cacheExchange, createClient, fetchExchange } from 'urql';
3
+
4
+ import { computedExchange, createEntity } from '../../src';
5
+ import { createMockFetch, runQuery } from '../utils';
6
+
7
+ describe('urql-computed-exchange', () => {
8
+ describe('computed-exchange', () => {
9
+ describe('computedExchange', () => {
10
+ let client: Client;
11
+ let entities: any;
12
+
13
+ beforeAll(() => {
14
+ entities = {
15
+ User: createEntity('User', {
16
+ fullName: {
17
+ dependencies: gql`
18
+ fragment _ on User {
19
+ firstName
20
+ lastName
21
+ }
22
+ `,
23
+ resolver: (user: any) => `${user.firstName} ${user.lastName}`,
24
+ },
25
+ }),
26
+ };
27
+
28
+ client = createClient({
29
+ url: '/graphql',
30
+ fetch: createMockFetch()
31
+ .post('/graphql', {
32
+ status: 200,
33
+ json: async () => ({
34
+ data: {
35
+ user: {
36
+ id: 1,
37
+ firstName: 'Lorem',
38
+ lastName: 'Ipsum',
39
+ __typename: 'User',
40
+ },
41
+ },
42
+ }),
43
+ })
44
+ .build(),
45
+ exchanges: [cacheExchange, computedExchange({ entities }), fetchExchange],
46
+ preferGetMethod: false,
47
+ });
48
+ });
49
+
50
+ it('runs queries without computed properties', async () => {
51
+ const query = gql`
52
+ query User {
53
+ user(id: "id") {
54
+ id
55
+ firstName
56
+ lastName
57
+ }
58
+ }
59
+ `;
60
+
61
+ const result = await runQuery(client, query);
62
+ const { data } = result;
63
+ expect(data).toMatchObject({
64
+ user: {
65
+ id: 1,
66
+ firstName: 'Lorem',
67
+ lastName: 'Ipsum',
68
+ },
69
+ });
70
+ });
71
+
72
+ it('runs queries with computed properties', async () => {
73
+ const query = gql`
74
+ query User {
75
+ user(id: "id") {
76
+ id
77
+ firstName
78
+ lastName
79
+ fullName @computed(type: User)
80
+ }
81
+ }
82
+ `;
83
+
84
+ const { data } = await runQuery(client, query);
85
+ expect(data).toMatchObject({
86
+ user: {
87
+ id: 1,
88
+ firstName: 'Lorem',
89
+ lastName: 'Ipsum',
90
+ fullName: 'Lorem Ipsum',
91
+ },
92
+ });
93
+ });
94
+
95
+ it('handles complex computed property chains', async () => {
96
+ const chainEntities = {
97
+ User: createEntity('User', {
98
+ fullName: {
99
+ dependencies: gql`
100
+ fragment _ on User {
101
+ firstName
102
+ lastName
103
+ }
104
+ `,
105
+ resolver: (user: any) => `${user.firstName} ${user.lastName}`,
106
+ },
107
+ displayName: {
108
+ dependencies: gql`
109
+ fragment _ on User {
110
+ fullName @computed(type: User)
111
+ title
112
+ }
113
+ `,
114
+ resolver: (user: any) => `${user.title} ${user.fullName}`,
115
+ },
116
+ signature: {
117
+ dependencies: gql`
118
+ fragment _ on User {
119
+ displayName @computed(type: User)
120
+ department
121
+ }
122
+ `,
123
+ resolver: (user: any) => `${user.displayName} - ${user.department}`,
124
+ },
125
+ }),
126
+ };
127
+
128
+ const chainClient = createClient({
129
+ url: '/graphql',
130
+ fetch: createMockFetch()
131
+ .post('/graphql', {
132
+ status: 200,
133
+ json: async () => ({
134
+ data: {
135
+ user: {
136
+ id: 1,
137
+ firstName: 'John',
138
+ lastName: 'Doe',
139
+ title: 'Dr.',
140
+ department: 'Engineering',
141
+ __typename: 'User',
142
+ },
143
+ },
144
+ }),
145
+ })
146
+ .build(),
147
+ exchanges: [cacheExchange, computedExchange({ entities: chainEntities }), fetchExchange],
148
+ preferGetMethod: false,
149
+ });
150
+
151
+ const query = gql`
152
+ query User {
153
+ user(id: "id") {
154
+ id
155
+ signature @computed(type: User)
156
+ }
157
+ }
158
+ `;
159
+
160
+ const { data } = await runQuery(chainClient, query);
161
+ expect(data).toMatchObject({
162
+ user: {
163
+ id: 1,
164
+ signature: 'Dr. John Doe - Engineering',
165
+ },
166
+ });
167
+ });
168
+
169
+ it('handles multiple computed properties on same object', async () => {
170
+ const query = gql`
171
+ query User {
172
+ user(id: "id") {
173
+ id
174
+ fullName @computed(type: User)
175
+ fullName2: fullName @computed(type: User)
176
+ fullName3: fullName @computed(type: User)
177
+ }
178
+ }
179
+ `;
180
+
181
+ const { data } = await runQuery(client, query);
182
+ expect(data).toMatchObject({
183
+ user: {
184
+ id: 1,
185
+ fullName: 'Lorem Ipsum',
186
+ fullName2: 'Lorem Ipsum',
187
+ fullName3: 'Lorem Ipsum',
188
+ },
189
+ });
190
+ });
191
+
192
+ it('handles arrays with computed properties', async () => {
193
+ const arrayClient = createClient({
194
+ url: '/graphql',
195
+ fetch: createMockFetch()
196
+ .post('/graphql', {
197
+ status: 200,
198
+ json: async () => ({
199
+ data: {
200
+ users: [
201
+ {
202
+ id: 1,
203
+ firstName: 'John',
204
+ lastName: 'Doe',
205
+ __typename: 'User',
206
+ },
207
+ {
208
+ id: 2,
209
+ firstName: 'Jane',
210
+ lastName: 'Smith',
211
+ __typename: 'User',
212
+ },
213
+ ],
214
+ },
215
+ }),
216
+ })
217
+ .build(),
218
+ exchanges: [cacheExchange, computedExchange({ entities }), fetchExchange],
219
+ preferGetMethod: false,
220
+ });
221
+
222
+ const query = gql`
223
+ query Users {
224
+ users {
225
+ id
226
+ fullName @computed(type: User)
227
+ }
228
+ }
229
+ `;
230
+
231
+ const { data } = await runQuery(arrayClient, query);
232
+ expect(data).toMatchObject({
233
+ users: [
234
+ { id: 1, fullName: 'John Doe' },
235
+ { id: 2, fullName: 'Jane Smith' },
236
+ ],
237
+ });
238
+ });
239
+ });
240
+
241
+ describe('error handling', () => {
242
+ it.skip('handles circular dependencies gracefully', async () => {
243
+ // This test verifies that circular dependencies don't cause infinite loops
244
+ // and that the exchange fails gracefully rather than hanging
245
+ const circularEntities = {
246
+ User: createEntity('User', {
247
+ fieldA: {
248
+ dependencies: gql`
249
+ fragment _ on User {
250
+ fieldB @computed(type: User)
251
+ }
252
+ `,
253
+ resolver: (user: any) => `A-${user.fieldB}`,
254
+ },
255
+ fieldB: {
256
+ dependencies: gql`
257
+ fragment _ on User {
258
+ fieldA @computed(type: User)
259
+ }
260
+ `,
261
+ resolver: (user: any) => `B-${user.fieldA}`,
262
+ },
263
+ }),
264
+ };
265
+
266
+ const circularClient = createClient({
267
+ url: '/graphql',
268
+ fetch: createMockFetch()
269
+ .post('/graphql', {
270
+ status: 200,
271
+ json: async () => ({
272
+ data: {
273
+ user: {
274
+ id: 1,
275
+ __typename: 'User',
276
+ },
277
+ },
278
+ }),
279
+ })
280
+ .build(),
281
+ exchanges: [cacheExchange, computedExchange({ entities: circularEntities }), fetchExchange],
282
+ preferGetMethod: false,
283
+ });
284
+
285
+ const query = gql`
286
+ query User {
287
+ user(id: "id") {
288
+ id
289
+ fieldA @computed(type: User)
290
+ }
291
+ }
292
+ `;
293
+
294
+ // The test should complete within a reasonable time and not hang
295
+ // We expect either an error result or the query to fail gracefully
296
+ const startTime = Date.now();
297
+
298
+ try {
299
+ const result = await runQuery(circularClient, query);
300
+ const endTime = Date.now();
301
+
302
+ // Should complete quickly (within 5 seconds)
303
+ expect(endTime - startTime).toBeLessThan(5000);
304
+
305
+ // Should have an error due to circular dependency
306
+ expect(result.error).toBeDefined();
307
+ } catch (error: any) {
308
+ const endTime = Date.now();
309
+
310
+ // Should complete quickly (within 5 seconds)
311
+ expect(endTime - startTime).toBeLessThan(5000);
312
+
313
+ // Should be a circular dependency related error
314
+ expect(error.message).toMatch(/circular|dependency|iteration|irresoluble/i);
315
+ }
316
+ }, 6000); // 6 second timeout
317
+
318
+ it('handles missing dependencies gracefully', async () => {
319
+ const entitiesWithMissingDeps = {
320
+ User: createEntity('User', {
321
+ computedField: {
322
+ dependencies: gql`
323
+ fragment _ on User {
324
+ nonExistentField
325
+ }
326
+ `,
327
+ resolver: (user: any) => user.nonExistentField || 'fallback',
328
+ },
329
+ }),
330
+ };
331
+
332
+ const missingDepsClient = createClient({
333
+ url: '/graphql',
334
+ fetch: createMockFetch()
335
+ .post('/graphql', {
336
+ status: 200,
337
+ json: async () => ({
338
+ data: {
339
+ user: {
340
+ id: 1,
341
+ firstName: 'John',
342
+ __typename: 'User',
343
+ },
344
+ },
345
+ }),
346
+ })
347
+ .build(),
348
+ exchanges: [cacheExchange, computedExchange({ entities: entitiesWithMissingDeps }), fetchExchange],
349
+ preferGetMethod: false,
350
+ });
351
+
352
+ const query = gql`
353
+ query User {
354
+ user(id: "id") {
355
+ id
356
+ computedField @computed(type: User)
357
+ }
358
+ }
359
+ `;
360
+
361
+ const { data } = await runQuery(missingDepsClient, query);
362
+ expect(data).toMatchObject({
363
+ user: {
364
+ id: 1,
365
+ computedField: 'fallback',
366
+ },
367
+ });
368
+ });
369
+
370
+ it('handles resolver errors gracefully', async () => {
371
+ const entitiesWithErrorResolver = {
372
+ User: createEntity('User', {
373
+ errorField: {
374
+ dependencies: gql`
375
+ fragment _ on User {
376
+ firstName
377
+ }
378
+ `,
379
+ resolver: () => {
380
+ throw new Error('Resolver error');
381
+ },
382
+ },
383
+ }),
384
+ };
385
+
386
+ const errorClient = createClient({
387
+ url: '/graphql',
388
+ fetch: createMockFetch()
389
+ .post('/graphql', {
390
+ status: 200,
391
+ json: async () => ({
392
+ data: {
393
+ user: {
394
+ id: 1,
395
+ firstName: 'John',
396
+ __typename: 'User',
397
+ },
398
+ },
399
+ }),
400
+ })
401
+ .build(),
402
+ exchanges: [cacheExchange, computedExchange({ entities: entitiesWithErrorResolver }), fetchExchange],
403
+ preferGetMethod: false,
404
+ });
405
+
406
+ const query = gql`
407
+ query User {
408
+ user(id: "id") {
409
+ id
410
+ errorField @computed(type: User)
411
+ }
412
+ }
413
+ `;
414
+
415
+ // This should not crash the entire query
416
+ const result = await runQuery(errorClient, query);
417
+ // The resolver error should result in the field being omitted or undefined
418
+ expect(result.data).toMatchObject({
419
+ user: {
420
+ id: 1,
421
+ },
422
+ });
423
+ // The errorField should either be undefined or not present
424
+ expect(result.data?.user?.errorField).toBeUndefined();
425
+ });
426
+ });
427
+
428
+ describe('caching behavior', () => {
429
+ let entities: any;
430
+
431
+ beforeAll(() => {
432
+ entities = {
433
+ User: createEntity('User', {
434
+ fullName: {
435
+ dependencies: gql`
436
+ fragment _ on User {
437
+ firstName
438
+ lastName
439
+ }
440
+ `,
441
+ resolver: (user: any) => `${user.firstName} ${user.lastName}`,
442
+ },
443
+ }),
444
+ };
445
+ });
446
+
447
+ it('respects cache-first policy for computed properties', async () => {
448
+ let fetchCount = 0;
449
+ const cacheClient = createClient({
450
+ url: '/graphql',
451
+ fetch: createMockFetch()
452
+ .post('/graphql', {
453
+ status: 200,
454
+ json: async () => {
455
+ fetchCount++;
456
+ return {
457
+ data: {
458
+ user: {
459
+ id: 1,
460
+ firstName: 'John',
461
+ lastName: 'Doe',
462
+ __typename: 'User',
463
+ },
464
+ },
465
+ };
466
+ },
467
+ })
468
+ .build(),
469
+ exchanges: [cacheExchange, computedExchange({ entities }), fetchExchange],
470
+ preferGetMethod: false,
471
+ });
472
+
473
+ const query = gql`
474
+ query User {
475
+ user(id: "id") {
476
+ id
477
+ fullName @computed(type: User)
478
+ }
479
+ }
480
+ `;
481
+
482
+ // First query
483
+ const result1 = await runQuery(cacheClient, query);
484
+ expect(result1.data).toMatchObject({
485
+ user: { id: 1, fullName: 'John Doe' },
486
+ });
487
+ expect(fetchCount).toBe(1);
488
+
489
+ // Second query should use cache
490
+ const result2 = await runQuery(cacheClient, query);
491
+ expect(result2.data).toMatchObject({
492
+ user: { id: 1, fullName: 'John Doe' },
493
+ });
494
+ expect(fetchCount).toBe(1); // Should still be 1 due to caching
495
+ });
496
+
497
+ it('works with different request policies', async () => {
498
+ let fetchCount = 0;
499
+ const networkClient = createClient({
500
+ url: '/graphql',
501
+ fetch: createMockFetch()
502
+ .post('/graphql', {
503
+ status: 200,
504
+ json: async () => {
505
+ fetchCount++;
506
+ return {
507
+ data: {
508
+ user: {
509
+ id: 1,
510
+ firstName: 'John',
511
+ lastName: 'Doe',
512
+ __typename: 'User',
513
+ },
514
+ },
515
+ };
516
+ },
517
+ })
518
+ .build(),
519
+ exchanges: [cacheExchange, computedExchange({ entities }), fetchExchange],
520
+ preferGetMethod: false,
521
+ });
522
+
523
+ const query = gql`
524
+ query User {
525
+ user(id: "id") {
526
+ id
527
+ fullName @computed(type: User)
528
+ }
529
+ }
530
+ `;
531
+
532
+ // Test with network-only policy
533
+ const result = await runQuery(networkClient, query, {}, { requestPolicy: 'network-only' });
534
+ expect(result.data).toMatchObject({
535
+ user: { id: 1, fullName: 'John Doe' },
536
+ });
537
+ expect(fetchCount).toBe(1);
538
+ });
539
+ });
540
+ });
541
+ });
@@ -0,0 +1,66 @@
1
+ import gql from 'fraql';
2
+ import { createClient, cacheExchange, fetchExchange } from 'urql';
3
+
4
+ import { computedExchange, createEntity } from '../../src';
5
+ import { createMockFetch, runQuery } from '../utils';
6
+
7
+ describe('Performance Tests', () => {
8
+ it('handles large datasets efficiently', async () => {
9
+ const entities = {
10
+ User: createEntity('User', {
11
+ fullName: {
12
+ dependencies: gql`
13
+ fragment _ on User {
14
+ firstName
15
+ lastName
16
+ }
17
+ `,
18
+ resolver: (user: any) => `${user.firstName} ${user.lastName}`,
19
+ },
20
+ }),
21
+ };
22
+
23
+ // Generate large dataset
24
+ const users = Array.from({ length: 1000 }, (_, i) => ({
25
+ id: i + 1,
26
+ firstName: `User${i}`,
27
+ lastName: `LastName${i}`,
28
+ __typename: 'User',
29
+ }));
30
+
31
+ const client = createClient({
32
+ url: '/graphql',
33
+ fetch: createMockFetch()
34
+ .post('/graphql', {
35
+ status: 200,
36
+ json: async () => ({
37
+ data: { users },
38
+ }),
39
+ })
40
+ .build(),
41
+ exchanges: [cacheExchange, computedExchange({ entities }), fetchExchange],
42
+ preferGetMethod: false,
43
+ });
44
+
45
+ const query = gql`
46
+ query Users {
47
+ users {
48
+ id
49
+ fullName @computed(type: User)
50
+ }
51
+ }
52
+ `;
53
+
54
+ const startTime = Date.now();
55
+ const { data } = await runQuery(client, query);
56
+ const endTime = Date.now();
57
+
58
+ // Should complete within reasonable time
59
+ expect(endTime - startTime).toBeLessThan(5000);
60
+
61
+ // Verify data integrity
62
+ expect(data.users).toHaveLength(1000);
63
+ expect(data.users[0].fullName).toBe('User0 LastName0');
64
+ expect(data.users[999].fullName).toBe('User999 LastName999');
65
+ }, 10000);
66
+ });
@@ -0,0 +1,2 @@
1
+ export * from './run-query';
2
+ export * from './simple-mock-fetch';
@@ -0,0 +1,15 @@
1
+ import { DocumentNode } from 'graphql';
2
+ import { Client, OperationResult, createRequest } from 'urql';
3
+ import { pipe, subscribe } from 'wonka';
4
+
5
+ export function runQuery(client: Client, query: string | DocumentNode, variables: any = {}, context: any = {}) {
6
+ const request = createRequest(query, variables);
7
+ return new Promise<OperationResult>((resolve) => {
8
+ pipe(
9
+ client.executeQuery(request, context),
10
+ subscribe((res) => {
11
+ resolve(res);
12
+ }),
13
+ );
14
+ });
15
+ }