Skip to content

Commit

Permalink
Custom EventSource implementation (#391)
Browse files Browse the repository at this point in the history
* Custom EventSource implementation

* Changeset
  • Loading branch information
SamyPesse authored Feb 8, 2024
1 parent 2d653e6 commit 17099cf
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 27 deletions.
5 changes: 5 additions & 0 deletions .changeset/itchy-terms-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@gitbook/api': minor
---

Use fetch and a custom EventSource parsing to support node/browser/worker for streaming operations
17 changes: 10 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"dist/**"
],
"dependencies": {
"@microsoft/fetch-event-source": "^2.0.1",
"event-iterator": "^2.0.0"
"event-iterator": "^2.0.0",
"eventsource-parser": "^1.1.1"
},
"devDependencies": {
"swagger-typescript-api": "^13.0.3",
Expand Down
63 changes: 45 additions & 18 deletions packages/api/templates/http-client.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
const { apiConfig, generateResponses, config } = it;
%>
import { EventIterator } from 'event-iterator';
import { fetchEventSource } from '@microsoft/fetch-event-source';
import { createParser, type ParsedEvent, type ReconnectInterval } from 'eventsource-parser';

export type QueryParamsType = Record<string | number, any>;
export type ResponseFormat = keyof Omit<Body, "body" | "bodyUsed">;
Expand Down Expand Up @@ -241,28 +241,55 @@ export class HttpClient<SecurityDataType = unknown> {
const { query: requestQuery, ...requestParams } = this.mergeRequestParams(params, secureParams);
const queryString = requestQuery ? this.toQueryString(requestQuery) : undefined;

await fetchEventSource(
const response = await this.customFetch(
`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`,
{
...requestParams,
signal: cancelToken ? this.createAbortSignal(cancelToken) : requestParams.signal,
onmessage(event) {
if (event.data === 'done') {
queue.stop();
} else {
const data = JSON.parse(event.data);
queue.push(data);
}
},
onclose() {
queue.stop();
},
onerror(error) {
queue.fail(error);
}
)

if (!response.ok) {
throw new Error(`${response.status} ${response.statusText}`);
return;
}

const reader = response.body.getReader();

const stop = () => {
reader.cancel();
queue.stop();
}

const parser = createParser((event: ParsedEvent | ReconnectInterval) => {
if (event.type === 'event') {
if (event.data === 'done') {
stop();
} else {
const data = JSON.parse(event.data);
queue.push(data);
}
},
);
})();
}
})

const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();

if (value) {
parser.feed(decoder.decode(value))
}

if (done) {
break;
}
}

stop();
})()
.catch(error => {
queue.fail(error);
});
}
);
};
Expand Down

0 comments on commit 17099cf

Please sign in to comment.