You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
8.1 KiB
186 lines
8.1 KiB
5 months ago
|
"use strict";
|
||
|
/**
|
||
|
*
|
||
|
* common
|
||
|
*
|
||
|
*/
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
exports.stringifyMessage = exports.parseMessage = exports.isMessage = exports.validateMessage = exports.MessageType = exports.CloseCode = exports.DEPRECATED_GRAPHQL_WS_PROTOCOL = exports.GRAPHQL_TRANSPORT_WS_PROTOCOL = void 0;
|
||
|
const utils_1 = require("./utils");
|
||
|
/**
|
||
|
* The WebSocket sub-protocol used for the [GraphQL over WebSocket Protocol](https://github.com/graphql/graphql-over-http/blob/main/rfcs/GraphQLOverWebSocket.md).
|
||
|
*
|
||
|
* @category Common
|
||
|
*/
|
||
|
exports.GRAPHQL_TRANSPORT_WS_PROTOCOL = 'graphql-transport-ws';
|
||
|
/**
|
||
|
* The deprecated subprotocol used by [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws).
|
||
|
*
|
||
|
* @private
|
||
|
*/
|
||
|
exports.DEPRECATED_GRAPHQL_WS_PROTOCOL = 'graphql-ws';
|
||
|
/**
|
||
|
* `graphql-ws` expected and standard close codes of the [GraphQL over WebSocket Protocol](https://github.com/graphql/graphql-over-http/blob/main/rfcs/GraphQLOverWebSocket.md).
|
||
|
*
|
||
|
* @category Common
|
||
|
*/
|
||
|
var CloseCode;
|
||
|
(function (CloseCode) {
|
||
|
CloseCode[CloseCode["InternalServerError"] = 4500] = "InternalServerError";
|
||
|
CloseCode[CloseCode["InternalClientError"] = 4005] = "InternalClientError";
|
||
|
CloseCode[CloseCode["BadRequest"] = 4400] = "BadRequest";
|
||
|
CloseCode[CloseCode["BadResponse"] = 4004] = "BadResponse";
|
||
|
/** Tried subscribing before connect ack */
|
||
|
CloseCode[CloseCode["Unauthorized"] = 4401] = "Unauthorized";
|
||
|
CloseCode[CloseCode["Forbidden"] = 4403] = "Forbidden";
|
||
|
CloseCode[CloseCode["SubprotocolNotAcceptable"] = 4406] = "SubprotocolNotAcceptable";
|
||
|
CloseCode[CloseCode["ConnectionInitialisationTimeout"] = 4408] = "ConnectionInitialisationTimeout";
|
||
|
CloseCode[CloseCode["ConnectionAcknowledgementTimeout"] = 4504] = "ConnectionAcknowledgementTimeout";
|
||
|
/** Subscriber distinction is very important */
|
||
|
CloseCode[CloseCode["SubscriberAlreadyExists"] = 4409] = "SubscriberAlreadyExists";
|
||
|
CloseCode[CloseCode["TooManyInitialisationRequests"] = 4429] = "TooManyInitialisationRequests";
|
||
|
})(CloseCode || (exports.CloseCode = CloseCode = {}));
|
||
|
/**
|
||
|
* Types of messages allowed to be sent by the client/server over the WS protocol.
|
||
|
*
|
||
|
* @category Common
|
||
|
*/
|
||
|
var MessageType;
|
||
|
(function (MessageType) {
|
||
|
MessageType["ConnectionInit"] = "connection_init";
|
||
|
MessageType["ConnectionAck"] = "connection_ack";
|
||
|
MessageType["Ping"] = "ping";
|
||
|
MessageType["Pong"] = "pong";
|
||
|
MessageType["Subscribe"] = "subscribe";
|
||
|
MessageType["Next"] = "next";
|
||
|
MessageType["Error"] = "error";
|
||
|
MessageType["Complete"] = "complete";
|
||
|
})(MessageType || (exports.MessageType = MessageType = {}));
|
||
|
/**
|
||
|
* Validates the message against the GraphQL over WebSocket Protocol.
|
||
|
*
|
||
|
* Invalid messages will throw descriptive errors.
|
||
|
*
|
||
|
* @category Common
|
||
|
*/
|
||
|
function validateMessage(val) {
|
||
|
if (!(0, utils_1.isObject)(val)) {
|
||
|
throw new Error(`Message is expected to be an object, but got ${(0, utils_1.extendedTypeof)(val)}`);
|
||
|
}
|
||
|
if (!val.type) {
|
||
|
throw new Error(`Message is missing the 'type' property`);
|
||
|
}
|
||
|
if (typeof val.type !== 'string') {
|
||
|
throw new Error(`Message is expects the 'type' property to be a string, but got ${(0, utils_1.extendedTypeof)(val.type)}`);
|
||
|
}
|
||
|
switch (val.type) {
|
||
|
case MessageType.ConnectionInit:
|
||
|
case MessageType.ConnectionAck:
|
||
|
case MessageType.Ping:
|
||
|
case MessageType.Pong: {
|
||
|
if (val.payload != null && !(0, utils_1.isObject)(val.payload)) {
|
||
|
throw new Error(`"${val.type}" message expects the 'payload' property to be an object or nullish or missing, but got "${val.payload}"`);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case MessageType.Subscribe: {
|
||
|
if (typeof val.id !== 'string') {
|
||
|
throw new Error(`"${val.type}" message expects the 'id' property to be a string, but got ${(0, utils_1.extendedTypeof)(val.id)}`);
|
||
|
}
|
||
|
if (!val.id) {
|
||
|
throw new Error(`"${val.type}" message requires a non-empty 'id' property`);
|
||
|
}
|
||
|
if (!(0, utils_1.isObject)(val.payload)) {
|
||
|
throw new Error(`"${val.type}" message expects the 'payload' property to be an object, but got ${(0, utils_1.extendedTypeof)(val.payload)}`);
|
||
|
}
|
||
|
if (typeof val.payload.query !== 'string') {
|
||
|
throw new Error(`"${val.type}" message payload expects the 'query' property to be a string, but got ${(0, utils_1.extendedTypeof)(val.payload.query)}`);
|
||
|
}
|
||
|
if (val.payload.variables != null && !(0, utils_1.isObject)(val.payload.variables)) {
|
||
|
throw new Error(`"${val.type}" message payload expects the 'variables' property to be a an object or nullish or missing, but got ${(0, utils_1.extendedTypeof)(val.payload.variables)}`);
|
||
|
}
|
||
|
if (val.payload.operationName != null &&
|
||
|
(0, utils_1.extendedTypeof)(val.payload.operationName) !== 'string') {
|
||
|
throw new Error(`"${val.type}" message payload expects the 'operationName' property to be a string or nullish or missing, but got ${(0, utils_1.extendedTypeof)(val.payload.operationName)}`);
|
||
|
}
|
||
|
if (val.payload.extensions != null && !(0, utils_1.isObject)(val.payload.extensions)) {
|
||
|
throw new Error(`"${val.type}" message payload expects the 'extensions' property to be a an object or nullish or missing, but got ${(0, utils_1.extendedTypeof)(val.payload.extensions)}`);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case MessageType.Next: {
|
||
|
if (typeof val.id !== 'string') {
|
||
|
throw new Error(`"${val.type}" message expects the 'id' property to be a string, but got ${(0, utils_1.extendedTypeof)(val.id)}`);
|
||
|
}
|
||
|
if (!val.id) {
|
||
|
throw new Error(`"${val.type}" message requires a non-empty 'id' property`);
|
||
|
}
|
||
|
if (!(0, utils_1.isObject)(val.payload)) {
|
||
|
throw new Error(`"${val.type}" message expects the 'payload' property to be an object, but got ${(0, utils_1.extendedTypeof)(val.payload)}`);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case MessageType.Error: {
|
||
|
if (typeof val.id !== 'string') {
|
||
|
throw new Error(`"${val.type}" message expects the 'id' property to be a string, but got ${(0, utils_1.extendedTypeof)(val.id)}`);
|
||
|
}
|
||
|
if (!val.id) {
|
||
|
throw new Error(`"${val.type}" message requires a non-empty 'id' property`);
|
||
|
}
|
||
|
if (!(0, utils_1.areGraphQLErrors)(val.payload)) {
|
||
|
throw new Error(`"${val.type}" message expects the 'payload' property to be an array of GraphQL errors, but got ${JSON.stringify(val.payload)}`);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case MessageType.Complete: {
|
||
|
if (typeof val.id !== 'string') {
|
||
|
throw new Error(`"${val.type}" message expects the 'id' property to be a string, but got ${(0, utils_1.extendedTypeof)(val.id)}`);
|
||
|
}
|
||
|
if (!val.id) {
|
||
|
throw new Error(`"${val.type}" message requires a non-empty 'id' property`);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
throw new Error(`Invalid message 'type' property "${val.type}"`);
|
||
|
}
|
||
|
return val;
|
||
|
}
|
||
|
exports.validateMessage = validateMessage;
|
||
|
/**
|
||
|
* Checks if the provided value is a valid GraphQL over WebSocket message.
|
||
|
*
|
||
|
* @deprecated Use `validateMessage` instead.
|
||
|
*
|
||
|
* @category Common
|
||
|
*/
|
||
|
function isMessage(val) {
|
||
|
try {
|
||
|
validateMessage(val);
|
||
|
return true;
|
||
|
}
|
||
|
catch (_a) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
exports.isMessage = isMessage;
|
||
|
/**
|
||
|
* Parses the raw websocket message data to a valid message.
|
||
|
*
|
||
|
* @category Common
|
||
|
*/
|
||
|
function parseMessage(data, reviver) {
|
||
|
return validateMessage(typeof data === 'string' ? JSON.parse(data, reviver) : data);
|
||
|
}
|
||
|
exports.parseMessage = parseMessage;
|
||
|
/**
|
||
|
* Stringifies a valid message ready to be sent through the socket.
|
||
|
*
|
||
|
* @category Common
|
||
|
*/
|
||
|
function stringifyMessage(msg, replacer) {
|
||
|
validateMessage(msg);
|
||
|
return JSON.stringify(msg, replacer);
|
||
|
}
|
||
|
exports.stringifyMessage = stringifyMessage;
|