@graphql-tools/url-loader 7.12.4 → 7.13.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/event-stream/{handleReadable.js → handleAsyncIterable.js} +5 -5
- package/cjs/event-stream/handleEventStreamResponse.js +3 -3
- package/cjs/event-stream/handleReadableStream.js +20 -120
- package/esm/event-stream/{handleReadable.js → handleAsyncIterable.js} +3 -3
- package/esm/event-stream/handleEventStreamResponse.js +3 -3
- package/esm/event-stream/handleReadableStream.js +20 -120
- package/package.json +1 -1
- package/typings/event-stream/handleAsyncIterable.d.ts +1 -0
- package/typings/event-stream/handleReadableStream.d.ts +1 -15
- package/typings/event-stream/handleReadable.d.ts +0 -1
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* eslint-disable no-labels */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
4
|
+
exports.handleAsyncIterable = void 0;
|
|
5
5
|
let decodeUint8Array;
|
|
6
6
|
if (globalThis.Buffer) {
|
|
7
7
|
decodeUint8Array = uint8Array => globalThis.Buffer.from(uint8Array).toString('utf-8');
|
|
8
8
|
}
|
|
9
9
|
else {
|
|
10
10
|
const textDecoder = new TextDecoder();
|
|
11
|
-
decodeUint8Array = uint8Array => textDecoder.decode(uint8Array);
|
|
11
|
+
decodeUint8Array = uint8Array => textDecoder.decode(uint8Array, { stream: true });
|
|
12
12
|
}
|
|
13
|
-
async function*
|
|
14
|
-
outer: for await (const chunk of
|
|
13
|
+
async function* handleAsyncIterable(asyncIterable) {
|
|
14
|
+
outer: for await (const chunk of asyncIterable) {
|
|
15
15
|
const chunkStr = typeof chunk === 'string' ? chunk : decodeUint8Array(chunk);
|
|
16
16
|
for (const part of chunkStr.split('\n\n')) {
|
|
17
17
|
if (part) {
|
|
@@ -28,4 +28,4 @@ async function* handleReadable(readable) {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
exports.
|
|
31
|
+
exports.handleAsyncIterable = handleAsyncIterable;
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.handleEventStreamResponse = void 0;
|
|
4
4
|
const utils_1 = require("@graphql-tools/utils");
|
|
5
|
-
const
|
|
5
|
+
const handleAsyncIterable_js_1 = require("./handleAsyncIterable.js");
|
|
6
6
|
const handleReadableStream_js_1 = require("./handleReadableStream.js");
|
|
7
7
|
async function handleEventStreamResponse(response) {
|
|
8
8
|
// node-fetch returns body as a promise so we need to resolve it
|
|
9
|
-
const body =
|
|
9
|
+
const body = response.body;
|
|
10
10
|
if (body) {
|
|
11
11
|
if ((0, utils_1.isAsyncIterable)(body)) {
|
|
12
|
-
return (0,
|
|
12
|
+
return (0, handleAsyncIterable_js_1.handleAsyncIterable)(body);
|
|
13
13
|
}
|
|
14
14
|
return (0, handleReadableStream_js_1.handleReadableStream)(body);
|
|
15
15
|
}
|
|
@@ -1,131 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
2
|
+
/* eslint-disable no-labels */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.handleReadableStream = void 0;
|
|
5
|
-
async function* handleReadableStream(
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
retry: undefined,
|
|
19
|
-
};
|
|
20
|
-
while (!(result = await reader.read()).done) {
|
|
21
|
-
const arr = result.value;
|
|
22
|
-
if (buffer === undefined) {
|
|
23
|
-
buffer = arr;
|
|
24
|
-
position = 0;
|
|
25
|
-
fieldLength = -1;
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
// we're still parsing the old line. Append the new bytes into buffer:
|
|
29
|
-
buffer = concat(buffer, arr);
|
|
30
|
-
}
|
|
31
|
-
const bufLength = buffer.length;
|
|
32
|
-
let lineStart = 0; // index where the current line starts
|
|
33
|
-
while (position < bufLength) {
|
|
34
|
-
if (discardTrailingNewline) {
|
|
35
|
-
if (buffer[position] === 10 /* ControlChars.NewLine */) {
|
|
36
|
-
lineStart = ++position; // skip to next char
|
|
5
|
+
async function* handleReadableStream(readableStream) {
|
|
6
|
+
const textDecoderStream = new TextDecoderStream();
|
|
7
|
+
const decodedStream = readableStream.pipeThrough(textDecoderStream);
|
|
8
|
+
const reader = decodedStream.getReader();
|
|
9
|
+
outer: while (true) {
|
|
10
|
+
const { value, done } = await reader.read();
|
|
11
|
+
if (value) {
|
|
12
|
+
for (const part of value.split('\n\n')) {
|
|
13
|
+
if (part) {
|
|
14
|
+
const eventStr = part.split('event: ')[1];
|
|
15
|
+
const dataStr = part.split('data: ')[1];
|
|
16
|
+
if (eventStr === 'complete') {
|
|
17
|
+
break outer;
|
|
37
18
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
let lineEnd = -1; // index of the \r or \n char
|
|
42
|
-
for (; position < bufLength && lineEnd === -1; ++position) {
|
|
43
|
-
switch (buffer[position]) {
|
|
44
|
-
case 58 /* ControlChars.Colon */: {
|
|
45
|
-
if (fieldLength === -1) {
|
|
46
|
-
// first colon in line
|
|
47
|
-
fieldLength = position - lineStart;
|
|
48
|
-
}
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
case 13 /* ControlChars.CarriageReturn */: {
|
|
52
|
-
discardTrailingNewline = true;
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
case 10 /* ControlChars.NewLine */: {
|
|
56
|
-
lineEnd = position;
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
19
|
+
if (dataStr) {
|
|
20
|
+
const data = JSON.parse(dataStr);
|
|
21
|
+
yield data.payload || data;
|
|
59
22
|
}
|
|
60
23
|
}
|
|
61
|
-
if (lineEnd === -1) {
|
|
62
|
-
// We reached the end of the buffer but the line hasn't ended.
|
|
63
|
-
// Wait for the next arr and then continue parsing:
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
// we've reached the line end, send it out:
|
|
67
|
-
const line = buffer.subarray(lineStart, lineEnd);
|
|
68
|
-
if (line.length === 0) {
|
|
69
|
-
// empty line denotes end of message. Trigger the callback and start a new message:
|
|
70
|
-
if (message.event || message.data) {
|
|
71
|
-
// NOT a server ping (":\n\n")
|
|
72
|
-
yield JSON.parse(message.data);
|
|
73
|
-
message = {
|
|
74
|
-
data: '',
|
|
75
|
-
event: '',
|
|
76
|
-
id: '',
|
|
77
|
-
retry: undefined,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
else if (fieldLength > 0) {
|
|
82
|
-
// exclude comments and lines with no values
|
|
83
|
-
// line is of format "<field>:<value>" or "<field>: <value>"
|
|
84
|
-
// https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation
|
|
85
|
-
const field = decoder.decode(line.subarray(0, fieldLength));
|
|
86
|
-
const valueOffset = fieldLength + (line[fieldLength + 1] === 32 /* ControlChars.Space */ ? 2 : 1);
|
|
87
|
-
const value = decoder.decode(line.subarray(valueOffset));
|
|
88
|
-
switch (field) {
|
|
89
|
-
case 'data':
|
|
90
|
-
// if this message already has data, append the new value to the old.
|
|
91
|
-
// otherwise, just set to the new value:
|
|
92
|
-
message.data = message.data ? message.data + '\n' + value : value; // otherwise,
|
|
93
|
-
break;
|
|
94
|
-
case 'event':
|
|
95
|
-
message.event = value;
|
|
96
|
-
break;
|
|
97
|
-
case 'id':
|
|
98
|
-
message.id = value;
|
|
99
|
-
break;
|
|
100
|
-
case 'retry': {
|
|
101
|
-
const retry = parseInt(value, 10);
|
|
102
|
-
message.retry = retry;
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
lineStart = position; // we're now on the next line
|
|
108
|
-
fieldLength = -1;
|
|
109
|
-
}
|
|
110
|
-
if (lineStart === bufLength) {
|
|
111
|
-
buffer = undefined; // we've finished reading it
|
|
112
|
-
}
|
|
113
|
-
else if (lineStart !== 0) {
|
|
114
|
-
// Create a new view into buffer beginning at lineStart so we don't
|
|
115
|
-
// need to copy over the previous lines when we get the new arr:
|
|
116
|
-
buffer = buffer.subarray(lineStart);
|
|
117
|
-
position -= lineStart;
|
|
118
24
|
}
|
|
119
25
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
26
|
+
if (done) {
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
123
29
|
}
|
|
124
30
|
}
|
|
125
31
|
exports.handleReadableStream = handleReadableStream;
|
|
126
|
-
function concat(a, b) {
|
|
127
|
-
const res = new Uint8Array(a.length + b.length);
|
|
128
|
-
res.set(a);
|
|
129
|
-
res.set(b, a.length);
|
|
130
|
-
return res;
|
|
131
|
-
}
|
|
@@ -5,10 +5,10 @@ if (globalThis.Buffer) {
|
|
|
5
5
|
}
|
|
6
6
|
else {
|
|
7
7
|
const textDecoder = new TextDecoder();
|
|
8
|
-
decodeUint8Array = uint8Array => textDecoder.decode(uint8Array);
|
|
8
|
+
decodeUint8Array = uint8Array => textDecoder.decode(uint8Array, { stream: true });
|
|
9
9
|
}
|
|
10
|
-
export async function*
|
|
11
|
-
outer: for await (const chunk of
|
|
10
|
+
export async function* handleAsyncIterable(asyncIterable) {
|
|
11
|
+
outer: for await (const chunk of asyncIterable) {
|
|
12
12
|
const chunkStr = typeof chunk === 'string' ? chunk : decodeUint8Array(chunk);
|
|
13
13
|
for (const part of chunkStr.split('\n\n')) {
|
|
14
14
|
if (part) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { inspect, isAsyncIterable } from '@graphql-tools/utils';
|
|
2
|
-
import {
|
|
2
|
+
import { handleAsyncIterable } from './handleAsyncIterable.js';
|
|
3
3
|
import { handleReadableStream } from './handleReadableStream.js';
|
|
4
4
|
export async function handleEventStreamResponse(response) {
|
|
5
5
|
// node-fetch returns body as a promise so we need to resolve it
|
|
6
|
-
const body =
|
|
6
|
+
const body = response.body;
|
|
7
7
|
if (body) {
|
|
8
8
|
if (isAsyncIterable(body)) {
|
|
9
|
-
return
|
|
9
|
+
return handleAsyncIterable(body);
|
|
10
10
|
}
|
|
11
11
|
return handleReadableStream(body);
|
|
12
12
|
}
|
|
@@ -1,127 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
export async function* handleReadableStream(
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
|
1
|
+
/* eslint-disable no-labels */
|
|
2
|
+
export async function* handleReadableStream(readableStream) {
|
|
3
|
+
const textDecoderStream = new TextDecoderStream();
|
|
4
|
+
const decodedStream = readableStream.pipeThrough(textDecoderStream);
|
|
5
|
+
const reader = decodedStream.getReader();
|
|
6
|
+
outer: while (true) {
|
|
7
|
+
const { value, done } = await reader.read();
|
|
8
|
+
if (value) {
|
|
9
|
+
for (const part of value.split('\n\n')) {
|
|
10
|
+
if (part) {
|
|
11
|
+
const eventStr = part.split('event: ')[1];
|
|
12
|
+
const dataStr = part.split('data: ')[1];
|
|
13
|
+
if (eventStr === 'complete') {
|
|
14
|
+
break outer;
|
|
34
15
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
}
|
|
16
|
+
if (dataStr) {
|
|
17
|
+
const data = JSON.parse(dataStr);
|
|
18
|
+
yield data.payload || data;
|
|
56
19
|
}
|
|
57
20
|
}
|
|
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
21
|
}
|
|
116
22
|
}
|
|
23
|
+
if (done) {
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
117
26
|
}
|
|
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
27
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function handleAsyncIterable(asyncIterable: AsyncIterable<Uint8Array | string>): AsyncGenerator<any, void, unknown>;
|
|
@@ -1,15 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Represents a message sent in an event stream
|
|
3
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format
|
|
4
|
-
*/
|
|
5
|
-
export interface EventSourceMessage {
|
|
6
|
-
/** The event ID to set the EventSource object's last event ID value. */
|
|
7
|
-
id: string;
|
|
8
|
-
/** A string identifying the type of event described. */
|
|
9
|
-
event: string;
|
|
10
|
-
/** The event data */
|
|
11
|
-
data: string;
|
|
12
|
-
/** The reconnection interval (in milliseconds) to wait before retrying the connection */
|
|
13
|
-
retry?: number;
|
|
14
|
-
}
|
|
15
|
-
export declare function handleReadableStream(stream: ReadableStream<Uint8Array>): AsyncGenerator<any, void, unknown>;
|
|
1
|
+
export declare function handleReadableStream(readableStream: ReadableStream<Uint8Array>): AsyncGenerator<any, void, unknown>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function handleReadable(readable: AsyncIterable<Uint8Array | string>): AsyncGenerator<any, void, unknown>;
|