Skip to content

Commit 63a2936

Browse files
authored
[@graphql-tools/url-loader] Fix SSE ping event (#3821)
* Fix ping event * Create plenty-nails-shave.md * Add test for readable stream * sorted packages in package.json (done by npm) * rename typo in filename
1 parent 1e12c91 commit 63a2936

File tree

4 files changed

+70
-12
lines changed

4 files changed

+70
-12
lines changed

.changeset/plenty-nails-shave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@graphql-tools/url-loader": patch
3+
---
4+
5+
[@graphql-tools/url-loader] Fix SSE ping event

packages/loaders/url/package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@
3636
},
3737
"devDependencies": {
3838
"@types/express": "4.17.13",
39-
"@types/valid-url": "1.0.3",
4039
"@types/extract-files": "8.1.1",
40+
"@types/valid-url": "1.0.3",
41+
"babel-loader": "8.2.3",
4142
"express": "4.17.1",
4243
"express-graphql": "0.12.0",
4344
"graphql-upload": "12.0.0",
4445
"puppeteer": "11.0.0",
45-
"babel-loader": "8.2.3",
46+
"web-streams-polyfill": "^3.1.1",
4647
"webpack": "5.61.0"
4748
},
4849
"dependencies": {
@@ -57,14 +58,14 @@
5758
"extract-files": "11.0.0",
5859
"graphql-sse": "^1.0.1",
5960
"graphql-ws": "^5.4.1",
60-
"meros": "1.1.4",
6161
"isomorphic-ws": "4.0.1",
62+
"meros": "1.1.4",
6263
"subscriptions-transport-ws": "^0.11.0",
6364
"sync-fetch": "0.3.1",
6465
"tslib": "~2.3.0",
6566
"valid-url": "1.0.9",
66-
"ws": "8.2.3",
67-
"value-or-promise": "1.0.11"
67+
"value-or-promise": "1.0.11",
68+
"ws": "8.2.3"
6869
},
6970
"publishConfig": {
7071
"access": "public",

packages/loaders/url/src/event-stream/handleReadableStream.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,16 @@ export async function* handleReadableStream(stream: ReadableStream<Uint8Array>)
9595
const line = buffer.subarray(lineStart, lineEnd);
9696
if (line.length === 0) {
9797
// empty line denotes end of message. Trigger the callback and start a new message:
98-
yield JSON.parse(message.data);
99-
message = {
100-
data: '',
101-
event: '',
102-
id: '',
103-
retry: undefined,
104-
};
98+
if (message.event || message.data) {
99+
// NOT a server ping (":\n\n")
100+
yield JSON.parse(message.data);
101+
message = {
102+
data: '',
103+
event: '',
104+
id: '',
105+
retry: undefined,
106+
};
107+
}
105108
} else if (fieldLength > 0) {
106109
// exclude comments and lines with no values
107110
// line is of format "<field>:<value>" or "<field>: <value>"
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { handleReadableStream } from '../src/event-stream/handleReadableStream';
2+
import { TransformStream } from 'web-streams-polyfill/ponyfill';
3+
import { TextEncoder } from 'util';
4+
5+
describe('handleReadableStream', () => {
6+
it('should handle an event with data', async () => {
7+
const { readable, writable } = new TransformStream();
8+
const encoder = new TextEncoder();
9+
const stream = writable.getWriter();
10+
11+
const generator = handleReadableStream(readable as any);
12+
13+
// stream.write(encoder.encode(':\n\n'));
14+
stream.write(encoder.encode('event: complete\n'));
15+
stream.write(encoder.encode('data: { "foo": "bar" }\n'));
16+
stream.write(encoder.encode('\n'));
17+
18+
expect((await generator.next()).value).toMatchInlineSnapshot(`
19+
Object {
20+
"foo": "bar",
21+
}
22+
`);
23+
});
24+
25+
it('should ignore server pings', async () => {
26+
const { readable, writable } = new TransformStream();
27+
const encoder = new TextEncoder();
28+
const stream = writable.getWriter();
29+
30+
const readStream = () => {
31+
const generator = handleReadableStream(readable as any);
32+
33+
stream.write(encoder.encode(':\n\n'));
34+
stream.write(encoder.encode('event: next\n'));
35+
stream.write(encoder.encode('data: { "foo": "bar" }\n\n'));
36+
37+
return generator.next();
38+
};
39+
40+
await expect(readStream()).resolves.toMatchInlineSnapshot(`
41+
Object {
42+
"done": false,
43+
"value": Object {
44+
"foo": "bar",
45+
},
46+
}
47+
`);
48+
});
49+
});

0 commit comments

Comments
 (0)