graphql-sse
Advanced tools
Comparing version 2.3.0 to 2.4.0
@@ -10,2 +10,21 @@ /** | ||
/** @category Client */ | ||
export interface EventListeners<SingleConnection extends boolean = false> { | ||
/** | ||
* Emitted when the client starts connecting to the server. | ||
* | ||
* @param reconnecting - Whether the client is reconnecting after the connection was broken. | ||
*/ | ||
connecting?: (reconnecting: boolean) => void; | ||
/** | ||
* Emitted when the client receives a message from the server. | ||
*/ | ||
message?: (message: StreamMessage<SingleConnection, StreamEvent>) => void; | ||
/** | ||
* Emitted when the client has successfully connected to the server. | ||
* | ||
* @param reconnecting - Whether the client has reconnected after the connection was broken. | ||
*/ | ||
connected?: (reconnected: boolean) => void; | ||
} | ||
/** @category Client */ | ||
export interface ClientOptions<SingleConnection extends boolean = false> { | ||
@@ -35,3 +54,3 @@ /** | ||
* Note that the `lazy` option has NO EFFECT when using the client | ||
* in "distinct connection mode" (`singleConnection = false`). | ||
* in "distinct connections mode" (`singleConnection = false`). | ||
* | ||
@@ -48,3 +67,3 @@ * @default true | ||
* Note that the `lazy` option has NO EFFECT when using the client | ||
* in "distinct connection mode" (`singleConnection = false`). | ||
* in "distinct connections mode" (`singleConnection = false`). | ||
* | ||
@@ -171,7 +190,17 @@ * @default 0 | ||
* Use this function if you want to inspect valid messages received through the active SSE connection. | ||
* | ||
* @deprecated Consider using {@link ClientOptions.on} instead. | ||
*/ | ||
onMessage?: (message: StreamMessage<SingleConnection, StreamEvent>) => void; | ||
/** | ||
* Event listeners for events happening in teh SSE connection. | ||
* | ||
* Will emit events for both the "single connection mode" and the default "distinct connections mode". | ||
* | ||
* Beware that the `connecting` event will be called for **each** subscription when using with "distinct connections mode". | ||
*/ | ||
on?: EventListeners<SingleConnection>; | ||
} | ||
/** @category Client */ | ||
export interface Client { | ||
export interface Client<SingleConnection extends boolean = false> { | ||
/** | ||
@@ -182,9 +211,13 @@ * Subscribes to receive through a SSE connection. | ||
* function used for dropping the subscription and cleaning up. | ||
* | ||
* @param on - The event listener for "distinct connections mode". Note that **no events will be emitted** in "single connection mode"; for that, consider using the event listener in {@link ClientOptions}. | ||
*/ | ||
subscribe<Data = Record<string, unknown>, Extensions = unknown>(request: RequestParams, sink: Sink<ExecutionResult<Data, Extensions>>): () => void; | ||
subscribe<Data = Record<string, unknown>, Extensions = unknown>(request: RequestParams, sink: Sink<ExecutionResult<Data, Extensions>>, on?: SingleConnection extends true ? never : EventListeners<false>): () => void; | ||
/** | ||
* Subscribes and iterates over emitted results from an SSE connection | ||
* through the returned async iterator. | ||
* | ||
* @param on - The event listener for "distinct connections mode". Note that **no events will be emitted** in "single connection mode"; for that, consider using the event listener in {@link ClientOptions}. | ||
*/ | ||
iterate<Data = Record<string, unknown>, Extensions = unknown>(request: RequestParams): AsyncIterableIterator<ExecutionResult<Data, Extensions>>; | ||
iterate<Data = Record<string, unknown>, Extensions = unknown>(request: RequestParams, on?: SingleConnection extends true ? never : EventListeners<false>): AsyncIterableIterator<ExecutionResult<Data, Extensions>>; | ||
/** | ||
@@ -209,3 +242,3 @@ * Dispose of the client, destroy connections and clean up resources. | ||
*/ | ||
export declare function createClient<SingleConnection extends boolean = false>(options: ClientOptions<SingleConnection>): Client; | ||
export declare function createClient<SingleConnection extends boolean = false>(options: ClientOptions<SingleConnection>): Client<SingleConnection>; | ||
/** | ||
@@ -212,0 +245,0 @@ * A network error caused by the client or an unexpected response from the server. |
@@ -64,3 +64,3 @@ "use strict"; | ||
Math.floor(Math.random() * (3000 - 300) + 300))); | ||
}, credentials = 'same-origin', referrer, referrerPolicy, onMessage, } = options; | ||
}, credentials = 'same-origin', referrer, referrerPolicy, onMessage, on: clientOn, } = options; | ||
const fetchFn = (options.fetchFn || fetch); | ||
@@ -108,3 +108,3 @@ const AbortControllerImpl = (options.abortControllerImpl || | ||
return await (conn !== null && conn !== void 0 ? conn : (conn = (async () => { | ||
var _a; | ||
var _a, _b, _c; | ||
if (retryingErr) { | ||
@@ -117,2 +117,3 @@ await retry(retries); | ||
} | ||
(_a = clientOn === null || clientOn === void 0 ? void 0 : clientOn.connecting) === null || _a === void 0 ? void 0 : _a.call(clientOn, !!retryingErr); | ||
// we must create a new controller here because lazy mode aborts currently active ones | ||
@@ -132,3 +133,3 @@ connCtrl = new AbortControllerImpl(); | ||
? await options.headers() | ||
: (_a = options.headers) !== null && _a !== void 0 ? _a : {}; | ||
: (_b = options.headers) !== null && _b !== void 0 ? _b : {}; | ||
if (connCtrl.signal.aborted) | ||
@@ -162,4 +163,9 @@ throw new Error('Connection aborted by the client'); | ||
fetchFn, | ||
onMessage, | ||
onMessage: (msg) => { | ||
var _a; | ||
(_a = clientOn === null || clientOn === void 0 ? void 0 : clientOn.message) === null || _a === void 0 ? void 0 : _a.call(clientOn, msg); | ||
onMessage === null || onMessage === void 0 ? void 0 : onMessage(msg); // @deprecated | ||
}, | ||
}); | ||
(_c = clientOn === null || clientOn === void 0 ? void 0 : clientOn.connected) === null || _c === void 0 ? void 0 : _c.call(clientOn, !!retryingErr); | ||
connected.waitForThrow().catch(() => (conn = undefined)); | ||
@@ -201,80 +207,5 @@ return connected; | ||
} | ||
return { | ||
subscribe(request, sink) { | ||
if (!singleConnection) { | ||
// distinct connections mode | ||
const control = new AbortControllerImpl(); | ||
const unlisten = client.onDispose(() => { | ||
unlisten(); | ||
control.abort(); | ||
}); | ||
(async () => { | ||
var _a; | ||
let retryingErr = null, retries = 0; | ||
for (;;) { | ||
try { | ||
if (retryingErr) { | ||
await retry(retries); | ||
// connection might've been aborted while waiting for retry | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
retries++; | ||
} | ||
const url = typeof options.url === 'function' | ||
? await options.url() | ||
: options.url; | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
const headers = typeof options.headers === 'function' | ||
? await options.headers() | ||
: (_a = options.headers) !== null && _a !== void 0 ? _a : {}; | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
const { getResults } = await connect({ | ||
signal: control.signal, | ||
headers: { | ||
...headers, | ||
'content-type': 'application/json; charset=utf-8', | ||
}, | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
url, | ||
body: JSON.stringify(request), | ||
fetchFn, | ||
onMessage, | ||
}); | ||
for await (const result of getResults()) { | ||
// only after receiving results are future connects not considered retries. | ||
// this is because a client might successfully connect, but the server | ||
// ends up terminating the connection afterwards before streaming anything. | ||
// of course, if the client completes the subscription, this loop will | ||
// break and therefore stop the stream (it wont reconnect) | ||
retryingErr = null; | ||
retries = 0; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
sink.next(result); | ||
} | ||
return control.abort(); | ||
} | ||
catch (err) { | ||
if (control.signal.aborted) | ||
return; | ||
// all non-network errors are worth reporting immediately | ||
if (!(err instanceof NetworkError)) | ||
throw err; | ||
// retries are not allowed or we tried to many times, report error | ||
if (!retryAttempts || retries >= retryAttempts) | ||
throw err; | ||
// try again | ||
retryingErr = err; | ||
} | ||
} | ||
})() | ||
.then(() => sink.complete()) | ||
.catch((err) => sink.error(err)); | ||
return () => control.abort(); | ||
} | ||
// single connection mode | ||
locks++; | ||
function subscribe(request, sink, on) { | ||
if (!singleConnection) { | ||
// distinct connections mode | ||
const control = new AbortControllerImpl(); | ||
@@ -286,59 +217,47 @@ const unlisten = client.onDispose(() => { | ||
(async () => { | ||
const operationId = generateID(); | ||
request = { | ||
...request, | ||
extensions: { ...request.extensions, operationId }, | ||
}; | ||
let complete = null; | ||
var _a, _b, _c, _d, _e; | ||
let retryingErr = null, retries = 0; | ||
for (;;) { | ||
complete = null; | ||
try { | ||
const { url, headers, getResults } = await getOrConnect(); | ||
let res; | ||
try { | ||
res = await fetchFn(url, { | ||
signal: control.signal, | ||
method: 'POST', | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
headers: { | ||
...headers, | ||
'content-type': 'application/json; charset=utf-8', | ||
}, | ||
body: JSON.stringify(request), | ||
}); | ||
if (retryingErr) { | ||
await retry(retries); | ||
// connection might've been aborted while waiting for retry | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
retries++; | ||
} | ||
catch (err) { | ||
throw new NetworkError(err); | ||
} | ||
if (res.status !== 202) | ||
throw new NetworkError(res); | ||
complete = async () => { | ||
let res; | ||
try { | ||
const control = new AbortControllerImpl(); | ||
const unlisten = client.onDispose(() => { | ||
unlisten(); | ||
control.abort(); | ||
}); | ||
res = await fetchFn(url + '?operationId=' + operationId, { | ||
signal: control.signal, | ||
method: 'DELETE', | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
headers, | ||
}); | ||
} | ||
catch (err) { | ||
throw new NetworkError(err); | ||
} | ||
if (res.status !== 200) | ||
throw new NetworkError(res); | ||
}; | ||
for await (const result of getResults({ | ||
(_a = clientOn === null || clientOn === void 0 ? void 0 : clientOn.connecting) === null || _a === void 0 ? void 0 : _a.call(clientOn, !!retryingErr); | ||
(_b = on === null || on === void 0 ? void 0 : on.connecting) === null || _b === void 0 ? void 0 : _b.call(on, !!retryingErr); | ||
const url = typeof options.url === 'function' | ||
? await options.url() | ||
: options.url; | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
const headers = typeof options.headers === 'function' | ||
? await options.headers() | ||
: (_c = options.headers) !== null && _c !== void 0 ? _c : {}; | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
const { getResults } = await connect({ | ||
signal: control.signal, | ||
operationId, | ||
})) { | ||
headers: { | ||
...headers, | ||
'content-type': 'application/json; charset=utf-8', | ||
}, | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
url, | ||
body: JSON.stringify(request), | ||
fetchFn, | ||
onMessage: (msg) => { | ||
var _a, _b; | ||
(_a = clientOn === null || clientOn === void 0 ? void 0 : clientOn.message) === null || _a === void 0 ? void 0 : _a.call(clientOn, msg); | ||
(_b = on === null || on === void 0 ? void 0 : on.message) === null || _b === void 0 ? void 0 : _b.call(on, msg); | ||
onMessage === null || onMessage === void 0 ? void 0 : onMessage(msg); // @deprecated | ||
}, | ||
}); | ||
(_d = clientOn === null || clientOn === void 0 ? void 0 : clientOn.connected) === null || _d === void 0 ? void 0 : _d.call(clientOn, !!retryingErr); | ||
(_e = on === null || on === void 0 ? void 0 : on.connected) === null || _e === void 0 ? void 0 : _e.call(on, !!retryingErr); | ||
for await (const result of getResults()) { | ||
// only after receiving results are future connects not considered retries. | ||
@@ -354,3 +273,2 @@ // this is because a client might successfully connect, but the server | ||
} | ||
complete = null; // completed by the server | ||
return control.abort(); | ||
@@ -360,39 +278,12 @@ } | ||
if (control.signal.aborted) | ||
return await (complete === null || complete === void 0 ? void 0 : complete()); | ||
return; | ||
// all non-network errors are worth reporting immediately | ||
if (!(err instanceof NetworkError)) { | ||
control.abort(); // TODO: tests for making sure the control's aborted | ||
if (!(err instanceof NetworkError)) | ||
throw err; | ||
} | ||
// was a network error, get rid of the current connection to ensure retries | ||
// but only if the client is running in lazy mode (otherwise the non-lazy lock will get rid of the connection) | ||
if (lazy) { | ||
conn = undefined; | ||
} | ||
// retries are not allowed or we tried to many times, report error | ||
if (!retryAttempts || retries >= retryAttempts) { | ||
control.abort(); // TODO: tests for making sure the control's aborted | ||
if (!retryAttempts || retries >= retryAttempts) | ||
throw err; | ||
} | ||
// try again | ||
retryingErr = err; | ||
} | ||
finally { | ||
// release lock if subscription is aborted | ||
if (control.signal.aborted && --locks === 0) { | ||
if (isFinite(lazyCloseTimeout) && lazyCloseTimeout > 0) { | ||
// allow for the specified calmdown time and then close the | ||
// connection, only if no lock got created in the meantime and | ||
// if the connection is still open | ||
setTimeout(() => { | ||
if (!locks) | ||
connCtrl.abort(); | ||
}, lazyCloseTimeout); | ||
} | ||
else { | ||
// otherwise close immediately | ||
connCtrl.abort(); | ||
} | ||
} | ||
} | ||
} | ||
@@ -403,4 +294,129 @@ })() | ||
return () => control.abort(); | ||
}, | ||
iterate(request) { | ||
} | ||
// single connection mode | ||
locks++; | ||
const control = new AbortControllerImpl(); | ||
const unlisten = client.onDispose(() => { | ||
unlisten(); | ||
control.abort(); | ||
}); | ||
(async () => { | ||
const operationId = generateID(); | ||
request = { | ||
...request, | ||
extensions: { ...request.extensions, operationId }, | ||
}; | ||
let complete = null; | ||
for (;;) { | ||
complete = null; | ||
try { | ||
const { url, headers, getResults } = await getOrConnect(); | ||
let res; | ||
try { | ||
res = await fetchFn(url, { | ||
signal: control.signal, | ||
method: 'POST', | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
headers: { | ||
...headers, | ||
'content-type': 'application/json; charset=utf-8', | ||
}, | ||
body: JSON.stringify(request), | ||
}); | ||
} | ||
catch (err) { | ||
throw new NetworkError(err); | ||
} | ||
if (res.status !== 202) | ||
throw new NetworkError(res); | ||
complete = async () => { | ||
let res; | ||
try { | ||
const control = new AbortControllerImpl(); | ||
const unlisten = client.onDispose(() => { | ||
unlisten(); | ||
control.abort(); | ||
}); | ||
res = await fetchFn(url + '?operationId=' + operationId, { | ||
signal: control.signal, | ||
method: 'DELETE', | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
headers, | ||
}); | ||
} | ||
catch (err) { | ||
throw new NetworkError(err); | ||
} | ||
if (res.status !== 200) | ||
throw new NetworkError(res); | ||
}; | ||
for await (const result of getResults({ | ||
signal: control.signal, | ||
operationId, | ||
})) { | ||
// only after receiving results are future connects not considered retries. | ||
// this is because a client might successfully connect, but the server | ||
// ends up terminating the connection afterwards before streaming anything. | ||
// of course, if the client completes the subscription, this loop will | ||
// break and therefore stop the stream (it wont reconnect) | ||
retryingErr = null; | ||
retries = 0; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
sink.next(result); | ||
} | ||
complete = null; // completed by the server | ||
return control.abort(); | ||
} | ||
catch (err) { | ||
if (control.signal.aborted) | ||
return await (complete === null || complete === void 0 ? void 0 : complete()); | ||
// all non-network errors are worth reporting immediately | ||
if (!(err instanceof NetworkError)) { | ||
control.abort(); // TODO: tests for making sure the control's aborted | ||
throw err; | ||
} | ||
// was a network error, get rid of the current connection to ensure retries | ||
// but only if the client is running in lazy mode (otherwise the non-lazy lock will get rid of the connection) | ||
if (lazy) { | ||
conn = undefined; | ||
} | ||
// retries are not allowed or we tried to many times, report error | ||
if (!retryAttempts || retries >= retryAttempts) { | ||
control.abort(); // TODO: tests for making sure the control's aborted | ||
throw err; | ||
} | ||
// try again | ||
retryingErr = err; | ||
} | ||
finally { | ||
// release lock if subscription is aborted | ||
if (control.signal.aborted && --locks === 0) { | ||
if (isFinite(lazyCloseTimeout) && lazyCloseTimeout > 0) { | ||
// allow for the specified calmdown time and then close the | ||
// connection, only if no lock got created in the meantime and | ||
// if the connection is still open | ||
setTimeout(() => { | ||
if (!locks) | ||
connCtrl.abort(); | ||
}, lazyCloseTimeout); | ||
} | ||
else { | ||
// otherwise close immediately | ||
connCtrl.abort(); | ||
} | ||
} | ||
} | ||
} | ||
})() | ||
.then(() => sink.complete()) | ||
.catch((err) => sink.error(err)); | ||
return () => control.abort(); | ||
} | ||
return { | ||
subscribe, | ||
iterate(request, on) { | ||
const pending = []; | ||
@@ -414,4 +430,5 @@ const deferred = { | ||
}; | ||
const dispose = this.subscribe(request, { | ||
const dispose = subscribe(request, { | ||
next(val) { | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
pending.push(val); | ||
@@ -429,3 +446,3 @@ deferred.resolve(); | ||
}, | ||
}); | ||
}, on); | ||
const iterator = (async function* iterator() { | ||
@@ -432,0 +449,0 @@ for (;;) { |
{ | ||
"name": "graphql-sse", | ||
"version": "2.3.0", | ||
"version": "2.4.0", | ||
"description": "Zero-dependency, HTTP/1 safe, simple, GraphQL over Server-Sent Events Protocol server and client", | ||
@@ -29,3 +29,3 @@ "keywords": [ | ||
}, | ||
"packageManager": "yarn@3.6.2", | ||
"packageManager": "yarn@4.0.2", | ||
"main": "lib/index.js", | ||
@@ -102,33 +102,33 @@ "module": "lib/index.mjs", | ||
"devDependencies": { | ||
"@rollup/plugin-terser": "^0.4.3", | ||
"@rollup/plugin-typescript": "^11.1.3", | ||
"@rollup/plugin-terser": "^0.4.4", | ||
"@rollup/plugin-typescript": "^11.1.5", | ||
"@semantic-release/changelog": "^6.0.3", | ||
"@semantic-release/git": "^10.0.1", | ||
"@types/eslint": "^8.44.2", | ||
"@types/eventsource": "^1.1.11", | ||
"@types/express": "^4.17.17", | ||
"@types/eslint": "^8.44.7", | ||
"@types/eventsource": "^1.1.15", | ||
"@types/express": "^4.17.21", | ||
"@types/glob": "^8.1.0", | ||
"@types/koa": "^2.13.8", | ||
"@types/koa-mount": "^4.0.2", | ||
"@typescript-eslint/eslint-plugin": "^6.6.0", | ||
"@typescript-eslint/parser": "^6.6.0", | ||
"eslint": "^8.48.0", | ||
"@types/koa": "^2.13.12", | ||
"@types/koa-mount": "^4.0.5", | ||
"@typescript-eslint/eslint-plugin": "^6.13.1", | ||
"@typescript-eslint/parser": "^6.13.1", | ||
"eslint": "^8.54.0", | ||
"eslint-config-prettier": "^9.0.0", | ||
"eventsource": "^2.0.2", | ||
"express": "^4.18.2", | ||
"fastify": "^4.22.2", | ||
"glob": "^10.3.4", | ||
"graphql": "^16.8.0", | ||
"fastify": "^4.24.3", | ||
"glob": "^10.3.10", | ||
"graphql": "^16.8.1", | ||
"koa": "^2.14.2", | ||
"koa-mount": "^4.0.0", | ||
"prettier": "^3.0.3", | ||
"rollup": "^3.29.0", | ||
"prettier": "^3.1.0", | ||
"rollup": "^4.6.0", | ||
"rollup-plugin-gzip": "^3.1.0", | ||
"semantic-release": "^21.1.1", | ||
"semantic-release": "^22.0.8", | ||
"tslib": "^2.6.2", | ||
"typedoc": "^0.25.1", | ||
"typedoc-plugin-markdown": "^3.16.0", | ||
"typescript": "^5.2.2", | ||
"vitest": "^0.34.3" | ||
"typedoc": "^0.25.4", | ||
"typedoc-plugin-markdown": "^3.17.1", | ||
"typescript": "^5.3.2", | ||
"vitest": "^0.34.6" | ||
} | ||
} |
@@ -1,3 +0,1 @@ | ||
[![GraphQL Conf 2023](/GraphQLConf-2023-Banner.png)](https://graphql.org/conf/) | ||
<div align="center"> | ||
@@ -4,0 +2,0 @@ <br /> |
@@ -258,3 +258,3 @@ (function (global, factory) { | ||
Math.floor(Math.random() * (3000 - 300) + 300))); | ||
}, credentials = 'same-origin', referrer, referrerPolicy, onMessage, } = options; | ||
}, credentials = 'same-origin', referrer, referrerPolicy, onMessage, on: clientOn, } = options; | ||
const fetchFn = (options.fetchFn || fetch); | ||
@@ -302,3 +302,3 @@ const AbortControllerImpl = (options.abortControllerImpl || | ||
return await (conn !== null && conn !== void 0 ? conn : (conn = (async () => { | ||
var _a; | ||
var _a, _b, _c; | ||
if (retryingErr) { | ||
@@ -311,2 +311,3 @@ await retry(retries); | ||
} | ||
(_a = clientOn === null || clientOn === void 0 ? void 0 : clientOn.connecting) === null || _a === void 0 ? void 0 : _a.call(clientOn, !!retryingErr); | ||
// we must create a new controller here because lazy mode aborts currently active ones | ||
@@ -326,3 +327,3 @@ connCtrl = new AbortControllerImpl(); | ||
? await options.headers() | ||
: (_a = options.headers) !== null && _a !== void 0 ? _a : {}; | ||
: (_b = options.headers) !== null && _b !== void 0 ? _b : {}; | ||
if (connCtrl.signal.aborted) | ||
@@ -356,4 +357,9 @@ throw new Error('Connection aborted by the client'); | ||
fetchFn, | ||
onMessage, | ||
onMessage: (msg) => { | ||
var _a; | ||
(_a = clientOn === null || clientOn === void 0 ? void 0 : clientOn.message) === null || _a === void 0 ? void 0 : _a.call(clientOn, msg); | ||
onMessage === null || onMessage === void 0 ? void 0 : onMessage(msg); // @deprecated | ||
}, | ||
}); | ||
(_c = clientOn === null || clientOn === void 0 ? void 0 : clientOn.connected) === null || _c === void 0 ? void 0 : _c.call(clientOn, !!retryingErr); | ||
connected.waitForThrow().catch(() => (conn = undefined)); | ||
@@ -395,80 +401,5 @@ return connected; | ||
} | ||
return { | ||
subscribe(request, sink) { | ||
if (!singleConnection) { | ||
// distinct connections mode | ||
const control = new AbortControllerImpl(); | ||
const unlisten = client.onDispose(() => { | ||
unlisten(); | ||
control.abort(); | ||
}); | ||
(async () => { | ||
var _a; | ||
let retryingErr = null, retries = 0; | ||
for (;;) { | ||
try { | ||
if (retryingErr) { | ||
await retry(retries); | ||
// connection might've been aborted while waiting for retry | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
retries++; | ||
} | ||
const url = typeof options.url === 'function' | ||
? await options.url() | ||
: options.url; | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
const headers = typeof options.headers === 'function' | ||
? await options.headers() | ||
: (_a = options.headers) !== null && _a !== void 0 ? _a : {}; | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
const { getResults } = await connect({ | ||
signal: control.signal, | ||
headers: { | ||
...headers, | ||
'content-type': 'application/json; charset=utf-8', | ||
}, | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
url, | ||
body: JSON.stringify(request), | ||
fetchFn, | ||
onMessage, | ||
}); | ||
for await (const result of getResults()) { | ||
// only after receiving results are future connects not considered retries. | ||
// this is because a client might successfully connect, but the server | ||
// ends up terminating the connection afterwards before streaming anything. | ||
// of course, if the client completes the subscription, this loop will | ||
// break and therefore stop the stream (it wont reconnect) | ||
retryingErr = null; | ||
retries = 0; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
sink.next(result); | ||
} | ||
return control.abort(); | ||
} | ||
catch (err) { | ||
if (control.signal.aborted) | ||
return; | ||
// all non-network errors are worth reporting immediately | ||
if (!(err instanceof NetworkError)) | ||
throw err; | ||
// retries are not allowed or we tried to many times, report error | ||
if (!retryAttempts || retries >= retryAttempts) | ||
throw err; | ||
// try again | ||
retryingErr = err; | ||
} | ||
} | ||
})() | ||
.then(() => sink.complete()) | ||
.catch((err) => sink.error(err)); | ||
return () => control.abort(); | ||
} | ||
// single connection mode | ||
locks++; | ||
function subscribe(request, sink, on) { | ||
if (!singleConnection) { | ||
// distinct connections mode | ||
const control = new AbortControllerImpl(); | ||
@@ -480,59 +411,47 @@ const unlisten = client.onDispose(() => { | ||
(async () => { | ||
const operationId = generateID(); | ||
request = { | ||
...request, | ||
extensions: { ...request.extensions, operationId }, | ||
}; | ||
let complete = null; | ||
var _a, _b, _c, _d, _e; | ||
let retryingErr = null, retries = 0; | ||
for (;;) { | ||
complete = null; | ||
try { | ||
const { url, headers, getResults } = await getOrConnect(); | ||
let res; | ||
try { | ||
res = await fetchFn(url, { | ||
signal: control.signal, | ||
method: 'POST', | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
headers: { | ||
...headers, | ||
'content-type': 'application/json; charset=utf-8', | ||
}, | ||
body: JSON.stringify(request), | ||
}); | ||
if (retryingErr) { | ||
await retry(retries); | ||
// connection might've been aborted while waiting for retry | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
retries++; | ||
} | ||
catch (err) { | ||
throw new NetworkError(err); | ||
} | ||
if (res.status !== 202) | ||
throw new NetworkError(res); | ||
complete = async () => { | ||
let res; | ||
try { | ||
const control = new AbortControllerImpl(); | ||
const unlisten = client.onDispose(() => { | ||
unlisten(); | ||
control.abort(); | ||
}); | ||
res = await fetchFn(url + '?operationId=' + operationId, { | ||
signal: control.signal, | ||
method: 'DELETE', | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
headers, | ||
}); | ||
} | ||
catch (err) { | ||
throw new NetworkError(err); | ||
} | ||
if (res.status !== 200) | ||
throw new NetworkError(res); | ||
}; | ||
for await (const result of getResults({ | ||
(_a = clientOn === null || clientOn === void 0 ? void 0 : clientOn.connecting) === null || _a === void 0 ? void 0 : _a.call(clientOn, !!retryingErr); | ||
(_b = on === null || on === void 0 ? void 0 : on.connecting) === null || _b === void 0 ? void 0 : _b.call(on, !!retryingErr); | ||
const url = typeof options.url === 'function' | ||
? await options.url() | ||
: options.url; | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
const headers = typeof options.headers === 'function' | ||
? await options.headers() | ||
: (_c = options.headers) !== null && _c !== void 0 ? _c : {}; | ||
if (control.signal.aborted) | ||
throw new Error('Connection aborted by the client'); | ||
const { getResults } = await connect({ | ||
signal: control.signal, | ||
operationId, | ||
})) { | ||
headers: { | ||
...headers, | ||
'content-type': 'application/json; charset=utf-8', | ||
}, | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
url, | ||
body: JSON.stringify(request), | ||
fetchFn, | ||
onMessage: (msg) => { | ||
var _a, _b; | ||
(_a = clientOn === null || clientOn === void 0 ? void 0 : clientOn.message) === null || _a === void 0 ? void 0 : _a.call(clientOn, msg); | ||
(_b = on === null || on === void 0 ? void 0 : on.message) === null || _b === void 0 ? void 0 : _b.call(on, msg); | ||
onMessage === null || onMessage === void 0 ? void 0 : onMessage(msg); // @deprecated | ||
}, | ||
}); | ||
(_d = clientOn === null || clientOn === void 0 ? void 0 : clientOn.connected) === null || _d === void 0 ? void 0 : _d.call(clientOn, !!retryingErr); | ||
(_e = on === null || on === void 0 ? void 0 : on.connected) === null || _e === void 0 ? void 0 : _e.call(on, !!retryingErr); | ||
for await (const result of getResults()) { | ||
// only after receiving results are future connects not considered retries. | ||
@@ -548,3 +467,2 @@ // this is because a client might successfully connect, but the server | ||
} | ||
complete = null; // completed by the server | ||
return control.abort(); | ||
@@ -554,39 +472,12 @@ } | ||
if (control.signal.aborted) | ||
return await (complete === null || complete === void 0 ? void 0 : complete()); | ||
return; | ||
// all non-network errors are worth reporting immediately | ||
if (!(err instanceof NetworkError)) { | ||
control.abort(); // TODO: tests for making sure the control's aborted | ||
if (!(err instanceof NetworkError)) | ||
throw err; | ||
} | ||
// was a network error, get rid of the current connection to ensure retries | ||
// but only if the client is running in lazy mode (otherwise the non-lazy lock will get rid of the connection) | ||
if (lazy) { | ||
conn = undefined; | ||
} | ||
// retries are not allowed or we tried to many times, report error | ||
if (!retryAttempts || retries >= retryAttempts) { | ||
control.abort(); // TODO: tests for making sure the control's aborted | ||
if (!retryAttempts || retries >= retryAttempts) | ||
throw err; | ||
} | ||
// try again | ||
retryingErr = err; | ||
} | ||
finally { | ||
// release lock if subscription is aborted | ||
if (control.signal.aborted && --locks === 0) { | ||
if (isFinite(lazyCloseTimeout) && lazyCloseTimeout > 0) { | ||
// allow for the specified calmdown time and then close the | ||
// connection, only if no lock got created in the meantime and | ||
// if the connection is still open | ||
setTimeout(() => { | ||
if (!locks) | ||
connCtrl.abort(); | ||
}, lazyCloseTimeout); | ||
} | ||
else { | ||
// otherwise close immediately | ||
connCtrl.abort(); | ||
} | ||
} | ||
} | ||
} | ||
@@ -597,4 +488,129 @@ })() | ||
return () => control.abort(); | ||
}, | ||
iterate(request) { | ||
} | ||
// single connection mode | ||
locks++; | ||
const control = new AbortControllerImpl(); | ||
const unlisten = client.onDispose(() => { | ||
unlisten(); | ||
control.abort(); | ||
}); | ||
(async () => { | ||
const operationId = generateID(); | ||
request = { | ||
...request, | ||
extensions: { ...request.extensions, operationId }, | ||
}; | ||
let complete = null; | ||
for (;;) { | ||
complete = null; | ||
try { | ||
const { url, headers, getResults } = await getOrConnect(); | ||
let res; | ||
try { | ||
res = await fetchFn(url, { | ||
signal: control.signal, | ||
method: 'POST', | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
headers: { | ||
...headers, | ||
'content-type': 'application/json; charset=utf-8', | ||
}, | ||
body: JSON.stringify(request), | ||
}); | ||
} | ||
catch (err) { | ||
throw new NetworkError(err); | ||
} | ||
if (res.status !== 202) | ||
throw new NetworkError(res); | ||
complete = async () => { | ||
let res; | ||
try { | ||
const control = new AbortControllerImpl(); | ||
const unlisten = client.onDispose(() => { | ||
unlisten(); | ||
control.abort(); | ||
}); | ||
res = await fetchFn(url + '?operationId=' + operationId, { | ||
signal: control.signal, | ||
method: 'DELETE', | ||
credentials, | ||
referrer, | ||
referrerPolicy, | ||
headers, | ||
}); | ||
} | ||
catch (err) { | ||
throw new NetworkError(err); | ||
} | ||
if (res.status !== 200) | ||
throw new NetworkError(res); | ||
}; | ||
for await (const result of getResults({ | ||
signal: control.signal, | ||
operationId, | ||
})) { | ||
// only after receiving results are future connects not considered retries. | ||
// this is because a client might successfully connect, but the server | ||
// ends up terminating the connection afterwards before streaming anything. | ||
// of course, if the client completes the subscription, this loop will | ||
// break and therefore stop the stream (it wont reconnect) | ||
retryingErr = null; | ||
retries = 0; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
sink.next(result); | ||
} | ||
complete = null; // completed by the server | ||
return control.abort(); | ||
} | ||
catch (err) { | ||
if (control.signal.aborted) | ||
return await (complete === null || complete === void 0 ? void 0 : complete()); | ||
// all non-network errors are worth reporting immediately | ||
if (!(err instanceof NetworkError)) { | ||
control.abort(); // TODO: tests for making sure the control's aborted | ||
throw err; | ||
} | ||
// was a network error, get rid of the current connection to ensure retries | ||
// but only if the client is running in lazy mode (otherwise the non-lazy lock will get rid of the connection) | ||
if (lazy) { | ||
conn = undefined; | ||
} | ||
// retries are not allowed or we tried to many times, report error | ||
if (!retryAttempts || retries >= retryAttempts) { | ||
control.abort(); // TODO: tests for making sure the control's aborted | ||
throw err; | ||
} | ||
// try again | ||
retryingErr = err; | ||
} | ||
finally { | ||
// release lock if subscription is aborted | ||
if (control.signal.aborted && --locks === 0) { | ||
if (isFinite(lazyCloseTimeout) && lazyCloseTimeout > 0) { | ||
// allow for the specified calmdown time and then close the | ||
// connection, only if no lock got created in the meantime and | ||
// if the connection is still open | ||
setTimeout(() => { | ||
if (!locks) | ||
connCtrl.abort(); | ||
}, lazyCloseTimeout); | ||
} | ||
else { | ||
// otherwise close immediately | ||
connCtrl.abort(); | ||
} | ||
} | ||
} | ||
} | ||
})() | ||
.then(() => sink.complete()) | ||
.catch((err) => sink.error(err)); | ||
return () => control.abort(); | ||
} | ||
return { | ||
subscribe, | ||
iterate(request, on) { | ||
const pending = []; | ||
@@ -608,4 +624,5 @@ const deferred = { | ||
}; | ||
const dispose = this.subscribe(request, { | ||
const dispose = subscribe(request, { | ||
next(val) { | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
pending.push(val); | ||
@@ -623,3 +640,3 @@ deferred.resolve(); | ||
}, | ||
}); | ||
}, on); | ||
const iterator = (async function* iterator() { | ||
@@ -626,0 +643,0 @@ for (;;) { |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).graphqlSse={})}(this,(function(e){"use strict";function t(e){return"object"==typeof e&&null!==e}const r="x-graphql-event-stream-token";function n(e){if("next"!==e&&"complete"!==e)throw new Error(`Invalid stream event "${e}"`);return e}function o(e,t){if(t)try{t=JSON.parse(t)}catch{throw new Error("Invalid stream data")}if("next"===e&&!t)throw new Error('Stream data must be an object for "next" events');return t||null}var a;!function(e){e[e.NewLine=10]="NewLine",e[e.CchunkiageReturn=13]="CchunkiageReturn",e[e.Space=32]="Space",e[e.Colon=58]="Colon"}(a||(a={}));class i extends Error{constructor(e){let r,n;var o;t(o=e)&&"boolean"==typeof o.ok&&"number"==typeof o.status&&"string"==typeof o.statusText?(n=e,r="Server responded with "+e.status+": "+e.statusText):r=e instanceof Error?e.message:String(e),super(r),this.name=this.constructor.name,this.response=n}}async function s(e){const{signal:t,url:r,credentials:s,headers:c,body:l,referrer:f,referrerPolicy:d,fetchFn:u,onMessage:h}=e,w={},y={};let b;try{b=await u(r,{signal:t,method:l?"POST":"GET",credentials:s,referrer:f,referrerPolicy:d,headers:{...c,accept:"text/event-stream"},body:l})}catch(e){throw new i(e)}if(!b.ok)throw new i(b);if(!b.body)throw new Error("Missing response body");let p,g=null;return(async()=>{var e;try{const t=function(){let e,t,r,i=!1,s={event:"",data:""},c=[];const l=new TextDecoder;return function(f){if(void 0===e)e=f,t=0,r=-1;else{const t=new Uint8Array(e.length+f.length);t.set(e),t.set(f,e.length),e=t}const d=e.length;let u=0;for(;t<d;){i&&(e[t]===a.NewLine&&(u=++t),i=!1);let f=-1;for(;t<d&&-1===f;++t)switch(e[t]){case a.Colon:-1===r&&(r=t-u);break;case a.CchunkiageReturn:i=!0;case a.NewLine:f=t}if(-1===f)break;if(u===f){if(s.event||s.data){if(!s.event)throw new Error("Missing message event");const e=n(s.event),t=o(e,s.data);c.push({event:e,data:t}),s={event:"",data:""}}}else if(r>0){const t=e.subarray(u,f),n=l.decode(t.subarray(0,r)),o=r+(t[r+1]===a.Space?2:1),i=l.decode(t.subarray(o));switch(n){case"event":s.event=i;break;case"data":s.data=s.data?s.data+"\n"+i:i}}u=t,r=-1}if(u===d){e=void 0;const t=[...c];return c=[],t}0!==u&&(e=e.subarray(u),t-=u)}}();for await(const r of function(e){if("function"==typeof Object(e)[Symbol.asyncIterator])return e[Symbol.asyncIterator]();return async function*(){const t=e.getReader();let r;do{r=await t.read(),void 0!==r.value&&(yield r.value)}while(!r.done)}()}(b.body)){if("string"==typeof r)throw g=new Error(`Unexpected string chunk "${r}"`);let n;try{n=t(r)}catch(e){throw g=e}if(n)for(const t of n){try{null==h||h(t)}catch(e){throw g=e}const r=t.data&&"id"in t.data?t.data.id:"";switch(r in y||(y[r]=[]),t.event){case"next":r?y[r].push(t.data.payload):y[r].push(t.data);break;case"complete":y[r].push("complete");break;default:throw g=new Error(`Unexpected message event "${t.event}"`)}null===(e=w[r])||void 0===e||e.proceed()}}if(Object.keys(w).length)throw new Error("Connection closed while having active streams")}catch(e){g=!g&&Object.keys(w).length?new i(e):e,null==p||p(g)}finally{Object.values(w).forEach((({proceed:e})=>e()))}})(),{url:r,headers:c,waitForThrow:()=>new Promise(((e,t)=>{if(g)return t(g);p=t})),async*getResults(e){var t;const{signal:r,operationId:n=""}=null!=e?e:{};try{for(;;){for(;null===(t=y[n])||void 0===t?void 0:t.length;){const e=y[n].shift();if("complete"===e)return;yield e}if(g)throw g;if(null==r?void 0:r.aborted)throw new Error("Getting results aborted by the client");await new Promise((e=>{const t=()=>{null==r||r.removeEventListener("abort",t),delete w[n],e()};null==r||r.addEventListener("abort",t),w[n]={proceed:t}}))}}finally{delete y[n]}}}}e.NetworkError=i,e.TOKEN_HEADER_KEY=r,e.TOKEN_QUERY_KEY="token",e.createClient=function(e){const{singleConnection:t=!1,lazy:n=!0,lazyCloseTimeout:o=0,onNonLazyError:a=console.error,generateID:c=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)}))},retryAttempts:l=5,retry:f=async function(e){let t=1e3;for(let r=0;r<e;r++)t*=2;await new Promise((e=>setTimeout(e,t+Math.floor(2700*Math.random()+300))))},credentials:d="same-origin",referrer:u,referrerPolicy:h,onMessage:w}=e,y=e.fetchFn||fetch,b=e.abortControllerImpl||AbortController,p=(()=>{let e=!1;const t=[];return{get disposed(){return e},onDispose:r=>e?(setTimeout((()=>r()),0),()=>{}):(t.push(r),()=>{t.splice(t.indexOf(r),1)}),dispose(){if(!e){e=!0;for(const e of[...t])e()}}}})();let g,v,x=0,m=null,E=0;async function S(){try{if(p.disposed)throw new Error("Client has been disposed");return await(null!=v?v:v=(async()=>{var t;if(m){if(await f(E),g.signal.aborted)throw new Error("Connection aborted by the client");E++}g=new b;const n=p.onDispose((()=>g.abort()));g.signal.addEventListener("abort",(()=>{n(),v=void 0}));const o="function"==typeof e.url?await e.url():e.url;if(g.signal.aborted)throw new Error("Connection aborted by the client");const a="function"==typeof e.headers?await e.headers():null!==(t=e.headers)&&void 0!==t?t:{};if(g.signal.aborted)throw new Error("Connection aborted by the client");let c;try{c=await y(o,{signal:g.signal,method:"PUT",credentials:d,referrer:u,referrerPolicy:h,headers:a})}catch(e){throw new i(e)}if(201!==c.status)throw new i(c);const l=await c.text();a[r]=l;const x=await s({signal:g.signal,headers:a,credentials:d,referrer:u,referrerPolicy:h,url:o,fetchFn:y,onMessage:w});return x.waitForThrow().catch((()=>v=void 0)),x})())}catch(e){throw v=void 0,e}}return t&&!n&&(async()=>{for(x++;;)try{const{waitForThrow:e}=await S();await e()}catch(e){if(p.disposed)return;if(!(e instanceof i))return null==a?void 0:a(e);if(v=void 0,!l||E>=l)return null==a?void 0:a(e);m=e}})(),{subscribe(r,a){if(!t){const t=new b,n=p.onDispose((()=>{n(),t.abort()}));return(async()=>{var n;let o=null,c=0;for(;;)try{if(o){if(await f(c),t.signal.aborted)throw new Error("Connection aborted by the client");c++}const i="function"==typeof e.url?await e.url():e.url;if(t.signal.aborted)throw new Error("Connection aborted by the client");const l="function"==typeof e.headers?await e.headers():null!==(n=e.headers)&&void 0!==n?n:{};if(t.signal.aborted)throw new Error("Connection aborted by the client");const{getResults:b}=await s({signal:t.signal,headers:{...l,"content-type":"application/json; charset=utf-8"},credentials:d,referrer:u,referrerPolicy:h,url:i,body:JSON.stringify(r),fetchFn:y,onMessage:w});for await(const e of b())o=null,c=0,a.next(e);return t.abort()}catch(e){if(t.signal.aborted)return;if(!(e instanceof i))throw e;if(!l||c>=l)throw e;o=e}})().then((()=>a.complete())).catch((e=>a.error(e))),()=>t.abort()}x++;const C=new b,T=p.onDispose((()=>{T(),C.abort()}));return(async()=>{const e=c();r={...r,extensions:{...r.extensions,operationId:e}};let t=null;for(;;){t=null;try{const{url:n,headers:o,getResults:s}=await S();let c;try{c=await y(n,{signal:C.signal,method:"POST",credentials:d,referrer:u,referrerPolicy:h,headers:{...o,"content-type":"application/json; charset=utf-8"},body:JSON.stringify(r)})}catch(e){throw new i(e)}if(202!==c.status)throw new i(c);t=async()=>{let t;try{const r=new b,a=p.onDispose((()=>{a(),r.abort()}));t=await y(n+"?operationId="+e,{signal:r.signal,method:"DELETE",credentials:d,referrer:u,referrerPolicy:h,headers:o})}catch(e){throw new i(e)}if(200!==t.status)throw new i(t)};for await(const t of s({signal:C.signal,operationId:e}))m=null,E=0,a.next(t);return t=null,C.abort()}catch(e){if(C.signal.aborted)return await(null==t?void 0:t());if(!(e instanceof i))throw C.abort(),e;if(n&&(v=void 0),!l||E>=l)throw C.abort(),e;m=e}finally{C.signal.aborted&&0==--x&&(isFinite(o)&&o>0?setTimeout((()=>{x||g.abort()}),o):g.abort())}}})().then((()=>a.complete())).catch((e=>a.error(e))),()=>C.abort()},iterate(e){const t=[],r={done:!1,error:null,resolve:()=>{}},n=this.subscribe(e,{next(e){t.push(e),r.resolve()},error(e){r.done=!0,r.error=e,r.resolve()},complete(){r.done=!0,r.resolve()}}),o=async function*(){for(;;){for(t.length||await new Promise((e=>r.resolve=e));t.length;)yield t.shift();if(r.error)throw r.error;if(r.done)return}}();return o.throw=async e=>(r.done||(r.done=!0,r.error=e,r.resolve()),{done:!0,value:void 0}),o.return=async()=>(n(),{done:!0,value:void 0}),o},dispose(){p.dispose()}}},e.isAsyncGenerator=function(e){return t(e)&&"function"==typeof Object(e)[Symbol.asyncIterator]&&"function"==typeof e.return&&"function"==typeof e.throw&&"function"==typeof e.next},e.isAsyncIterable=function(e){return"function"==typeof Object(e)[Symbol.asyncIterator]},e.parseStreamData=o,e.print=function(e){let t=`event: ${e.event}\ndata:`;return e.data&&(t+=" ",t+=JSON.stringify(e.data)),t+="\n\n",t},e.validateStreamEvent=n})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).graphqlSse={})}(this,(function(e){"use strict";function t(e){return"object"==typeof e&&null!==e}const n="x-graphql-event-stream-token";function r(e){if("next"!==e&&"complete"!==e)throw new Error(`Invalid stream event "${e}"`);return e}function o(e,t){if(t)try{t=JSON.parse(t)}catch{throw new Error("Invalid stream data")}if("next"===e&&!t)throw new Error('Stream data must be an object for "next" events');return t||null}var a;!function(e){e[e.NewLine=10]="NewLine",e[e.CchunkiageReturn=13]="CchunkiageReturn",e[e.Space=32]="Space",e[e.Colon=58]="Colon"}(a||(a={}));class i extends Error{constructor(e){let n,r;var o;t(o=e)&&"boolean"==typeof o.ok&&"number"==typeof o.status&&"string"==typeof o.statusText?(r=e,n="Server responded with "+e.status+": "+e.statusText):n=e instanceof Error?e.message:String(e),super(n),this.name=this.constructor.name,this.response=r}}async function s(e){const{signal:t,url:n,credentials:s,headers:l,body:c,referrer:d,referrerPolicy:u,fetchFn:f,onMessage:h}=e,w={},y={};let v;try{v=await f(n,{signal:t,method:c?"POST":"GET",credentials:s,referrer:d,referrerPolicy:u,headers:{...l,accept:"text/event-stream"},body:c})}catch(e){throw new i(e)}if(!v.ok)throw new i(v);if(!v.body)throw new Error("Missing response body");let p,b=null;return(async()=>{var e;try{const t=function(){let e,t,n,i=!1,s={event:"",data:""},l=[];const c=new TextDecoder;return function(d){if(void 0===e)e=d,t=0,n=-1;else{const t=new Uint8Array(e.length+d.length);t.set(e),t.set(d,e.length),e=t}const u=e.length;let f=0;for(;t<u;){i&&(e[t]===a.NewLine&&(f=++t),i=!1);let d=-1;for(;t<u&&-1===d;++t)switch(e[t]){case a.Colon:-1===n&&(n=t-f);break;case a.CchunkiageReturn:i=!0;case a.NewLine:d=t}if(-1===d)break;if(f===d){if(s.event||s.data){if(!s.event)throw new Error("Missing message event");const e=r(s.event),t=o(e,s.data);l.push({event:e,data:t}),s={event:"",data:""}}}else if(n>0){const t=e.subarray(f,d),r=c.decode(t.subarray(0,n)),o=n+(t[n+1]===a.Space?2:1),i=c.decode(t.subarray(o));switch(r){case"event":s.event=i;break;case"data":s.data=s.data?s.data+"\n"+i:i}}f=t,n=-1}if(f===u){e=void 0;const t=[...l];return l=[],t}0!==f&&(e=e.subarray(f),t-=f)}}();for await(const n of function(e){if("function"==typeof Object(e)[Symbol.asyncIterator])return e[Symbol.asyncIterator]();return async function*(){const t=e.getReader();let n;do{n=await t.read(),void 0!==n.value&&(yield n.value)}while(!n.done)}()}(v.body)){if("string"==typeof n)throw b=new Error(`Unexpected string chunk "${n}"`);let r;try{r=t(n)}catch(e){throw b=e}if(r)for(const t of r){try{null==h||h(t)}catch(e){throw b=e}const n=t.data&&"id"in t.data?t.data.id:"";switch(n in y||(y[n]=[]),t.event){case"next":n?y[n].push(t.data.payload):y[n].push(t.data);break;case"complete":y[n].push("complete");break;default:throw b=new Error(`Unexpected message event "${t.event}"`)}null===(e=w[n])||void 0===e||e.proceed()}}if(Object.keys(w).length)throw new Error("Connection closed while having active streams")}catch(e){b=!b&&Object.keys(w).length?new i(e):e,null==p||p(b)}finally{Object.values(w).forEach((({proceed:e})=>e()))}})(),{url:n,headers:l,waitForThrow:()=>new Promise(((e,t)=>{if(b)return t(b);p=t})),async*getResults(e){var t;const{signal:n,operationId:r=""}=null!=e?e:{};try{for(;;){for(;null===(t=y[r])||void 0===t?void 0:t.length;){const e=y[r].shift();if("complete"===e)return;yield e}if(b)throw b;if(null==n?void 0:n.aborted)throw new Error("Getting results aborted by the client");await new Promise((e=>{const t=()=>{null==n||n.removeEventListener("abort",t),delete w[r],e()};null==n||n.addEventListener("abort",t),w[r]={proceed:t}}))}}finally{delete y[r]}}}}e.NetworkError=i,e.TOKEN_HEADER_KEY=n,e.TOKEN_QUERY_KEY="token",e.createClient=function(e){const{singleConnection:t=!1,lazy:r=!0,lazyCloseTimeout:o=0,onNonLazyError:a=console.error,generateID:l=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)}))},retryAttempts:c=5,retry:d=async function(e){let t=1e3;for(let n=0;n<e;n++)t*=2;await new Promise((e=>setTimeout(e,t+Math.floor(2700*Math.random()+300))))},credentials:u="same-origin",referrer:f,referrerPolicy:h,onMessage:w,on:y}=e,v=e.fetchFn||fetch,p=e.abortControllerImpl||AbortController,b=(()=>{let e=!1;const t=[];return{get disposed(){return e},onDispose:n=>e?(setTimeout((()=>n()),0),()=>{}):(t.push(n),()=>{t.splice(t.indexOf(n),1)}),dispose(){if(!e){e=!0;for(const e of[...t])e()}}}})();let g,x,m=0,E=null,S=0;async function C(){try{if(b.disposed)throw new Error("Client has been disposed");return await(null!=x?x:x=(async()=>{var t,r,o;if(E){if(await d(S),g.signal.aborted)throw new Error("Connection aborted by the client");S++}null===(t=null==y?void 0:y.connecting)||void 0===t||t.call(y,!!E),g=new p;const a=b.onDispose((()=>g.abort()));g.signal.addEventListener("abort",(()=>{a(),x=void 0}));const l="function"==typeof e.url?await e.url():e.url;if(g.signal.aborted)throw new Error("Connection aborted by the client");const c="function"==typeof e.headers?await e.headers():null!==(r=e.headers)&&void 0!==r?r:{};if(g.signal.aborted)throw new Error("Connection aborted by the client");let m;try{m=await v(l,{signal:g.signal,method:"PUT",credentials:u,referrer:f,referrerPolicy:h,headers:c})}catch(e){throw new i(e)}if(201!==m.status)throw new i(m);const C=await m.text();c[n]=C;const T=await s({signal:g.signal,headers:c,credentials:u,referrer:f,referrerPolicy:h,url:l,fetchFn:v,onMessage:e=>{var t;null===(t=null==y?void 0:y.message)||void 0===t||t.call(y,e),null==w||w(e)}});return null===(o=null==y?void 0:y.connected)||void 0===o||o.call(y,!!E),T.waitForThrow().catch((()=>x=void 0)),T})())}catch(e){throw x=void 0,e}}function T(n,a,T){if(!t){const t=new p,r=b.onDispose((()=>{r(),t.abort()}));return(async()=>{var r,o,l,p,b;let g=null,x=0;for(;;)try{if(g){if(await d(x),t.signal.aborted)throw new Error("Connection aborted by the client");x++}null===(r=null==y?void 0:y.connecting)||void 0===r||r.call(y,!!g),null===(o=null==T?void 0:T.connecting)||void 0===o||o.call(T,!!g);const i="function"==typeof e.url?await e.url():e.url;if(t.signal.aborted)throw new Error("Connection aborted by the client");const c="function"==typeof e.headers?await e.headers():null!==(l=e.headers)&&void 0!==l?l:{};if(t.signal.aborted)throw new Error("Connection aborted by the client");const{getResults:m}=await s({signal:t.signal,headers:{...c,"content-type":"application/json; charset=utf-8"},credentials:u,referrer:f,referrerPolicy:h,url:i,body:JSON.stringify(n),fetchFn:v,onMessage:e=>{var t,n;null===(t=null==y?void 0:y.message)||void 0===t||t.call(y,e),null===(n=null==T?void 0:T.message)||void 0===n||n.call(T,e),null==w||w(e)}});null===(p=null==y?void 0:y.connected)||void 0===p||p.call(y,!!g),null===(b=null==T?void 0:T.connected)||void 0===b||b.call(T,!!g);for await(const e of m())g=null,x=0,a.next(e);return t.abort()}catch(e){if(t.signal.aborted)return;if(!(e instanceof i))throw e;if(!c||x>=c)throw e;g=e}})().then((()=>a.complete())).catch((e=>a.error(e))),()=>t.abort()}m++;const k=new p,O=b.onDispose((()=>{O(),k.abort()}));return(async()=>{const e=l();n={...n,extensions:{...n.extensions,operationId:e}};let t=null;for(;;){t=null;try{const{url:r,headers:o,getResults:s}=await C();let l;try{l=await v(r,{signal:k.signal,method:"POST",credentials:u,referrer:f,referrerPolicy:h,headers:{...o,"content-type":"application/json; charset=utf-8"},body:JSON.stringify(n)})}catch(e){throw new i(e)}if(202!==l.status)throw new i(l);t=async()=>{let t;try{const n=new p,a=b.onDispose((()=>{a(),n.abort()}));t=await v(r+"?operationId="+e,{signal:n.signal,method:"DELETE",credentials:u,referrer:f,referrerPolicy:h,headers:o})}catch(e){throw new i(e)}if(200!==t.status)throw new i(t)};for await(const t of s({signal:k.signal,operationId:e}))E=null,S=0,a.next(t);return t=null,k.abort()}catch(e){if(k.signal.aborted)return await(null==t?void 0:t());if(!(e instanceof i))throw k.abort(),e;if(r&&(x=void 0),!c||S>=c)throw k.abort(),e;E=e}finally{k.signal.aborted&&0==--m&&(isFinite(o)&&o>0?setTimeout((()=>{m||g.abort()}),o):g.abort())}}})().then((()=>a.complete())).catch((e=>a.error(e))),()=>k.abort()}return t&&!r&&(async()=>{for(m++;;)try{const{waitForThrow:e}=await C();await e()}catch(e){if(b.disposed)return;if(!(e instanceof i))return null==a?void 0:a(e);if(x=void 0,!c||S>=c)return null==a?void 0:a(e);E=e}})(),{subscribe:T,iterate(e,t){const n=[],r={done:!1,error:null,resolve:()=>{}},o=T(e,{next(e){n.push(e),r.resolve()},error(e){r.done=!0,r.error=e,r.resolve()},complete(){r.done=!0,r.resolve()}},t),a=async function*(){for(;;){for(n.length||await new Promise((e=>r.resolve=e));n.length;)yield n.shift();if(r.error)throw r.error;if(r.done)return}}();return a.throw=async e=>(r.done||(r.done=!0,r.error=e,r.resolve()),{done:!0,value:void 0}),a.return=async()=>(o(),{done:!0,value:void 0}),a},dispose(){b.dispose()}}},e.isAsyncGenerator=function(e){return t(e)&&"function"==typeof Object(e)[Symbol.asyncIterator]&&"function"==typeof e.return&&"function"==typeof e.throw&&"function"==typeof e.next},e.isAsyncIterable=function(e){return"function"==typeof Object(e)[Symbol.asyncIterator]},e.parseStreamData=o,e.print=function(e){let t=`event: ${e.event}\ndata:`;return e.data&&(t+=" ",t+=JSON.stringify(e.data)),t+="\n\n",t},e.validateStreamEvent=r})); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
306917
6000
4
36