@graphql-tools/url-loader 7.5.3 → 7.6.0-alpha-2dcefe9f.0

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.
@@ -1 +1 @@
1
- export declare function addCancelToResponseStream<T>(resultStream: AsyncIterable<T>, controller: AbortController): AsyncIterator<T | undefined, any, undefined>;
1
+ export declare function addCancelToResponseStream<T>(resultStream: AsyncIterable<T>, controller: AbortController): AsyncIterable<T | undefined>;
@@ -1,2 +1,2 @@
1
1
  import { ExecutionResult } from 'graphql';
2
- export declare function handleEventStreamResponse(response: Response): Promise<AsyncIterableIterator<ExecutionResult>>;
2
+ export declare function handleEventStreamResponse(response: Response): Promise<AsyncGenerator<ExecutionResult>>;
@@ -1,3 +1 @@
1
- /// <reference types="node" />
2
- import type { Readable } from 'stream';
3
- export declare function handleReadable(readable: Readable): AsyncGenerator<any, void, unknown>;
1
+ export declare function handleReadable(readable: AsyncIterable<Uint8Array | string>): AsyncGenerator<any, void, unknown>;
@@ -1,2 +1,2 @@
1
- import { ExecutionResult } from 'graphql';
1
+ import type { ExecutionResult } from 'graphql';
2
2
  export declare function handleMultipartMixedResponse(response: Response): Promise<AsyncIterableIterator<ExecutionResult<import("graphql/jsutils/ObjMap").ObjMap<unknown>, import("graphql/jsutils/ObjMap").ObjMap<unknown>> | undefined>>;
package/index.js CHANGED
@@ -54,7 +54,6 @@ const defaultSyncFetch = (input, init) => {
54
54
  return syncFetchImported(input, init);
55
55
  };
56
56
 
57
- /* eslint-disable */
58
57
  function isIncomingMessage(body) {
59
58
  return body != null && typeof body === 'object' && 'pipe' in body;
60
59
  }
@@ -100,9 +99,11 @@ async function handleMultipartMixedResponse(response) {
100
99
  });
101
100
  }
102
101
 
102
+ /* eslint-disable no-labels */
103
103
  async function* handleReadable(readable) {
104
+ const decoder = new TextDecoder();
104
105
  outer: for await (const chunk of readable) {
105
- const chunkStr = chunk.toString();
106
+ const chunkStr = typeof chunk === 'string' ? chunk : decoder.decode(chunk);
106
107
  for (const part of chunkStr.split('\n\n')) {
107
108
  if (part) {
108
109
  const eventStr = part.split('event: ')[1];
@@ -166,12 +167,10 @@ async function* handleReadableStream(stream) {
166
167
  }
167
168
  break;
168
169
  }
169
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
170
- // @ts-ignore
171
170
  case 13 /* CarriageReturn */: {
172
171
  discardTrailingNewline = true;
172
+ break;
173
173
  }
174
- // eslint-disable-next-line no-fallthrough
175
174
  case 10 /* NewLine */: {
176
175
  lineEnd = position;
177
176
  break;
@@ -249,20 +248,34 @@ function concat(a, b) {
249
248
  return res;
250
249
  }
251
250
 
252
- /* eslint-disable */
253
251
  async function handleEventStreamResponse(response) {
252
+ // node-fetch returns body as a promise so we need to resolve it
254
253
  const body = await response.body;
255
254
  if (body) {
256
- if ('pipe' in body) {
255
+ if (utils.isAsyncIterable(body)) {
257
256
  return handleReadable(body);
258
257
  }
259
258
  return handleReadableStream(body);
260
259
  }
261
- throw new Error('Body is null???');
260
+ throw new Error('Response body is expected to be a readable stream but got; ' + utils.inspect(body));
262
261
  }
263
262
 
264
263
  function addCancelToResponseStream(resultStream, controller) {
265
- return utils.withCancel(resultStream, () => controller.abort());
264
+ return utils.withCancel(resultStream, () => {
265
+ if (!controller.signal.aborted) {
266
+ controller.abort();
267
+ }
268
+ });
269
+ }
270
+
271
+ function isBlob(obj) {
272
+ return typeof obj.arrayBuffer === 'function';
273
+ }
274
+ function isGraphQLUpload(upload) {
275
+ return typeof upload.createReadStream === 'function';
276
+ }
277
+ function isPromiseLike(obj) {
278
+ return typeof obj.then === 'function';
266
279
  }
267
280
 
268
281
  /* eslint-disable no-case-declarations */
@@ -333,18 +346,38 @@ class UrlLoader {
333
346
  extensions,
334
347
  }));
335
348
  form.append('map', JSON.stringify(map));
336
- return valueOrPromise.ValueOrPromise.all(uploads.map((u$, i) => new valueOrPromise.ValueOrPromise(() => u$).then(u => {
349
+ function handleUpload(upload, i) {
337
350
  const indexStr = i.toString();
338
- if (u != null && 'promise' in u) {
339
- return u.promise.then((upload) => {
351
+ if (upload != null) {
352
+ const filename = upload.filename || upload.name || upload.path || `blob-${indexStr}`;
353
+ if (isPromiseLike(upload)) {
354
+ return upload.then((resolvedUpload) => handleUpload(resolvedUpload, i));
355
+ // If Blob
356
+ }
357
+ else if (isBlob(upload)) {
358
+ return upload.arrayBuffer().then((arrayBuffer) => {
359
+ form.append(indexStr, new crossUndiciFetch.File([arrayBuffer], filename, { type: upload.type }), filename);
360
+ });
361
+ }
362
+ else if (isGraphQLUpload(upload)) {
340
363
  const stream = upload.createReadStream();
341
- form.append(indexStr, stream, upload.filename);
342
- });
343
- }
344
- else {
345
- form.append(indexStr, u, u.name || u.path || indexStr);
364
+ const chunks = [];
365
+ return Promise.resolve().then(async () => {
366
+ for await (const chunk of stream) {
367
+ if (chunk) {
368
+ chunks.push(...chunk);
369
+ }
370
+ }
371
+ const blobPart = new Uint8Array(chunks);
372
+ form.append(indexStr, new crossUndiciFetch.File([blobPart], filename, { type: upload.mimetype }), filename);
373
+ });
374
+ }
375
+ else {
376
+ form.append(indexStr, new crossUndiciFetch.File([upload], filename), filename);
377
+ }
346
378
  }
347
- })))
379
+ }
380
+ return valueOrPromise.ValueOrPromise.all(uploads.map((upload, i) => new valueOrPromise.ValueOrPromise(() => handleUpload(upload, i))))
348
381
  .then(() => form)
349
382
  .resolve();
350
383
  }
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { print, buildASTSchema, buildSchema } from 'graphql';
2
- import { mapAsyncIterator, withCancel, isAsyncIterable, observableToAsyncIterable, getOperationASTFromRequest, parseGraphQLSDL } from '@graphql-tools/utils';
2
+ import { mapAsyncIterator, isAsyncIterable, inspect, withCancel, observableToAsyncIterable, getOperationASTFromRequest, parseGraphQLSDL } from '@graphql-tools/utils';
3
3
  import { isWebUri } from 'valid-url';
4
4
  import { introspectSchema, wrapSchema } from '@graphql-tools/wrap';
5
5
  import { createClient } from 'graphql-ws';
@@ -9,7 +9,7 @@ import { extractFiles, isExtractableFile } from 'extract-files';
9
9
  import { SubscriptionClient } from 'subscriptions-transport-ws';
10
10
  import { ValueOrPromise } from 'value-or-promise';
11
11
  import { isLiveQueryOperationDefinitionNode } from '@n1ru4l/graphql-live-query';
12
- import { fetch, FormData, AbortController } from 'cross-undici-fetch';
12
+ import { fetch, FormData, AbortController, File } from 'cross-undici-fetch';
13
13
  import syncFetchImported from 'sync-fetch';
14
14
  import { meros } from 'meros/node';
15
15
  import { meros as meros$1 } from 'meros/browser';
@@ -29,7 +29,6 @@ const defaultSyncFetch = (input, init) => {
29
29
  return syncFetchImported(input, init);
30
30
  };
31
31
 
32
- /* eslint-disable */
33
32
  function isIncomingMessage(body) {
34
33
  return body != null && typeof body === 'object' && 'pipe' in body;
35
34
  }
@@ -75,9 +74,11 @@ async function handleMultipartMixedResponse(response) {
75
74
  });
76
75
  }
77
76
 
77
+ /* eslint-disable no-labels */
78
78
  async function* handleReadable(readable) {
79
+ const decoder = new TextDecoder();
79
80
  outer: for await (const chunk of readable) {
80
- const chunkStr = chunk.toString();
81
+ const chunkStr = typeof chunk === 'string' ? chunk : decoder.decode(chunk);
81
82
  for (const part of chunkStr.split('\n\n')) {
82
83
  if (part) {
83
84
  const eventStr = part.split('event: ')[1];
@@ -141,12 +142,10 @@ async function* handleReadableStream(stream) {
141
142
  }
142
143
  break;
143
144
  }
144
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
145
- // @ts-ignore
146
145
  case 13 /* CarriageReturn */: {
147
146
  discardTrailingNewline = true;
147
+ break;
148
148
  }
149
- // eslint-disable-next-line no-fallthrough
150
149
  case 10 /* NewLine */: {
151
150
  lineEnd = position;
152
151
  break;
@@ -224,20 +223,34 @@ function concat(a, b) {
224
223
  return res;
225
224
  }
226
225
 
227
- /* eslint-disable */
228
226
  async function handleEventStreamResponse(response) {
227
+ // node-fetch returns body as a promise so we need to resolve it
229
228
  const body = await response.body;
230
229
  if (body) {
231
- if ('pipe' in body) {
230
+ if (isAsyncIterable(body)) {
232
231
  return handleReadable(body);
233
232
  }
234
233
  return handleReadableStream(body);
235
234
  }
236
- throw new Error('Body is null???');
235
+ throw new Error('Response body is expected to be a readable stream but got; ' + inspect(body));
237
236
  }
238
237
 
239
238
  function addCancelToResponseStream(resultStream, controller) {
240
- return withCancel(resultStream, () => controller.abort());
239
+ return withCancel(resultStream, () => {
240
+ if (!controller.signal.aborted) {
241
+ controller.abort();
242
+ }
243
+ });
244
+ }
245
+
246
+ function isBlob(obj) {
247
+ return typeof obj.arrayBuffer === 'function';
248
+ }
249
+ function isGraphQLUpload(upload) {
250
+ return typeof upload.createReadStream === 'function';
251
+ }
252
+ function isPromiseLike(obj) {
253
+ return typeof obj.then === 'function';
241
254
  }
242
255
 
243
256
  /* eslint-disable no-case-declarations */
@@ -309,18 +322,38 @@ class UrlLoader {
309
322
  extensions,
310
323
  }));
311
324
  form.append('map', JSON.stringify(map));
312
- return ValueOrPromise.all(uploads.map((u$, i) => new ValueOrPromise(() => u$).then(u => {
325
+ function handleUpload(upload, i) {
313
326
  const indexStr = i.toString();
314
- if (u != null && 'promise' in u) {
315
- return u.promise.then((upload) => {
327
+ if (upload != null) {
328
+ const filename = upload.filename || upload.name || upload.path || `blob-${indexStr}`;
329
+ if (isPromiseLike(upload)) {
330
+ return upload.then((resolvedUpload) => handleUpload(resolvedUpload, i));
331
+ // If Blob
332
+ }
333
+ else if (isBlob(upload)) {
334
+ return upload.arrayBuffer().then((arrayBuffer) => {
335
+ form.append(indexStr, new File([arrayBuffer], filename, { type: upload.type }), filename);
336
+ });
337
+ }
338
+ else if (isGraphQLUpload(upload)) {
316
339
  const stream = upload.createReadStream();
317
- form.append(indexStr, stream, upload.filename);
318
- });
319
- }
320
- else {
321
- form.append(indexStr, u, u.name || u.path || indexStr);
340
+ const chunks = [];
341
+ return Promise.resolve().then(async () => {
342
+ for await (const chunk of stream) {
343
+ if (chunk) {
344
+ chunks.push(...chunk);
345
+ }
346
+ }
347
+ const blobPart = new Uint8Array(chunks);
348
+ form.append(indexStr, new File([blobPart], filename, { type: upload.mimetype }), filename);
349
+ });
350
+ }
351
+ else {
352
+ form.append(indexStr, new File([upload], filename), filename);
353
+ }
322
354
  }
323
- })))
355
+ }
356
+ return ValueOrPromise.all(uploads.map((upload, i) => new ValueOrPromise(() => handleUpload(upload, i))))
324
357
  .then(() => form)
325
358
  .resolve();
326
359
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-tools/url-loader",
3
- "version": "7.5.3",
3
+ "version": "7.6.0-alpha-2dcefe9f.0",
4
4
  "description": "A set of utils for faster development of GraphQL tools",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
@@ -10,22 +10,22 @@
10
10
  "@graphql-tools/delegate": "^8.4.1",
11
11
  "@graphql-tools/utils": "^8.5.1",
12
12
  "@graphql-tools/wrap": "^8.3.1",
13
- "@n1ru4l/graphql-live-query": "0.9.0",
14
- "@types/websocket": "1.0.4",
13
+ "@n1ru4l/graphql-live-query": "^0.9.0",
14
+ "@types/websocket": "^1.0.4",
15
15
  "@types/ws": "^8.0.0",
16
- "cross-undici-fetch": "^0.0.26",
16
+ "cross-undici-fetch": "^0.1.4",
17
17
  "dset": "^3.1.0",
18
- "extract-files": "11.0.0",
18
+ "extract-files": "^11.0.0",
19
19
  "graphql-sse": "^1.0.1",
20
20
  "graphql-ws": "^5.4.1",
21
- "isomorphic-ws": "4.0.1",
22
- "meros": "1.1.4",
21
+ "isomorphic-ws": "^4.0.1",
22
+ "meros": "^1.1.4",
23
23
  "subscriptions-transport-ws": "^0.11.0",
24
- "sync-fetch": "0.3.1",
25
- "tslib": "~2.3.0",
26
- "valid-url": "1.0.9",
27
- "value-or-promise": "1.0.11",
28
- "ws": "8.3.0"
24
+ "sync-fetch": "^0.3.1",
25
+ "tslib": "^2.3.0",
26
+ "valid-url": "^1.0.9",
27
+ "value-or-promise": "^1.0.11",
28
+ "ws": "^8.3.0"
29
29
  },
30
30
  "repository": {
31
31
  "type": "git",
package/utils.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /// <reference types="node" />
2
+ import type { Readable } from 'stream';
3
+ export declare function isBlob(obj: any): obj is Blob;
4
+ interface GraphQLUpload {
5
+ filename: string;
6
+ mimetype: string;
7
+ createReadStream: () => Readable;
8
+ }
9
+ export declare function isGraphQLUpload(upload: any): upload is GraphQLUpload;
10
+ export declare function isPromiseLike(obj: any): obj is PromiseLike<any>;
11
+ export {};