Comparing version 1.0.0-rc.2 to 1.0.0-rc.3
@@ -44,2 +44,4 @@ import Ajv from 'ajv'; | ||
incomingJSONSchemas: Map<string, ValidateFunction<MessageType>>; | ||
/** Map of JSONSchemas by incoming requestId */ | ||
incomingJSONSchemasByRequestId: Map<string, ValidateFunction<MessageType>>; | ||
/** Map of JSONSchemas by outgoing message type */ | ||
@@ -97,3 +99,3 @@ outgoingJSONSchemas: Map<string, ValidateFunction<MessageType>>; | ||
*/ | ||
protected abstract getMessageObject(type: string, payload?: any, requestId?: string): MessageType; | ||
abstract getMessageObject(type: string, payload?: any, requestId?: string): MessageType; | ||
/** | ||
@@ -105,5 +107,8 @@ * Build and serialize message out of its parts. | ||
* @param {string} requestId requestId meta data | ||
* @param {SchemaObject} jsonSchema JSONSchema object to validate message. | ||
* If not set, tries to get a JSONSchema for this message type from assigned by | ||
* validation.outgoing.AddJSONSchema() | ||
* @returns {string} Serialized message ready to be sent | ||
*/ | ||
protected buildMessage(type: string, payload?: any, requestId?: string): string; | ||
protected buildMessage(type: string, payload?: any, requestId?: string, jsonSchema?: SchemaObject): string; | ||
/** | ||
@@ -120,4 +125,5 @@ * Send message to server | ||
* @param {*} payload Message payload | ||
* @param {SchemaObject} jsonSchema JSONSchema object to validate message before sending | ||
*/ | ||
sendMessage<PayloadType = any>(type: string, payload?: PayloadType): void; | ||
sendMessage<PayloadType = any>(type: string, payload?: PayloadType, jsonSchema?: SchemaObject): void; | ||
/** | ||
@@ -134,2 +140,6 @@ * Send message to server and asynchronously wait for the response. | ||
* @param {string} waitForType Message type in the response waiting for (not recommended) | ||
@param {SchemaObject} requestJSONSchema JSONSchema object to validate request message | ||
before sending | ||
@param {SchemaObject} responseJSONSchema JSONSchema object to validate response message | ||
after receiving | ||
* @returns {Promise<{payload, message}>} Object with payload and raw message string | ||
@@ -156,3 +166,3 @@ * | ||
*/ | ||
sendRequest<RequestPayloadType = any, ResponsePayloadType = any>(type: string, payload?: RequestPayloadType, waitForType?: string): Promise<{ | ||
sendRequest<RequestPayloadType = any, ResponsePayloadType = any>(type: string, payload?: RequestPayloadType, waitForType?: string, requestJSONSchema?: SchemaObject, responseJSONSchema?: SchemaObject): Promise<{ | ||
payload: ResponsePayloadType; | ||
@@ -184,4 +194,5 @@ message: string; | ||
* @param {OnMessageCallback} callback Handler callback | ||
* @param {SchemaObject} jsonSchema JSONSchema object to validate message after receiving | ||
*/ | ||
onMessage<PayloadType = any>(type: string, callback: OnMessageCallback<PayloadType>): void; | ||
onMessage<PayloadType = any>(type: string, callback: OnMessageCallback<PayloadType>, jsonSchema?: SchemaObject): void; | ||
/** | ||
@@ -188,0 +199,0 @@ * Remove handler for the message type |
@@ -182,2 +182,3 @@ "use strict"; | ||
this.incomingJSONSchemas = new Map(); | ||
this.incomingJSONSchemasByRequestId = new Map(); | ||
this.outgoingJSONSchemas = new Map(); | ||
@@ -191,5 +192,8 @@ } | ||
* @param {string} requestId requestId meta data | ||
* @param {SchemaObject} jsonSchema JSONSchema object to validate message. | ||
* If not set, tries to get a JSONSchema for this message type from assigned by | ||
* validation.outgoing.AddJSONSchema() | ||
* @returns {string} Serialized message ready to be sent | ||
*/ | ||
WaitSocket.prototype.buildMessage = function (type, payload, requestId) { | ||
WaitSocket.prototype.buildMessage = function (type, payload, requestId, jsonSchema) { | ||
var messageObject = this.getMessageObject(type, payload, requestId); | ||
@@ -199,3 +203,9 @@ this.outgoingInterceptors.forEach(function (interceptor) { | ||
}); | ||
var validateFunction = this.outgoingJSONSchemas.get(type); | ||
if (this.validateCommonObject) { | ||
// TODO: Tests on this | ||
this.validate(messageObject, this.validateCommonObject); | ||
} | ||
var validateFunction = jsonSchema | ||
? this.ajv.compile(jsonSchema) | ||
: this.outgoingJSONSchemas.get(type); | ||
this.validate(messageObject, validateFunction); | ||
@@ -217,5 +227,6 @@ return JSON.stringify(messageObject); | ||
* @param {*} payload Message payload | ||
* @param {SchemaObject} jsonSchema JSONSchema object to validate message before sending | ||
*/ | ||
WaitSocket.prototype.sendMessage = function (type, payload) { | ||
var message = this.buildMessage(type, payload); | ||
WaitSocket.prototype.sendMessage = function (type, payload, jsonSchema) { | ||
var message = this.buildMessage(type, payload, undefined, jsonSchema); | ||
this.send(message); | ||
@@ -234,2 +245,6 @@ }; | ||
* @param {string} waitForType Message type in the response waiting for (not recommended) | ||
@param {SchemaObject} requestJSONSchema JSONSchema object to validate request message | ||
before sending | ||
@param {SchemaObject} responseJSONSchema JSONSchema object to validate response message | ||
after receiving | ||
* @returns {Promise<{payload, message}>} Object with payload and raw message string | ||
@@ -256,3 +271,3 @@ * | ||
*/ | ||
WaitSocket.prototype.sendRequest = function (type, payload, waitForType) { | ||
WaitSocket.prototype.sendRequest = function (type, payload, waitForType, requestJSONSchema, responseJSONSchema) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -263,2 +278,5 @@ var _this = this; | ||
if (waitForType) { | ||
if (responseJSONSchema) { | ||
_this.validation.incoming.addJSONSchema(type, responseJSONSchema); | ||
} | ||
var timeoutId_1 = setTimeout(function () { | ||
@@ -274,3 +292,3 @@ _this.responseCallbacksByType.delete(waitForType); | ||
// TODO: Custom error | ||
reject(error); | ||
reject(new Error(error)); | ||
} | ||
@@ -281,3 +299,3 @@ else { | ||
}; | ||
var message = _this.buildMessage(type, payload); | ||
var message = _this.buildMessage(type, payload, undefined, requestJSONSchema); | ||
_this.responseCallbacksByType.set(waitForType, callback); | ||
@@ -288,4 +306,8 @@ _this.send(message); | ||
var requestId_1 = nanoid_1.nanoid(); | ||
if (responseJSONSchema) { | ||
_this.incomingJSONSchemasByRequestId.set(requestId_1, _this.ajv.compile(responseJSONSchema)); | ||
} | ||
var timeoutId_2 = setTimeout(function () { | ||
_this.responseCallbacksByRequestId.delete(requestId_1); | ||
_this.incomingJSONSchemasByRequestId.delete(requestId_1); | ||
// TODO: Custom error | ||
@@ -297,5 +319,6 @@ reject(new Error("Timeout while waiting for response for requestId=" + requestId_1)); | ||
_this.responseCallbacksByRequestId.delete(requestId_1); | ||
_this.incomingJSONSchemasByRequestId.delete(requestId_1); | ||
if (error) { | ||
// TODO: Custom error | ||
reject(error); | ||
reject(new Error(error)); | ||
} | ||
@@ -306,3 +329,3 @@ else { | ||
}; | ||
var message = _this.buildMessage(type, payload, requestId_1); | ||
var message = _this.buildMessage(type, payload, requestId_1, requestJSONSchema); | ||
_this.responseCallbacksByRequestId.set(requestId_1, callback); | ||
@@ -340,23 +363,43 @@ _this.send(message); | ||
WaitSocket.prototype.handleMessage = function (event) { | ||
var message = event.data; | ||
var messageObject = JSON.parse(message); | ||
this.incomingInterceptors.forEach(function (interceptor) { | ||
messageObject = interceptor(messageObject); | ||
}); | ||
var type = this.getType(messageObject); | ||
var validateFunction = this.incomingJSONSchemas.get(type); | ||
var error; | ||
var errors = []; | ||
var payload; | ||
var message; | ||
var type = ''; | ||
var requestId; | ||
try { | ||
this.validate(messageObject, validateFunction); | ||
message = event.data; | ||
var messageObject_1 = JSON.parse(message); | ||
try { | ||
this.validate(messageObject_1, this.validateCommonObject); | ||
} | ||
catch (err) { | ||
errors.push(err); | ||
} | ||
this.incomingInterceptors.forEach(function (interceptor) { | ||
messageObject_1 = interceptor(messageObject_1); | ||
}); | ||
type = this.getType(messageObject_1); | ||
try { | ||
this.validate(messageObject_1, this.incomingJSONSchemas.get(type)); | ||
} | ||
catch (err) { | ||
errors.push(err); | ||
} | ||
payload = this.getPayload(messageObject_1); | ||
requestId = this.getRequestId(messageObject_1); | ||
if (requestId) { | ||
this.validate(messageObject_1, this.incomingJSONSchemasByRequestId.get(requestId)); | ||
} | ||
} | ||
catch (err) { | ||
error = err; | ||
errors.push(err); | ||
} | ||
var payload = this.getPayload(messageObject); | ||
var requestId = this.getRequestId(messageObject); | ||
var requestHandler = requestId | ||
var responseHandler = requestId | ||
? this.responseCallbacksByRequestId.get(requestId) | ||
: this.responseCallbacksByType.get(type); | ||
if (requestHandler) { | ||
requestHandler(payload, message, error); | ||
var error = errors.length | ||
? errors.join('\n') | ||
: undefined; | ||
if (responseHandler) { | ||
responseHandler(payload, message, error); | ||
} | ||
@@ -397,4 +440,8 @@ else { | ||
* @param {OnMessageCallback} callback Handler callback | ||
* @param {SchemaObject} jsonSchema JSONSchema object to validate message after receiving | ||
*/ | ||
WaitSocket.prototype.onMessage = function (type, callback) { | ||
WaitSocket.prototype.onMessage = function (type, callback, jsonSchema) { | ||
if (jsonSchema) { | ||
this.validation.incoming.addJSONSchema(type, jsonSchema); | ||
} | ||
this.callbacksByType.set(type, callback); | ||
@@ -408,2 +455,3 @@ }; | ||
WaitSocket.prototype.offMessage = function (type) { | ||
this.validation.incoming.removeJSONSchema(type); | ||
this.callbacksByType.delete(type); | ||
@@ -410,0 +458,0 @@ }; |
import { Static } from '@sinclair/typebox'; | ||
import { SchemaObject } from 'ajv'; | ||
import AbstractWaitSocket from './AbstractWaitSocket'; | ||
@@ -18,2 +19,3 @@ export declare const DefaultMessageSchema: import("@sinclair/typebox").TObject<{ | ||
* or WebSocket endpoint URI string | ||
* @param {SchemaObject} jsonSchema JSONSchema object for common message (for any type) | ||
* | ||
@@ -27,3 +29,3 @@ * @example | ||
*/ | ||
constructor(ws: WebSocket | string); | ||
constructor(ws: WebSocket | string, jsonSchema?: SchemaObject); | ||
/** | ||
@@ -37,3 +39,3 @@ * Returns message object with type, payload and requestId in it. | ||
*/ | ||
protected getMessageObject(type: string, payload?: any, requestId?: string): import("@sinclair/typebox").StaticProperties<{ | ||
getMessageObject(type: string, payload?: any, requestId?: string): import("@sinclair/typebox").StaticProperties<{ | ||
type: import("@sinclair/typebox").TString; | ||
@@ -40,0 +42,0 @@ payload: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TAny>; |
@@ -37,2 +37,3 @@ "use strict"; | ||
* or WebSocket endpoint URI string | ||
* @param {SchemaObject} jsonSchema JSONSchema object for common message (for any type) | ||
* | ||
@@ -46,4 +47,5 @@ * @example | ||
*/ | ||
function WaitSocket(ws) { | ||
return _super.call(this, ws, typebox_1.Type.Strict(exports.DefaultMessageSchema)) || this; | ||
function WaitSocket(ws, jsonSchema) { | ||
if (jsonSchema === void 0) { jsonSchema = typebox_1.Type.Strict(exports.DefaultMessageSchema); } | ||
return _super.call(this, ws, jsonSchema) || this; | ||
} | ||
@@ -50,0 +52,0 @@ /** |
{ | ||
"name": "waitsocket", | ||
"version": "1.0.0-rc.2", | ||
"version": "1.0.0-rc.3", | ||
"description": "Library for better handling WebSocket interactions and waiting for response messages", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -64,2 +64,5 @@ import { nanoid } from 'nanoid'; | ||
/** Map of JSONSchemas by incoming requestId */ | ||
incomingJSONSchemasByRequestId: Map<string, ValidateFunction<MessageType>>; | ||
/** Map of JSONSchemas by outgoing message type */ | ||
@@ -100,2 +103,3 @@ outgoingJSONSchemas: Map<string, ValidateFunction<MessageType>>; | ||
this.incomingJSONSchemas = new Map(); | ||
this.incomingJSONSchemasByRequestId = new Map(); | ||
this.outgoingJSONSchemas = new Map(); | ||
@@ -141,3 +145,3 @@ } | ||
*/ | ||
protected abstract getMessageObject(type: string, payload?: any, requestId?: string): MessageType; | ||
public abstract getMessageObject(type: string, payload?: any, requestId?: string): MessageType; | ||
@@ -150,5 +154,13 @@ /** | ||
* @param {string} requestId requestId meta data | ||
* @param {SchemaObject} jsonSchema JSONSchema object to validate message. | ||
* If not set, tries to get a JSONSchema for this message type from assigned by | ||
* validation.outgoing.AddJSONSchema() | ||
* @returns {string} Serialized message ready to be sent | ||
*/ | ||
protected buildMessage(type: string, payload?: any, requestId?: string): string { | ||
protected buildMessage( | ||
type: string, | ||
payload?: any, | ||
requestId?: string, | ||
jsonSchema?: SchemaObject, | ||
): string { | ||
let messageObject = this.getMessageObject(type, payload, requestId); | ||
@@ -159,3 +171,9 @@ this.outgoingInterceptors.forEach((interceptor) => { | ||
const validateFunction = this.outgoingJSONSchemas.get(type); | ||
if (this.validateCommonObject) { | ||
// TODO: Tests on this | ||
this.validate(messageObject, this.validateCommonObject); | ||
} | ||
const validateFunction = jsonSchema | ||
? this.ajv.compile(jsonSchema) | ||
: this.outgoingJSONSchemas.get(type); | ||
this.validate(messageObject, validateFunction); | ||
@@ -179,5 +197,10 @@ return JSON.stringify(messageObject); | ||
* @param {*} payload Message payload | ||
* @param {SchemaObject} jsonSchema JSONSchema object to validate message before sending | ||
*/ | ||
public sendMessage<PayloadType = any>(type: string, payload?: PayloadType) { | ||
const message = this.buildMessage(type, payload); | ||
public sendMessage<PayloadType = any>( | ||
type: string, | ||
payload?: PayloadType, | ||
jsonSchema?: SchemaObject, | ||
) { | ||
const message = this.buildMessage(type, payload, undefined, jsonSchema); | ||
this.send(message); | ||
@@ -197,2 +220,6 @@ } | ||
* @param {string} waitForType Message type in the response waiting for (not recommended) | ||
@param {SchemaObject} requestJSONSchema JSONSchema object to validate request message | ||
before sending | ||
@param {SchemaObject} responseJSONSchema JSONSchema object to validate response message | ||
after receiving | ||
* @returns {Promise<{payload, message}>} Object with payload and raw message string | ||
@@ -223,5 +250,11 @@ * | ||
waitForType?: string, | ||
requestJSONSchema?: SchemaObject, | ||
responseJSONSchema?: SchemaObject, | ||
): Promise<{ payload: ResponsePayloadType, message: string }> { | ||
return new Promise((resolve, reject) => { | ||
if (waitForType) { | ||
if (responseJSONSchema) { | ||
this.validation.incoming.addJSONSchema(type, responseJSONSchema); | ||
} | ||
const timeoutId = setTimeout(() => { | ||
@@ -241,3 +274,3 @@ this.responseCallbacksByType.delete(waitForType); | ||
// TODO: Custom error | ||
reject(error); | ||
reject(new Error(error)); | ||
} else { | ||
@@ -248,3 +281,3 @@ resolve({ payload: responsePayload, message: responseMessage }); | ||
const message = this.buildMessage(type, payload); | ||
const message = this.buildMessage(type, payload, undefined, requestJSONSchema); | ||
this.responseCallbacksByType.set(waitForType, callback); | ||
@@ -254,4 +287,10 @@ this.send(message); | ||
const requestId = nanoid(); | ||
if (responseJSONSchema) { | ||
this.incomingJSONSchemasByRequestId.set(requestId, this.ajv.compile(responseJSONSchema)); | ||
} | ||
const timeoutId = setTimeout(() => { | ||
this.responseCallbacksByRequestId.delete(requestId); | ||
this.incomingJSONSchemasByRequestId.delete(requestId); | ||
// TODO: Custom error | ||
@@ -267,5 +306,6 @@ reject(new Error(`Timeout while waiting for response for requestId=${requestId}`)); | ||
this.responseCallbacksByRequestId.delete(requestId); | ||
this.incomingJSONSchemasByRequestId.delete(requestId); | ||
if (error) { | ||
// TODO: Custom error | ||
reject(error); | ||
reject(new Error(error)); | ||
} else { | ||
@@ -276,3 +316,3 @@ resolve({ payload: responsePayload, message: responseMessage }); | ||
const message = this.buildMessage(type, payload, requestId); | ||
const message = this.buildMessage(type, payload, requestId, requestJSONSchema); | ||
this.responseCallbacksByRequestId.set(requestId, callback); | ||
@@ -310,26 +350,45 @@ this.send(message); | ||
private handleMessage(event: MessageEvent) { | ||
const message = event.data; | ||
let messageObject = JSON.parse(message); | ||
this.incomingInterceptors.forEach((interceptor) => { | ||
messageObject = interceptor(messageObject); | ||
}); | ||
const errors = []; | ||
let payload; | ||
let message; | ||
let type = ''; | ||
let requestId; | ||
try { | ||
message = event.data; | ||
let messageObject = JSON.parse(message); | ||
try { | ||
this.validate(messageObject, this.validateCommonObject); | ||
} catch (err) { | ||
errors.push(err); | ||
} | ||
this.incomingInterceptors.forEach((interceptor) => { | ||
messageObject = interceptor(messageObject); | ||
}); | ||
const type = this.getType(messageObject); | ||
const validateFunction = this.incomingJSONSchemas.get(type); | ||
let error; | ||
try { | ||
this.validate(messageObject, validateFunction); | ||
type = this.getType(messageObject); | ||
try { | ||
this.validate(messageObject, this.incomingJSONSchemas.get(type)); | ||
} catch (err) { | ||
errors.push(err); | ||
} | ||
payload = this.getPayload(messageObject); | ||
requestId = this.getRequestId(messageObject); | ||
if (requestId) { | ||
this.validate(messageObject, this.incomingJSONSchemasByRequestId.get(requestId)); | ||
} | ||
} catch (err) { | ||
error = err; | ||
errors.push(err); | ||
} | ||
const payload = this.getPayload(messageObject); | ||
const requestId = this.getRequestId(messageObject); | ||
const requestHandler = requestId | ||
const responseHandler = requestId | ||
? this.responseCallbacksByRequestId.get(requestId) | ||
: this.responseCallbacksByType.get(type); | ||
if (requestHandler) { | ||
requestHandler(payload, message, error); | ||
const error = errors.length | ||
? errors.join('\n') | ||
: undefined; | ||
if (responseHandler) { | ||
responseHandler(payload, message, error); | ||
} else { | ||
@@ -360,4 +419,12 @@ const messageHandler = this.callbacksByType.get(type); | ||
* @param {OnMessageCallback} callback Handler callback | ||
* @param {SchemaObject} jsonSchema JSONSchema object to validate message after receiving | ||
*/ | ||
public onMessage<PayloadType = any>(type: string, callback: OnMessageCallback<PayloadType>) { | ||
public onMessage<PayloadType = any>( | ||
type: string, | ||
callback: OnMessageCallback<PayloadType>, | ||
jsonSchema?: SchemaObject, | ||
) { | ||
if (jsonSchema) { | ||
this.validation.incoming.addJSONSchema(type, jsonSchema); | ||
} | ||
this.callbacksByType.set(type, callback); | ||
@@ -372,2 +439,3 @@ } | ||
public offMessage(type: string) { | ||
this.validation.incoming.removeJSONSchema(type); | ||
this.callbacksByType.delete(type); | ||
@@ -374,0 +442,0 @@ } |
import { Type, Static } from '@sinclair/typebox'; | ||
import { SchemaObject } from 'ajv'; | ||
@@ -22,2 +23,3 @@ import AbstractWaitSocket from './AbstractWaitSocket'; | ||
* or WebSocket endpoint URI string | ||
* @param {SchemaObject} jsonSchema JSONSchema object for common message (for any type) | ||
* | ||
@@ -31,4 +33,7 @@ * @example | ||
*/ | ||
constructor(ws: WebSocket | string) { | ||
super(ws, Type.Strict(DefaultMessageSchema)); | ||
constructor( | ||
ws: WebSocket | string, | ||
jsonSchema: SchemaObject = Type.Strict(DefaultMessageSchema), | ||
) { | ||
super(ws, jsonSchema); | ||
} | ||
@@ -44,3 +49,3 @@ | ||
*/ | ||
protected getMessageObject(type: string, payload?: any, requestId?: string) { | ||
public getMessageObject(type: string, payload?: any, requestId?: string) { | ||
const result: DefaultMessageType = { type }; | ||
@@ -47,0 +52,0 @@ if (payload) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
76366
1477