diff --git a/Index.ts b/Index.ts index 2220961..4eded91 100644 --- a/Index.ts +++ b/Index.ts @@ -2,5 +2,4 @@ export * from './src/Backend'; export * from './src/Frontend'; export * from './src/Interfaces' export * from './src/Types'; -export * from './src/Utils' -export * from './src/Decorator' \ No newline at end of file +export * from './src/Utils' \ No newline at end of file diff --git a/src/Decorator.ts b/src/Decorator.ts deleted file mode 100644 index 3faaeff..0000000 --- a/src/Decorator.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { CLASSNAME_ATTRIBUTE } from "./Strings" - -export abstract class DeserializerFactory { - static entityClasses = {} - - static from(object: any) { - if(!object){ - return - } - - if(typeof object !== 'object'){ //definitely not a class object - return object - } - - if(Array.isArray(object)){ - return object.map(DeserializerFactory.from) - } - - const clazz = DeserializerFactory.entityClasses[object[CLASSNAME_ATTRIBUTE]] - delete object[CLASSNAME_ATTRIBUTE] - - if(!clazz){ //anonymous object or class not registered as @Serializable - Object.keys(object).forEach(key => { - object[key] = DeserializerFactory.from(object[key]) - }) - return object - } - - const obj = new clazz() - Object.keys(object).forEach(key => { - obj[key] = DeserializerFactory.from(object[key]) - }) - return obj - } - - - - static makeDeserializable(object: any){ - if(!object) - return - - if(typeof object !== 'object') - return object - - if(object.constructor.name === 'Object'){ - Object.keys(object).forEach(key => { - object[key] = DeserializerFactory.makeDeserializable(object[key]) - }) - return object - } - - object[CLASSNAME_ATTRIBUTE] = object.constructor.name - Object.keys(object).forEach(key => { - object[key] = DeserializerFactory.makeDeserializable(object[key]) - }) - - return object - } -} - -export function Serializable(attr?: any) { - return function _Serializable(clazz: T) { - DeserializerFactory.entityClasses[clazz.name] = clazz - - return clazz - } -} \ No newline at end of file diff --git a/src/Frontend.ts b/src/Frontend.ts index 77dfbfb..76a8946 100644 --- a/src/Frontend.ts +++ b/src/Frontend.ts @@ -5,8 +5,6 @@ import * as T from './Types'; import * as I from './Interfaces'; import { stripAfterEquals, appendComma } from './Utils'; import { CALLBACK_NAME, DESTROY_PREFIX, SOCKET_NOT_CONNECTED, UNKNOWN_RPC_IDENTIFIER, USER_DEFINED_TIMEOUT } from './Strings'; -import { DeserializerFactory } from './Decorator'; -DeserializerFactory /** @@ -209,10 +207,9 @@ export class RPCSocket implements I const headerArgs = fnArgs.join(",") const argParams = fnArgs.map(stripAfterEquals).join(",") sesame = appendComma(sesame) - const deserializer = DeserializerFactory return eval(`async (${headerArgs}) => { const returnvalue = await this.call("${fnName}", ${sesame} ${argParams}) - return deserializer.from(returnvalue) + return returnvalue }`) } @@ -230,7 +227,6 @@ export class RPCSocket implements I const argParams = fnArgs.map(stripAfterEquals).join(",") sesame = appendComma(sesame, true) headerArgs = fnArgs.length > 0 ? headerArgs + "," : headerArgs - const deserializer = DeserializerFactory const destroy_prefix = DESTROY_PREFIX const frontendHookStr = ` @@ -248,10 +244,10 @@ export class RPCSocket implements I }) this.socket.hook(r.uuid, (...args) => { - ${CALLBACK_NAME}.apply(${CALLBACK_NAME}, args.map(deserializer.from)) + ${CALLBACK_NAME}.apply(${CALLBACK_NAME}, args) }) } - return deserializer.from(r.return) + return r.return }else{ throw new Error("Empty response") } diff --git a/src/Utils.ts b/src/Utils.ts index 48c9581..35c7d24 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -4,7 +4,6 @@ import * as T from "./Types"; import * as I from "./Interfaces"; import { Socket } from "socket.io" import { CALL_NOT_FOUND, DESTROY_PREFIX, RPC_BAD_TYPE, RPC_NO_NAME } from "./Strings"; -import { DeserializerFactory } from "./Decorator"; /** * Translate an RPC to RPCInfo for serialization. @@ -80,12 +79,11 @@ const callGenerator = (rpcName: string, $__socket__$: I.Socket, rpcFunction: T.G const argsArr = extractArgs(rpcFunction) const args = argsArr.join(',') const argsStr = argsArr.map(stripAfterEquals).join(',') - const deserializer = DeserializerFactory const callStr = `async (${args}) => { try{ const res = await rpcFunction(${argsStr}) - return deserializer.makeDeserializable(res) + return res }catch(e){ errorHandler($__socket__$, e, rpcName, [${args}]) } @@ -108,7 +106,6 @@ export function stripAfterEquals(str: string): string { * @returns A {@link HookFunction} */ const hookGenerator = (rpc: T.HookRPC, errorHandler: T.ErrorHandler, sesameFn?: T.SesameFunction, injectSocket?: boolean): T.HookInfo['generator'] => { - const deserializer = DeserializerFactory let argsArr = extractArgs(rpc.hook) argsArr.shift()//remove callback param @@ -125,7 +122,6 @@ const hookGenerator = (rpc: T.HookRPC, errorHandler: T.ErrorHandler, s const uuid = uuidv4() const res = await rpc.hook((...cbargs) => { ${rpc.onCallback ? `rpc.onCallback.apply({}, cbargs)` : ``} - cbargs = cbargs.map(deserializer.makeDeserializable) $__socket__$.call.apply($__socket__$, [uuid, ...cbargs]) },${callArgs}) ${rpc.onDestroy ? `$__socket__$.bind(destroy_prefix+uuid, () => { diff --git a/test/Test.ts b/test/Test.ts index 3a5b042..f95e5ea 100644 --- a/test/Test.ts +++ b/test/Test.ts @@ -1,5 +1,4 @@ import { describe, it } from "mocha"; -import { RPCServer, RPCSocket, Serializable } from '../Index' import { RPCExporter, Socket } from "../src/Interfaces"; import { ConnectedSocket, Callback, GenericFunction } from "../src/Types"; import * as log from 'why-is-node-running'; @@ -10,6 +9,7 @@ import { PromiseIO } from "../src/PromiseIO/Server"; import { PromiseIOClient } from "../src/PromiseIO/Client"; import { assert, expect } from 'chai'; import { CLASSNAME_ATTRIBUTE, USER_DEFINED_TIMEOUT } from "../src/Strings"; +import { RPCServer, RPCSocket } from "../Index"; var should = require('chai').should(); var chai = require("chai"); var chaiAsPromised = require("chai-as-promised"); @@ -1010,126 +1010,4 @@ describe("attaching handlers before connecting", () => { done(e) }) }) -}) - -describe("class (de-)serialization", () => { - - @Serializable() - class SubClass { - fString = "F" - } - - @Serializable() - class TestClass { - aString = "A" - aNumber = 46 - aObject = { - x: "x", - y: undefined, - sub: new SubClass() - } - aClassObject = new SubClass() - - public returnOK() { - return "OK" - } - } - - const verifyObject = (obj: any) => { - expect(obj).to.be.an.instanceOf(TestClass) - expect(obj.aString).to.be.a('string') - expect(obj.aNumber).to.be.a('number') - expect(obj.aObject).to.be.a('object') - expect(obj.aObject.x).to.be.a('string') - expect(obj.aObject.y).to.be.undefined - expect(obj.aObject.sub).to.be.an.instanceOf(SubClass) - expect(obj.aClassObject).to.be.an.instanceOf(SubClass) - expect(obj).to.not.have.key(CLASSNAME_ATTRIBUTE) - expect(obj.aObject.sub).to.not.have.key(CLASSNAME_ATTRIBUTE) - expect(obj.aClassObject).to.not.have.key(CLASSNAME_ATTRIBUTE) - expect(obj.returnOK()).to.be.equal('OK') - } - - describe("Responses", () => { - type TestIfc = { - Test: { - returnClass: () => Promise - classCallback: (callback: Callback<[TestClass]>) => Promise - } - } - - let myServer: RPCServer; - let mySocket: ConnectedSocket; - - before(function (done) { - myServer = new RPCServer([{ - name: "Test", - RPCs: [ - async function returnClass() { - return new TestClass() - }, { - name: "classCallback", - hook: async function (callback) { - setTimeout(_ => callback(new TestClass()), 250) - return new TestClass() - } - } - ] - }]) - myServer.listen(8084) - - new RPCSocket(8084, 'localhost').connect().then(connsock => { - mySocket = connsock - done() - }) - }) - - after(function (done) { - mySocket.close() - myServer.close() - done() - }) - - - it("receives class object in call response", async () => { - const obj: TestClass = await mySocket['Test'].returnClass() - verifyObject(obj) - }) - - it("receives class object in hook response", async function () { - const obj: TestClass = await mySocket.Test.classCallback(function(x){ - x - }) - verifyObject(obj) - }) - - it("receives class object in callback", function (done) { - mySocket.Test.classCallback(function (cbValue) { - verifyObject(cbValue) - done() - }).then(verifyObject) - }) - }) - describe("Parameters", () => { - it("Class object in call", function(done){ - const server = new RPCServer([ - { - name: "Test", - RPCs: [ - function callWithClass(testObj: TestClass){ - verifyObject(testObj) - done() - } - ] - } - ]).listen(8086) - - new RPCSocket(8086, 'localhost').connect().then(sock => { - sock['Test'].callWithClass(new TestClass()).then(_ => { - sock.close() - server.close() - }) - }) - }) - }) -}) +}) \ No newline at end of file