aws-appsync-subscription-link
Advanced tools
Comparing version 3.0.11 to 3.1.0
@@ -5,2 +5,5 @@ import { AUTH_TYPE } from "aws-appsync-auth-link"; | ||
import { AppSyncRealTimeSubscriptionHandshakeLink } from '../../src/realtime-subscription-handshake-link'; | ||
import { MESSAGE_TYPES } from "../../src/types"; | ||
import { v4 as uuid } from "uuid"; | ||
jest.mock('uuid', () => ({ v4: jest.fn() })); | ||
@@ -10,3 +13,3 @@ const query = gql`subscription { someSubscription { aField } }` | ||
class myWebSocket implements WebSocket { | ||
binaryType: BinaryType; | ||
binaryType: BinaryType; | ||
bufferedAmount: number; | ||
@@ -364,4 +367,162 @@ extensions: string; | ||
}); | ||
}) | ||
}); | ||
test("Can use a custom keepAliveTimeoutMs", (done) => { | ||
const id = "abcd-efgh-ijkl-mnop"; | ||
uuid.mockImplementationOnce(() => id); | ||
expect.assertions(5); | ||
jest.spyOn(Date.prototype, 'toISOString').mockImplementation(jest.fn(() => { | ||
return "2019-11-13T18:47:04.733Z"; | ||
})); | ||
AppSyncRealTimeSubscriptionHandshakeLink.createWebSocket = jest.fn((url, protocol) => { | ||
expect(url).toBe('wss://apikeytest.testcustomdomain.com/graphql/realtime?header=eyJob3N0IjoiYXBpa2V5dGVzdC50ZXN0Y3VzdG9tZG9tYWluLmNvbSIsIngtYW16LWRhdGUiOiIyMDE5MTExM1QxODQ3MDRaIiwieC1hcGkta2V5IjoieHh4eHgifQ==&payload=e30='); | ||
expect(protocol).toBe('graphql-ws'); | ||
const socket = new myWebSocket(); | ||
setTimeout(() => { | ||
socket.close = () => {}; | ||
socket.onopen.call(socket, (undefined as unknown as Event)); | ||
socket.send = (msg: string) => { | ||
const { type } = JSON.parse(msg); | ||
switch (type) { | ||
case MESSAGE_TYPES.GQL_CONNECTION_INIT: | ||
socket.onmessage.call(socket, { | ||
data: JSON.stringify({ | ||
type: MESSAGE_TYPES.GQL_CONNECTION_ACK, | ||
payload: { | ||
connectionTimeoutMs: 99999, | ||
}, | ||
}) | ||
} as MessageEvent); | ||
setTimeout(() => { | ||
socket.onmessage.call(socket, { | ||
data: JSON.stringify({ | ||
id, | ||
type: MESSAGE_TYPES.GQL_DATA, | ||
payload: { | ||
data: { something: 123 }, | ||
}, | ||
}) | ||
} as MessageEvent); | ||
}, 100); | ||
break; | ||
} | ||
}; | ||
}, 100); | ||
return socket; | ||
}); | ||
const link = new AppSyncRealTimeSubscriptionHandshakeLink({ | ||
auth: { | ||
type: AUTH_TYPE.API_KEY, | ||
apiKey: 'xxxxx' | ||
}, | ||
region: 'us-west-2', | ||
url: 'https://apikeytest.testcustomdomain.com/graphql', | ||
keepAliveTimeoutMs: 123456, | ||
}); | ||
expect(link).toBeInstanceOf(AppSyncRealTimeSubscriptionHandshakeLink); | ||
expect((link as any).keepAliveTimeout).toBe(123456); | ||
const sub = execute(link, { query }).subscribe({ | ||
error: (err) => { | ||
console.log(JSON.stringify(err)); | ||
fail(); | ||
}, | ||
next: (data) => { | ||
expect((link as any).keepAliveTimeout).toBe(123456); | ||
done(); | ||
sub.unsubscribe(); | ||
}, | ||
complete: () => { | ||
console.log('done with this'); | ||
fail(); | ||
} | ||
}); | ||
}); | ||
test("Uses service-provided timeout when no custom keepAliveTimeoutMs is configured", (done) => { | ||
const id = "abcd-efgh-ijkl-mnop"; | ||
uuid.mockImplementationOnce(() => id); | ||
expect.assertions(5); | ||
jest.spyOn(Date.prototype, 'toISOString').mockImplementation(jest.fn(() => { | ||
return "2019-11-13T18:47:04.733Z"; | ||
})); | ||
AppSyncRealTimeSubscriptionHandshakeLink.createWebSocket = jest.fn((url, protocol) => { | ||
expect(url).toBe('wss://apikeytest.testcustomdomain.com/graphql/realtime?header=eyJob3N0IjoiYXBpa2V5dGVzdC50ZXN0Y3VzdG9tZG9tYWluLmNvbSIsIngtYW16LWRhdGUiOiIyMDE5MTExM1QxODQ3MDRaIiwieC1hcGkta2V5IjoieHh4eHgifQ==&payload=e30='); | ||
expect(protocol).toBe('graphql-ws'); | ||
const socket = new myWebSocket(); | ||
setTimeout(() => { | ||
socket.close = () => {}; | ||
socket.onopen.call(socket, (undefined as unknown as Event)); | ||
socket.send = (msg: string) => { | ||
const { type } = JSON.parse(msg); | ||
switch (type) { | ||
case MESSAGE_TYPES.GQL_CONNECTION_INIT: | ||
socket.onmessage.call(socket, { | ||
data: JSON.stringify({ | ||
type: MESSAGE_TYPES.GQL_CONNECTION_ACK, | ||
payload: { | ||
connectionTimeoutMs: 99999, | ||
}, | ||
}) | ||
} as MessageEvent); | ||
setTimeout(() => { | ||
socket.onmessage.call(socket, { | ||
data: JSON.stringify({ | ||
id, | ||
type: MESSAGE_TYPES.GQL_DATA, | ||
payload: { | ||
data: { something: 123 }, | ||
}, | ||
}) | ||
} as MessageEvent); | ||
}, 100); | ||
break; | ||
} | ||
}; | ||
}, 100); | ||
return socket; | ||
}); | ||
const link = new AppSyncRealTimeSubscriptionHandshakeLink({ | ||
auth: { | ||
type: AUTH_TYPE.API_KEY, | ||
apiKey: 'xxxxx' | ||
}, | ||
region: 'us-west-2', | ||
url: 'https://apikeytest.testcustomdomain.com/graphql', | ||
}); | ||
expect(link).toBeInstanceOf(AppSyncRealTimeSubscriptionHandshakeLink); | ||
expect((link as any).keepAliveTimeout).toBeUndefined(); | ||
const sub = execute(link, { query }).subscribe({ | ||
error: (err) => { | ||
console.log(JSON.stringify(err)); | ||
fail(); | ||
}, | ||
next: (data) => { | ||
expect((link as any).keepAliveTimeout).toBe(99999); | ||
done(); | ||
sub.unsubscribe(); | ||
}, | ||
complete: () => { | ||
console.log('done with this'); | ||
fail(); | ||
} | ||
}); | ||
}); | ||
}); |
@@ -6,2 +6,13 @@ # Change Log | ||
<a name="3.1.0"></a> | ||
# [3.1.0](https://github.com/awslabs/aws-mobile-appsync-sdk-js/compare/aws-appsync-subscription-link@3.0.11...aws-appsync-subscription-link@3.1.0) (2022-06-24) | ||
### Features | ||
* Add keepAliveTimeoutMs config for AppSync WebSocket link ([#724](https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/724)) ([74b8351](https://github.com/awslabs/aws-mobile-appsync-sdk-js/commit/74b8351)) | ||
<a name="3.0.11"></a> | ||
@@ -8,0 +19,0 @@ ## [3.0.11](https://github.com/awslabs/aws-mobile-appsync-sdk-js/compare/aws-appsync-subscription-link@3.0.10...aws-appsync-subscription-link@3.0.11) (2022-05-02) |
import { CONTROL_EVENTS_KEY } from "./subscription-handshake-link"; | ||
import { ApolloLink } from "@apollo/client/core"; | ||
import { UrlInfo } from "./types"; | ||
declare function createSubscriptionHandshakeLink(args: UrlInfo, resultsFetcherLink?: ApolloLink): ApolloLink; | ||
import { AppSyncRealTimeSubscriptionConfig } from "./types"; | ||
declare function createSubscriptionHandshakeLink(args: AppSyncRealTimeSubscriptionConfig, resultsFetcherLink?: ApolloLink): ApolloLink; | ||
declare function createSubscriptionHandshakeLink(url: string, resultsFetcherLink?: ApolloLink): ApolloLink; | ||
export { CONTROL_EVENTS_KEY, createSubscriptionHandshakeLink }; |
@@ -6,3 +6,3 @@ /*! | ||
import { ApolloLink, Observable, Operation, FetchResult } from "@apollo/client/core"; | ||
import { UrlInfo } from "./types"; | ||
import { AppSyncRealTimeSubscriptionConfig } from "./types"; | ||
export declare const CONTROL_EVENTS_KEY = "@@controlEvents"; | ||
@@ -16,6 +16,6 @@ export declare class AppSyncRealTimeSubscriptionHandshakeLink extends ApolloLink { | ||
private keepAliveTimeoutId; | ||
private keepAliveTimeout; | ||
private keepAliveTimeout?; | ||
private subscriptionObserverMap; | ||
private promiseArray; | ||
constructor({ url: theUrl, region: theRegion, auth: theAuth }: UrlInfo); | ||
constructor({ url: theUrl, region: theRegion, auth: theAuth, keepAliveTimeoutMs }: AppSyncRealTimeSubscriptionConfig); | ||
private isCustomDomain; | ||
@@ -22,0 +22,0 @@ request(operation: Operation): Observable<FetchResult<Record<string, any>, Record<string, any>, Record<string, any>>>; |
@@ -93,2 +93,6 @@ "use strict"; | ||
/** | ||
* Frequency in milliseconds in which the server sends GQL_CONNECTION_KEEP_ALIVE messages | ||
*/ | ||
var SERVER_KEEP_ALIVE_TIMEOUT = 1 * 60 * 1000; | ||
/** | ||
* Default Time in milliseconds to wait for GQL_CONNECTION_KEEP_ALIVE message | ||
@@ -102,6 +106,6 @@ */ | ||
function AppSyncRealTimeSubscriptionHandshakeLink(_a) { | ||
var theUrl = _a.url, theRegion = _a.region, theAuth = _a.auth; | ||
var theUrl = _a.url, theRegion = _a.region, theAuth = _a.auth, keepAliveTimeoutMs = _a.keepAliveTimeoutMs; | ||
var _this = _super.call(this) || this; | ||
_this.socketStatus = types_1.SOCKET_STATUS.CLOSED; | ||
_this.keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT; | ||
_this.keepAliveTimeout = undefined; | ||
_this.subscriptionObserverMap = new Map(); | ||
@@ -112,2 +116,7 @@ _this.promiseArray = []; | ||
_this.auth = theAuth; | ||
_this.keepAliveTimeout = keepAliveTimeoutMs; | ||
if (_this.keepAliveTimeout < SERVER_KEEP_ALIVE_TIMEOUT) { | ||
var configName = 'keepAliveTimeoutMs'; | ||
throw new Error(configName + " must be greater than or equal to " + SERVER_KEEP_ALIVE_TIMEOUT + " (" + _this.keepAliveTimeout + " used)."); | ||
} | ||
return _this; | ||
@@ -612,8 +621,9 @@ } | ||
_this.awsRealTimeSocket.onmessage = function (message) { | ||
var _a; | ||
logger("subscription message from AWS AppSyncRealTime: " + message.data + " "); | ||
var data = JSON.parse(message.data); | ||
var type = data.type, _a = data.payload, _b = (_a === void 0 ? {} : _a).connectionTimeoutMs, connectionTimeoutMs = _b === void 0 ? DEFAULT_KEEP_ALIVE_TIMEOUT : _b; | ||
var type = data.type, _b = data.payload, _c = (_b === void 0 ? {} : _b).connectionTimeoutMs, connectionTimeoutMs = _c === void 0 ? DEFAULT_KEEP_ALIVE_TIMEOUT : _c; | ||
if (type === types_1.MESSAGE_TYPES.GQL_CONNECTION_ACK) { | ||
ackOk = true; | ||
_this.keepAliveTimeout = connectionTimeoutMs; | ||
_this.keepAliveTimeout = (_a = _this.keepAliveTimeout) !== null && _a !== void 0 ? _a : connectionTimeoutMs; | ||
_this.awsRealTimeSocket.onmessage = _this._handleIncomingSubscriptionMessage.bind(_this); | ||
@@ -632,3 +642,3 @@ _this.awsRealTimeSocket.onerror = function (err) { | ||
if (type === types_1.MESSAGE_TYPES.GQL_CONNECTION_ERROR) { | ||
var _c = data.payload, _d = (_c === void 0 ? {} : _c).errors, _e = (_d === void 0 ? [] : _d)[0], _f = _e === void 0 ? {} : _e, _g = _f.errorType, errorType = _g === void 0 ? "" : _g, _h = _f.errorCode, errorCode = _h === void 0 ? 0 : _h; | ||
var _d = data.payload, _e = (_d === void 0 ? {} : _d).errors, _f = (_e === void 0 ? [] : _e)[0], _g = _f === void 0 ? {} : _f, _h = _g.errorType, errorType = _h === void 0 ? "" : _h, _j = _g.errorCode, errorCode = _j === void 0 ? 0 : _j; | ||
rej({ errorType: errorType, errorCode: errorCode }); | ||
@@ -635,0 +645,0 @@ } |
@@ -74,2 +74,5 @@ import { AuthOptions } from "aws-appsync-auth-link"; | ||
}; | ||
export declare type AppSyncRealTimeSubscriptionConfig = UrlInfo & { | ||
keepAliveTimeoutMs?: number; | ||
}; | ||
export declare type ObserverQuery = { | ||
@@ -76,0 +79,0 @@ observer: ZenObservable.SubscriptionObserver<any>; |
{ | ||
"name": "aws-appsync-subscription-link", | ||
"version": "3.0.11", | ||
"version": "3.1.0", | ||
"main": "lib/index.js", | ||
@@ -5,0 +5,0 @@ "license": "Apache-2.0", |
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
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
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
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
294664
6472