graphql-sse
Advanced tools
Comparing version 1.0.3 to 1.0.4
@@ -6,4 +6,3 @@ /** | ||
*/ | ||
import { ExecutionResult } from 'graphql'; | ||
import { RequestParams, Sink } from './common'; | ||
import { RequestParams, Sink, ExecutionResult } from './common'; | ||
/** This file is the entry point for browsers, re-export common elements. */ | ||
@@ -10,0 +9,0 @@ export * from './common'; |
@@ -6,3 +6,3 @@ /** | ||
*/ | ||
import type { DocumentNode, ExecutionResult } from 'graphql'; | ||
import type { DocumentNode, GraphQLError } from 'graphql'; | ||
/** | ||
@@ -37,7 +37,23 @@ * Parameters for GraphQL's request for execution. | ||
/** @category Common */ | ||
export declare type StreamData<E extends StreamEvent = StreamEvent> = E extends 'next' ? ExecutionResult : E extends 'complete' ? null : never; | ||
export interface ExecutionResult<Data = Record<string, unknown>, Extensions = Record<string, unknown>> { | ||
errors?: ReadonlyArray<GraphQLError>; | ||
data?: Data | null; | ||
hasNext?: boolean; | ||
extensions?: Extensions; | ||
} | ||
/** @category Common */ | ||
export interface ExecutionPatchResult<Data = unknown, Extensions = Record<string, unknown>> { | ||
errors?: ReadonlyArray<GraphQLError>; | ||
data?: Data | null; | ||
path?: ReadonlyArray<string | number>; | ||
label?: string; | ||
hasNext: boolean; | ||
extensions?: Extensions; | ||
} | ||
/** @category Common */ | ||
export declare type StreamData<E extends StreamEvent = StreamEvent> = E extends 'next' ? ExecutionResult | ExecutionPatchResult : E extends 'complete' ? null : never; | ||
/** @category Common */ | ||
export declare type StreamDataForID<E extends StreamEvent = StreamEvent> = E extends 'next' ? { | ||
id: string; | ||
payload: ExecutionResult; | ||
payload: ExecutionResult | ExecutionPatchResult; | ||
} : E extends 'complete' ? { | ||
@@ -44,0 +60,0 @@ id: string; |
@@ -8,4 +8,4 @@ /** | ||
import type { IncomingMessage, ServerResponse } from 'http'; | ||
import { ExecutionArgs, ExecutionResult, GraphQLSchema, validate as graphqlValidate } from 'graphql'; | ||
import { RequestParams } from './common'; | ||
import { ExecutionArgs, GraphQLSchema, validate as graphqlValidate } from 'graphql'; | ||
import { RequestParams, ExecutionResult, ExecutionPatchResult } from './common'; | ||
/** | ||
@@ -23,3 +23,3 @@ * A concrete GraphQL execution context value type. | ||
/** @category Server */ | ||
export declare type OperationResult = Promise<AsyncIterableIterator<ExecutionResult> | ExecutionResult> | AsyncIterableIterator<ExecutionResult> | ExecutionResult; | ||
export declare type OperationResult = Promise<AsyncGenerator<ExecutionResult | ExecutionPatchResult> | AsyncIterable<ExecutionResult | ExecutionPatchResult> | ExecutionResult> | AsyncGenerator<ExecutionResult | ExecutionPatchResult> | AsyncIterable<ExecutionResult | ExecutionPatchResult> | ExecutionResult; | ||
/** @category Server */ | ||
@@ -149,3 +149,3 @@ export interface HandlerOptions { | ||
*/ | ||
onNext?: (req: IncomingMessage, args: ExecutionArgs, result: ExecutionResult) => Promise<ExecutionResult | void> | ExecutionResult | void; | ||
onNext?: (req: IncomingMessage, args: ExecutionArgs, result: ExecutionResult | ExecutionPatchResult) => Promise<ExecutionResult | ExecutionPatchResult | void> | ExecutionResult | ExecutionPatchResult | void; | ||
/** | ||
@@ -220,1 +220,2 @@ * The complete callback is executed after the operation | ||
export declare function createHandler(options: HandlerOptions): Handler; | ||
export declare function isAsyncGenerator<T = unknown>(val: unknown): val is AsyncGenerator<T>; |
@@ -15,3 +15,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createHandler = void 0; | ||
exports.isAsyncGenerator = exports.createHandler = void 0; | ||
const graphql_1 = require("graphql"); | ||
@@ -77,4 +77,4 @@ const utils_1 = require("./utils"); | ||
for (const op of Object.values(ops)) { | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
await (op === null || op === void 0 ? void 0 : op.return()); // iterator must implement the return method | ||
if (isAsyncGenerator(op)) | ||
await op.return(undefined); | ||
} | ||
@@ -263,3 +263,3 @@ while (pendingMsgs.length) { | ||
return async function handler(req, res, body) { | ||
var _a, _b, _c, _d, _e; | ||
var _a, _b, _c, _d; | ||
// authenticate first and acquire unique identification token | ||
@@ -295,5 +295,4 @@ const token = await authenticate(req, res); | ||
if (res.writableEnded) { | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
if (isAsyncIterable(result)) | ||
result.return(); // iterator must implement the return method | ||
if (isAsyncGenerator(result)) | ||
result.return(undefined); | ||
return; // `onOperation` responded | ||
@@ -340,4 +339,5 @@ } | ||
return res.writeHead(400, 'Operation ID is missing').end(); | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
(_c = stream.ops[opId]) === null || _c === void 0 ? void 0 : _c.return(); // iterator must implement the return method | ||
const op = stream.ops[opId]; | ||
if (isAsyncGenerator(op)) | ||
op.return(undefined); | ||
delete stream.ops[opId]; // deleting the operation means no further activity should take place | ||
@@ -363,3 +363,3 @@ return res.writeHead(200).end(); | ||
} | ||
const opId = String((_e = (_d = params.extensions) === null || _d === void 0 ? void 0 : _d.operationId) !== null && _e !== void 0 ? _e : ''); | ||
const opId = String((_d = (_c = params.extensions) === null || _c === void 0 ? void 0 : _c.operationId) !== null && _d !== void 0 ? _d : ''); | ||
if (!opId) | ||
@@ -382,5 +382,4 @@ return res.writeHead(400, 'Operation ID is missing').end(); | ||
if (res.writableEnded) { | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
if (isAsyncIterable(result)) | ||
result.return(); // iterator must implement the return method | ||
if (isAsyncGenerator(result)) | ||
result.return(undefined); | ||
delete stream.ops[opId]; | ||
@@ -391,5 +390,4 @@ return; // `onOperation` responded | ||
if (!(opId in stream.ops)) { | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
if (isAsyncIterable(result)) | ||
result.return(); // iterator must implement the return method | ||
if (isAsyncGenerator(result)) | ||
result.return(undefined); | ||
return res.writeHead(204).end(); | ||
@@ -465,1 +463,11 @@ } | ||
} | ||
function isAsyncGenerator(val) { | ||
return (utils_1.isObject(val) && | ||
typeof Object(val)[Symbol.asyncIterator] === 'function' && | ||
typeof val.return === 'function' | ||
// for lazy ones, we only need the return anyway | ||
// typeof val.throw === 'function' && | ||
// typeof val.next === 'function' | ||
); | ||
} | ||
exports.isAsyncGenerator = isAsyncGenerator; |
{ | ||
"name": "graphql-sse", | ||
"version": "1.0.3", | ||
"version": "1.0.4", | ||
"description": "Zero-dependency, HTTP/1 safe, simple, GraphQL over Server-Sent Events Protocol server and client", | ||
@@ -89,3 +89,3 @@ "keywords": [ | ||
"eventsource": "^1.1.0", | ||
"graphql": "^16.0.0-rc.1", | ||
"graphql": "16.0.0-rc.2.experimental-stream-defer.3", | ||
"jest": "^27.0.6", | ||
@@ -101,4 +101,4 @@ "node-fetch": "^2.6.1", | ||
"typedoc-plugin-markdown": "^3.10.4", | ||
"typescript": "^4.3.5" | ||
"typescript": "4.3.5" | ||
} | ||
} |
@@ -18,3 +18,3 @@ <div align="center"> | ||
```shell | ||
$ yarn add graphql-sse | ||
yarn add graphql-sse | ||
``` | ||
@@ -266,3 +266,3 @@ | ||
function subscribe<T>(payload: SubscribePayload): AsyncIterableIterator<T> { | ||
function subscribe<T>(payload: SubscribePayload): AsyncGenerator<T> { | ||
let deferred: { | ||
@@ -303,2 +303,5 @@ resolve: (done: boolean) => void; | ||
}, | ||
async throw(err) { | ||
throw err; | ||
}, | ||
async return() { | ||
@@ -305,0 +308,0 @@ dispose(); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
204683
3619
829