@graphql-tools/url-loader 7.10.0 → 7.11.0-alpha-6c480b2d.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.
- package/cjs/addCancelToResponseStream.js +12 -0
- package/cjs/defaultAsyncFetch.js +8 -0
- package/cjs/defaultSyncFetch.js +15 -0
- package/cjs/event-stream/handleEventStreamResponse.js +18 -0
- package/cjs/event-stream/handleReadable.js +31 -0
- package/cjs/event-stream/handleReadableStream.js +131 -0
- package/cjs/handleMultipartMixedResponse.js +52 -0
- package/{index.js → cjs/index.js} +81 -358
- package/cjs/package.json +1 -0
- package/cjs/utils.js +28 -0
- package/esm/addCancelToResponseStream.js +8 -0
- package/esm/defaultAsyncFetch.js +4 -0
- package/esm/defaultSyncFetch.js +10 -0
- package/esm/event-stream/handleEventStreamResponse.js +14 -0
- package/esm/event-stream/handleReadable.js +27 -0
- package/esm/event-stream/handleReadableStream.js +127 -0
- package/esm/handleMultipartMixedResponse.js +48 -0
- package/{index.mjs → esm/index.js} +12 -270
- package/esm/utils.js +22 -0
- package/package.json +35 -14
- package/{addCancelToResponseStream.d.ts → typings/addCancelToResponseStream.d.ts} +0 -0
- package/{defaultAsyncFetch.d.ts → typings/defaultAsyncFetch.d.ts} +0 -0
- package/{defaultSyncFetch.d.ts → typings/defaultSyncFetch.d.ts} +0 -0
- package/{event-stream → typings/event-stream}/handleEventStreamResponse.d.ts +0 -0
- package/{event-stream → typings/event-stream}/handleReadable.d.ts +0 -0
- package/{event-stream → typings/event-stream}/handleReadableStream.d.ts +0 -0
- package/{handleMultipartMixedResponse.d.ts → typings/handleMultipartMixedResponse.d.ts} +0 -0
- package/{index.d.ts → typings/index.d.ts} +2 -2
- /package/{utils.d.ts → typings/utils.d.ts} +0 -0
package/cjs/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
package/cjs/utils.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LEGACY_WS = exports.isPromiseLike = exports.isGraphQLUpload = exports.isBlob = void 0;
|
|
4
|
+
function isBlob(obj) {
|
|
5
|
+
return typeof obj.arrayBuffer === 'function';
|
|
6
|
+
}
|
|
7
|
+
exports.isBlob = isBlob;
|
|
8
|
+
function isGraphQLUpload(upload) {
|
|
9
|
+
return typeof upload.createReadStream === 'function';
|
|
10
|
+
}
|
|
11
|
+
exports.isGraphQLUpload = isGraphQLUpload;
|
|
12
|
+
function isPromiseLike(obj) {
|
|
13
|
+
return typeof obj.then === 'function';
|
|
14
|
+
}
|
|
15
|
+
exports.isPromiseLike = isPromiseLike;
|
|
16
|
+
var LEGACY_WS;
|
|
17
|
+
(function (LEGACY_WS) {
|
|
18
|
+
LEGACY_WS["CONNECTION_INIT"] = "connection_init";
|
|
19
|
+
LEGACY_WS["CONNECTION_ACK"] = "connection_ack";
|
|
20
|
+
LEGACY_WS["CONNECTION_ERROR"] = "connection_error";
|
|
21
|
+
LEGACY_WS["CONNECTION_KEEP_ALIVE"] = "ka";
|
|
22
|
+
LEGACY_WS["START"] = "start";
|
|
23
|
+
LEGACY_WS["STOP"] = "stop";
|
|
24
|
+
LEGACY_WS["CONNECTION_TERMINATE"] = "connection_terminate";
|
|
25
|
+
LEGACY_WS["DATA"] = "data";
|
|
26
|
+
LEGACY_WS["ERROR"] = "error";
|
|
27
|
+
LEGACY_WS["COMPLETE"] = "complete";
|
|
28
|
+
})(LEGACY_WS = exports.LEGACY_WS || (exports.LEGACY_WS = {}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import syncFetchImported from 'sync-fetch';
|
|
2
|
+
export const defaultSyncFetch = (input, init) => {
|
|
3
|
+
if (typeof input === 'string') {
|
|
4
|
+
init === null || init === void 0 ? true : delete init.signal;
|
|
5
|
+
}
|
|
6
|
+
else {
|
|
7
|
+
delete input.signal;
|
|
8
|
+
}
|
|
9
|
+
return syncFetchImported(input, init);
|
|
10
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { inspect, isAsyncIterable } from '@graphql-tools/utils';
|
|
2
|
+
import { handleReadable } from './handleReadable.js';
|
|
3
|
+
import { handleReadableStream } from './handleReadableStream.js';
|
|
4
|
+
export async function handleEventStreamResponse(response) {
|
|
5
|
+
// node-fetch returns body as a promise so we need to resolve it
|
|
6
|
+
const body = await response.body;
|
|
7
|
+
if (body) {
|
|
8
|
+
if (isAsyncIterable(body)) {
|
|
9
|
+
return handleReadable(body);
|
|
10
|
+
}
|
|
11
|
+
return handleReadableStream(body);
|
|
12
|
+
}
|
|
13
|
+
throw new Error('Response body is expected to be a readable stream but got; ' + inspect(body));
|
|
14
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* eslint-disable no-labels */
|
|
2
|
+
let decodeUint8Array;
|
|
3
|
+
if (globalThis.Buffer) {
|
|
4
|
+
decodeUint8Array = uint8Array => globalThis.Buffer.from(uint8Array).toString('utf-8');
|
|
5
|
+
}
|
|
6
|
+
else {
|
|
7
|
+
const textDecoder = new TextDecoder();
|
|
8
|
+
decodeUint8Array = uint8Array => textDecoder.decode(uint8Array);
|
|
9
|
+
}
|
|
10
|
+
export async function* handleReadable(readable) {
|
|
11
|
+
outer: for await (const chunk of readable) {
|
|
12
|
+
const chunkStr = typeof chunk === 'string' ? chunk : decodeUint8Array(chunk);
|
|
13
|
+
for (const part of chunkStr.split('\n\n')) {
|
|
14
|
+
if (part) {
|
|
15
|
+
const eventStr = part.split('event: ')[1];
|
|
16
|
+
const dataStr = part.split('data: ')[1];
|
|
17
|
+
if (eventStr === 'complete') {
|
|
18
|
+
break outer;
|
|
19
|
+
}
|
|
20
|
+
if (dataStr) {
|
|
21
|
+
const data = JSON.parse(dataStr);
|
|
22
|
+
yield data.payload || data;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Based on https://github.com/Azure/fetch-event-source/blob/main/src/parse.ts
|
|
2
|
+
export async function* handleReadableStream(stream) {
|
|
3
|
+
const decoder = new TextDecoder();
|
|
4
|
+
const reader = stream.getReader();
|
|
5
|
+
let buffer;
|
|
6
|
+
let position = 0; // current read position
|
|
7
|
+
let fieldLength = -1; // length of the `field` portion of the line
|
|
8
|
+
let discardTrailingNewline = false;
|
|
9
|
+
try {
|
|
10
|
+
let result;
|
|
11
|
+
let message = {
|
|
12
|
+
data: '',
|
|
13
|
+
event: '',
|
|
14
|
+
id: '',
|
|
15
|
+
retry: undefined,
|
|
16
|
+
};
|
|
17
|
+
while (!(result = await reader.read()).done) {
|
|
18
|
+
const arr = result.value;
|
|
19
|
+
if (buffer === undefined) {
|
|
20
|
+
buffer = arr;
|
|
21
|
+
position = 0;
|
|
22
|
+
fieldLength = -1;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// we're still parsing the old line. Append the new bytes into buffer:
|
|
26
|
+
buffer = concat(buffer, arr);
|
|
27
|
+
}
|
|
28
|
+
const bufLength = buffer.length;
|
|
29
|
+
let lineStart = 0; // index where the current line starts
|
|
30
|
+
while (position < bufLength) {
|
|
31
|
+
if (discardTrailingNewline) {
|
|
32
|
+
if (buffer[position] === 10 /* ControlChars.NewLine */) {
|
|
33
|
+
lineStart = ++position; // skip to next char
|
|
34
|
+
}
|
|
35
|
+
discardTrailingNewline = false;
|
|
36
|
+
}
|
|
37
|
+
// start looking forward till the end of line:
|
|
38
|
+
let lineEnd = -1; // index of the \r or \n char
|
|
39
|
+
for (; position < bufLength && lineEnd === -1; ++position) {
|
|
40
|
+
switch (buffer[position]) {
|
|
41
|
+
case 58 /* ControlChars.Colon */: {
|
|
42
|
+
if (fieldLength === -1) {
|
|
43
|
+
// first colon in line
|
|
44
|
+
fieldLength = position - lineStart;
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
case 13 /* ControlChars.CarriageReturn */: {
|
|
49
|
+
discardTrailingNewline = true;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
case 10 /* ControlChars.NewLine */: {
|
|
53
|
+
lineEnd = position;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (lineEnd === -1) {
|
|
59
|
+
// We reached the end of the buffer but the line hasn't ended.
|
|
60
|
+
// Wait for the next arr and then continue parsing:
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
// we've reached the line end, send it out:
|
|
64
|
+
const line = buffer.subarray(lineStart, lineEnd);
|
|
65
|
+
if (line.length === 0) {
|
|
66
|
+
// empty line denotes end of message. Trigger the callback and start a new message:
|
|
67
|
+
if (message.event || message.data) {
|
|
68
|
+
// NOT a server ping (":\n\n")
|
|
69
|
+
yield JSON.parse(message.data);
|
|
70
|
+
message = {
|
|
71
|
+
data: '',
|
|
72
|
+
event: '',
|
|
73
|
+
id: '',
|
|
74
|
+
retry: undefined,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else if (fieldLength > 0) {
|
|
79
|
+
// exclude comments and lines with no values
|
|
80
|
+
// line is of format "<field>:<value>" or "<field>: <value>"
|
|
81
|
+
// https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation
|
|
82
|
+
const field = decoder.decode(line.subarray(0, fieldLength));
|
|
83
|
+
const valueOffset = fieldLength + (line[fieldLength + 1] === 32 /* ControlChars.Space */ ? 2 : 1);
|
|
84
|
+
const value = decoder.decode(line.subarray(valueOffset));
|
|
85
|
+
switch (field) {
|
|
86
|
+
case 'data':
|
|
87
|
+
// if this message already has data, append the new value to the old.
|
|
88
|
+
// otherwise, just set to the new value:
|
|
89
|
+
message.data = message.data ? message.data + '\n' + value : value; // otherwise,
|
|
90
|
+
break;
|
|
91
|
+
case 'event':
|
|
92
|
+
message.event = value;
|
|
93
|
+
break;
|
|
94
|
+
case 'id':
|
|
95
|
+
message.id = value;
|
|
96
|
+
break;
|
|
97
|
+
case 'retry': {
|
|
98
|
+
const retry = parseInt(value, 10);
|
|
99
|
+
message.retry = retry;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
lineStart = position; // we're now on the next line
|
|
105
|
+
fieldLength = -1;
|
|
106
|
+
}
|
|
107
|
+
if (lineStart === bufLength) {
|
|
108
|
+
buffer = undefined; // we've finished reading it
|
|
109
|
+
}
|
|
110
|
+
else if (lineStart !== 0) {
|
|
111
|
+
// Create a new view into buffer beginning at lineStart so we don't
|
|
112
|
+
// need to copy over the previous lines when we get the new arr:
|
|
113
|
+
buffer = buffer.subarray(lineStart);
|
|
114
|
+
position -= lineStart;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
reader.releaseLock();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function concat(a, b) {
|
|
123
|
+
const res = new Uint8Array(a.length + b.length);
|
|
124
|
+
res.set(a);
|
|
125
|
+
res.set(b, a.length);
|
|
126
|
+
return res;
|
|
127
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { meros as merosIncomingMessage } from 'meros/node';
|
|
2
|
+
import { meros as merosReadableStream } from 'meros/browser';
|
|
3
|
+
import { mapAsyncIterator } from '@graphql-tools/utils';
|
|
4
|
+
import { dset } from 'dset/merge';
|
|
5
|
+
function isIncomingMessage(body) {
|
|
6
|
+
return body != null && typeof body === 'object' && 'pipe' in body;
|
|
7
|
+
}
|
|
8
|
+
export async function handleMultipartMixedResponse(response) {
|
|
9
|
+
const body = await response.body;
|
|
10
|
+
const contentType = response.headers.get('content-type') || '';
|
|
11
|
+
let asyncIterator;
|
|
12
|
+
if (isIncomingMessage(body)) {
|
|
13
|
+
// Meros/node expects headers as an object map with the content-type prop
|
|
14
|
+
body.headers = {
|
|
15
|
+
'content-type': contentType,
|
|
16
|
+
};
|
|
17
|
+
// And it expects `IncomingMessage` and `node-fetch` returns `body` as `Promise<PassThrough>`
|
|
18
|
+
asyncIterator = (await merosIncomingMessage(body));
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
// Nothing is needed for regular `Response`.
|
|
22
|
+
asyncIterator = (await merosReadableStream(response));
|
|
23
|
+
}
|
|
24
|
+
const executionResult = {};
|
|
25
|
+
return mapAsyncIterator(asyncIterator, (part) => {
|
|
26
|
+
if (part.json) {
|
|
27
|
+
const chunk = part.body;
|
|
28
|
+
if (chunk.path) {
|
|
29
|
+
if (chunk.data) {
|
|
30
|
+
const path = ['data'];
|
|
31
|
+
dset(executionResult, path.concat(chunk.path), chunk.data);
|
|
32
|
+
}
|
|
33
|
+
if (chunk.errors) {
|
|
34
|
+
executionResult.errors = (executionResult.errors || []).concat(chunk.errors);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
if (chunk.data) {
|
|
39
|
+
executionResult.data = chunk.data;
|
|
40
|
+
}
|
|
41
|
+
if (chunk.errors) {
|
|
42
|
+
executionResult.errors = chunk.errors;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return executionResult;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
@@ -1,279 +1,23 @@
|
|
|
1
|
+
/* eslint-disable no-case-declarations */
|
|
2
|
+
/// <reference lib="dom" />
|
|
1
3
|
import { print, buildASTSchema, buildSchema } from 'graphql';
|
|
2
|
-
import {
|
|
4
|
+
import { observableToAsyncIterable, isAsyncIterable, parseGraphQLSDL, getOperationASTFromRequest, } from '@graphql-tools/utils';
|
|
3
5
|
import { introspectSchema, wrapSchema } from '@graphql-tools/wrap';
|
|
4
6
|
import { createClient } from 'graphql-ws';
|
|
5
7
|
import WebSocket from 'isomorphic-ws';
|
|
6
8
|
import { extractFiles, isExtractableFile } from 'extract-files';
|
|
7
9
|
import { ValueOrPromise } from 'value-or-promise';
|
|
8
10
|
import { isLiveQueryOperationDefinitionNode } from '@n1ru4l/graphql-live-query';
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return fetch(input, init);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const defaultSyncFetch = (input, init) => {
|
|
20
|
-
if (typeof input === 'string') {
|
|
21
|
-
init === null || init === void 0 ? true : delete init.signal;
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
delete input.signal;
|
|
25
|
-
}
|
|
26
|
-
return syncFetchImported(input, init);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
function isIncomingMessage(body) {
|
|
30
|
-
return body != null && typeof body === 'object' && 'pipe' in body;
|
|
31
|
-
}
|
|
32
|
-
async function handleMultipartMixedResponse(response) {
|
|
33
|
-
const body = await response.body;
|
|
34
|
-
const contentType = response.headers.get('content-type') || '';
|
|
35
|
-
let asyncIterator;
|
|
36
|
-
if (isIncomingMessage(body)) {
|
|
37
|
-
// Meros/node expects headers as an object map with the content-type prop
|
|
38
|
-
body.headers = {
|
|
39
|
-
'content-type': contentType,
|
|
40
|
-
};
|
|
41
|
-
// And it expects `IncomingMessage` and `node-fetch` returns `body` as `Promise<PassThrough>`
|
|
42
|
-
asyncIterator = (await meros(body));
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
// Nothing is needed for regular `Response`.
|
|
46
|
-
asyncIterator = (await meros$1(response));
|
|
47
|
-
}
|
|
48
|
-
const executionResult = {};
|
|
49
|
-
return mapAsyncIterator(asyncIterator, (part) => {
|
|
50
|
-
if (part.json) {
|
|
51
|
-
const chunk = part.body;
|
|
52
|
-
if (chunk.path) {
|
|
53
|
-
if (chunk.data) {
|
|
54
|
-
const path = ['data'];
|
|
55
|
-
dset(executionResult, path.concat(chunk.path), chunk.data);
|
|
56
|
-
}
|
|
57
|
-
if (chunk.errors) {
|
|
58
|
-
executionResult.errors = (executionResult.errors || []).concat(chunk.errors);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
if (chunk.data) {
|
|
63
|
-
executionResult.data = chunk.data;
|
|
64
|
-
}
|
|
65
|
-
if (chunk.errors) {
|
|
66
|
-
executionResult.errors = chunk.errors;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return executionResult;
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/* eslint-disable no-labels */
|
|
75
|
-
let decodeUint8Array;
|
|
76
|
-
if (globalThis.Buffer) {
|
|
77
|
-
decodeUint8Array = uint8Array => globalThis.Buffer.from(uint8Array).toString('utf-8');
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
const textDecoder = new TextDecoder();
|
|
81
|
-
decodeUint8Array = uint8Array => textDecoder.decode(uint8Array);
|
|
82
|
-
}
|
|
83
|
-
async function* handleReadable(readable) {
|
|
84
|
-
outer: for await (const chunk of readable) {
|
|
85
|
-
const chunkStr = typeof chunk === 'string' ? chunk : decodeUint8Array(chunk);
|
|
86
|
-
for (const part of chunkStr.split('\n\n')) {
|
|
87
|
-
if (part) {
|
|
88
|
-
const eventStr = part.split('event: ')[1];
|
|
89
|
-
const dataStr = part.split('data: ')[1];
|
|
90
|
-
if (eventStr === 'complete') {
|
|
91
|
-
break outer;
|
|
92
|
-
}
|
|
93
|
-
if (dataStr) {
|
|
94
|
-
const data = JSON.parse(dataStr);
|
|
95
|
-
yield data.payload || data;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Based on https://github.com/Azure/fetch-event-source/blob/main/src/parse.ts
|
|
103
|
-
async function* handleReadableStream(stream) {
|
|
104
|
-
const decoder = new TextDecoder();
|
|
105
|
-
const reader = stream.getReader();
|
|
106
|
-
let buffer;
|
|
107
|
-
let position = 0; // current read position
|
|
108
|
-
let fieldLength = -1; // length of the `field` portion of the line
|
|
109
|
-
let discardTrailingNewline = false;
|
|
110
|
-
try {
|
|
111
|
-
let result;
|
|
112
|
-
let message = {
|
|
113
|
-
data: '',
|
|
114
|
-
event: '',
|
|
115
|
-
id: '',
|
|
116
|
-
retry: undefined,
|
|
117
|
-
};
|
|
118
|
-
while (!(result = await reader.read()).done) {
|
|
119
|
-
const arr = result.value;
|
|
120
|
-
if (buffer === undefined) {
|
|
121
|
-
buffer = arr;
|
|
122
|
-
position = 0;
|
|
123
|
-
fieldLength = -1;
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
// we're still parsing the old line. Append the new bytes into buffer:
|
|
127
|
-
buffer = concat(buffer, arr);
|
|
128
|
-
}
|
|
129
|
-
const bufLength = buffer.length;
|
|
130
|
-
let lineStart = 0; // index where the current line starts
|
|
131
|
-
while (position < bufLength) {
|
|
132
|
-
if (discardTrailingNewline) {
|
|
133
|
-
if (buffer[position] === 10 /* ControlChars.NewLine */) {
|
|
134
|
-
lineStart = ++position; // skip to next char
|
|
135
|
-
}
|
|
136
|
-
discardTrailingNewline = false;
|
|
137
|
-
}
|
|
138
|
-
// start looking forward till the end of line:
|
|
139
|
-
let lineEnd = -1; // index of the \r or \n char
|
|
140
|
-
for (; position < bufLength && lineEnd === -1; ++position) {
|
|
141
|
-
switch (buffer[position]) {
|
|
142
|
-
case 58 /* ControlChars.Colon */: {
|
|
143
|
-
if (fieldLength === -1) {
|
|
144
|
-
// first colon in line
|
|
145
|
-
fieldLength = position - lineStart;
|
|
146
|
-
}
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
case 13 /* ControlChars.CarriageReturn */: {
|
|
150
|
-
discardTrailingNewline = true;
|
|
151
|
-
break;
|
|
152
|
-
}
|
|
153
|
-
case 10 /* ControlChars.NewLine */: {
|
|
154
|
-
lineEnd = position;
|
|
155
|
-
break;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
if (lineEnd === -1) {
|
|
160
|
-
// We reached the end of the buffer but the line hasn't ended.
|
|
161
|
-
// Wait for the next arr and then continue parsing:
|
|
162
|
-
break;
|
|
163
|
-
}
|
|
164
|
-
// we've reached the line end, send it out:
|
|
165
|
-
const line = buffer.subarray(lineStart, lineEnd);
|
|
166
|
-
if (line.length === 0) {
|
|
167
|
-
// empty line denotes end of message. Trigger the callback and start a new message:
|
|
168
|
-
if (message.event || message.data) {
|
|
169
|
-
// NOT a server ping (":\n\n")
|
|
170
|
-
yield JSON.parse(message.data);
|
|
171
|
-
message = {
|
|
172
|
-
data: '',
|
|
173
|
-
event: '',
|
|
174
|
-
id: '',
|
|
175
|
-
retry: undefined,
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
else if (fieldLength > 0) {
|
|
180
|
-
// exclude comments and lines with no values
|
|
181
|
-
// line is of format "<field>:<value>" or "<field>: <value>"
|
|
182
|
-
// https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation
|
|
183
|
-
const field = decoder.decode(line.subarray(0, fieldLength));
|
|
184
|
-
const valueOffset = fieldLength + (line[fieldLength + 1] === 32 /* ControlChars.Space */ ? 2 : 1);
|
|
185
|
-
const value = decoder.decode(line.subarray(valueOffset));
|
|
186
|
-
switch (field) {
|
|
187
|
-
case 'data':
|
|
188
|
-
// if this message already has data, append the new value to the old.
|
|
189
|
-
// otherwise, just set to the new value:
|
|
190
|
-
message.data = message.data ? message.data + '\n' + value : value; // otherwise,
|
|
191
|
-
break;
|
|
192
|
-
case 'event':
|
|
193
|
-
message.event = value;
|
|
194
|
-
break;
|
|
195
|
-
case 'id':
|
|
196
|
-
message.id = value;
|
|
197
|
-
break;
|
|
198
|
-
case 'retry': {
|
|
199
|
-
const retry = parseInt(value, 10);
|
|
200
|
-
message.retry = retry;
|
|
201
|
-
break;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
lineStart = position; // we're now on the next line
|
|
206
|
-
fieldLength = -1;
|
|
207
|
-
}
|
|
208
|
-
if (lineStart === bufLength) {
|
|
209
|
-
buffer = undefined; // we've finished reading it
|
|
210
|
-
}
|
|
211
|
-
else if (lineStart !== 0) {
|
|
212
|
-
// Create a new view into buffer beginning at lineStart so we don't
|
|
213
|
-
// need to copy over the previous lines when we get the new arr:
|
|
214
|
-
buffer = buffer.subarray(lineStart);
|
|
215
|
-
position -= lineStart;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
finally {
|
|
220
|
-
reader.releaseLock();
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
function concat(a, b) {
|
|
224
|
-
const res = new Uint8Array(a.length + b.length);
|
|
225
|
-
res.set(a);
|
|
226
|
-
res.set(b, a.length);
|
|
227
|
-
return res;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
async function handleEventStreamResponse(response) {
|
|
231
|
-
// node-fetch returns body as a promise so we need to resolve it
|
|
232
|
-
const body = await response.body;
|
|
233
|
-
if (body) {
|
|
234
|
-
if (isAsyncIterable(body)) {
|
|
235
|
-
return handleReadable(body);
|
|
236
|
-
}
|
|
237
|
-
return handleReadableStream(body);
|
|
238
|
-
}
|
|
239
|
-
throw new Error('Response body is expected to be a readable stream but got; ' + inspect(body));
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function addCancelToResponseStream(resultStream, controller) {
|
|
243
|
-
return withCancel(resultStream, () => {
|
|
244
|
-
if (!controller.signal.aborted) {
|
|
245
|
-
controller.abort();
|
|
246
|
-
}
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function isBlob(obj) {
|
|
251
|
-
return typeof obj.arrayBuffer === 'function';
|
|
252
|
-
}
|
|
253
|
-
function isGraphQLUpload(upload) {
|
|
254
|
-
return typeof upload.createReadStream === 'function';
|
|
255
|
-
}
|
|
256
|
-
function isPromiseLike(obj) {
|
|
257
|
-
return typeof obj.then === 'function';
|
|
258
|
-
}
|
|
259
|
-
var LEGACY_WS;
|
|
260
|
-
(function (LEGACY_WS) {
|
|
261
|
-
LEGACY_WS["CONNECTION_INIT"] = "connection_init";
|
|
262
|
-
LEGACY_WS["CONNECTION_ACK"] = "connection_ack";
|
|
263
|
-
LEGACY_WS["CONNECTION_ERROR"] = "connection_error";
|
|
264
|
-
LEGACY_WS["CONNECTION_KEEP_ALIVE"] = "ka";
|
|
265
|
-
LEGACY_WS["START"] = "start";
|
|
266
|
-
LEGACY_WS["STOP"] = "stop";
|
|
267
|
-
LEGACY_WS["CONNECTION_TERMINATE"] = "connection_terminate";
|
|
268
|
-
LEGACY_WS["DATA"] = "data";
|
|
269
|
-
LEGACY_WS["ERROR"] = "error";
|
|
270
|
-
LEGACY_WS["COMPLETE"] = "complete";
|
|
271
|
-
})(LEGACY_WS || (LEGACY_WS = {}));
|
|
272
|
-
|
|
273
|
-
/* eslint-disable no-case-declarations */
|
|
11
|
+
import { defaultAsyncFetch } from './defaultAsyncFetch.js';
|
|
12
|
+
import { defaultSyncFetch } from './defaultSyncFetch.js';
|
|
13
|
+
import { handleMultipartMixedResponse } from './handleMultipartMixedResponse.js';
|
|
14
|
+
import { handleEventStreamResponse } from './event-stream/handleEventStreamResponse.js';
|
|
15
|
+
import { addCancelToResponseStream } from './addCancelToResponseStream.js';
|
|
16
|
+
import { AbortController, FormData, File } from 'cross-undici-fetch';
|
|
17
|
+
import { isBlob, isGraphQLUpload, isPromiseLike, LEGACY_WS } from './utils.js';
|
|
274
18
|
const asyncImport = (moduleName) => import(moduleName);
|
|
275
19
|
const syncImport = (moduleName) => require(moduleName);
|
|
276
|
-
var SubscriptionProtocol;
|
|
20
|
+
export var SubscriptionProtocol;
|
|
277
21
|
(function (SubscriptionProtocol) {
|
|
278
22
|
SubscriptionProtocol["WS"] = "WS";
|
|
279
23
|
/**
|
|
@@ -311,7 +55,7 @@ function isCompatibleUri(uri) {
|
|
|
311
55
|
* });
|
|
312
56
|
* ```
|
|
313
57
|
*/
|
|
314
|
-
class UrlLoader {
|
|
58
|
+
export class UrlLoader {
|
|
315
59
|
createFormDataFromVariables({ query, variables, operationName, extensions, }) {
|
|
316
60
|
const vars = Object.assign({}, variables);
|
|
317
61
|
const { clone, files } = extractFiles(vars, 'variables', ((v) => isExtractableFile(v) ||
|
|
@@ -866,5 +610,3 @@ class UrlLoader {
|
|
|
866
610
|
function switchProtocols(pointer, protocolMap) {
|
|
867
611
|
return Object.entries(protocolMap).reduce((prev, [source, target]) => prev.replace(`${source}://`, `${target}://`).replace(`${source}:\\`, `${target}:\\`), pointer);
|
|
868
612
|
}
|
|
869
|
-
|
|
870
|
-
export { SubscriptionProtocol, UrlLoader };
|
package/esm/utils.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function isBlob(obj) {
|
|
2
|
+
return typeof obj.arrayBuffer === 'function';
|
|
3
|
+
}
|
|
4
|
+
export function isGraphQLUpload(upload) {
|
|
5
|
+
return typeof upload.createReadStream === 'function';
|
|
6
|
+
}
|
|
7
|
+
export function isPromiseLike(obj) {
|
|
8
|
+
return typeof obj.then === 'function';
|
|
9
|
+
}
|
|
10
|
+
export var LEGACY_WS;
|
|
11
|
+
(function (LEGACY_WS) {
|
|
12
|
+
LEGACY_WS["CONNECTION_INIT"] = "connection_init";
|
|
13
|
+
LEGACY_WS["CONNECTION_ACK"] = "connection_ack";
|
|
14
|
+
LEGACY_WS["CONNECTION_ERROR"] = "connection_error";
|
|
15
|
+
LEGACY_WS["CONNECTION_KEEP_ALIVE"] = "ka";
|
|
16
|
+
LEGACY_WS["START"] = "start";
|
|
17
|
+
LEGACY_WS["STOP"] = "stop";
|
|
18
|
+
LEGACY_WS["CONNECTION_TERMINATE"] = "connection_terminate";
|
|
19
|
+
LEGACY_WS["DATA"] = "data";
|
|
20
|
+
LEGACY_WS["ERROR"] = "error";
|
|
21
|
+
LEGACY_WS["COMPLETE"] = "complete";
|
|
22
|
+
})(LEGACY_WS || (LEGACY_WS = {}));
|