From bf81c34dbcdb7298f9541f6cbbf4f3bbb94cd499 Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Wed, 21 Feb 2024 18:29:35 +0100 Subject: [PATCH] fix(core): update --- package.json | 4 +- pnpm-lock.yaml | 58 ++++--------- test/test.ts | 31 ++++++- ts/00_commitinfo_data.ts | 2 +- ts/index.ts | 1 + ts/typedrequest.classes.streamobject.ts | 44 ---------- ts/typedrequest.classes.typedrequest.ts | 60 ++++++++++---- ts/typedrequest.classes.typedrouter.ts | 40 +++++++++ ts/typedrequest.classes.virtualstream.ts | 100 +++++++++++++++++++++++ tsconfig.json | 12 ++- 10 files changed, 244 insertions(+), 108 deletions(-) delete mode 100644 ts/typedrequest.classes.streamobject.ts create mode 100644 ts/typedrequest.classes.virtualstream.ts diff --git a/package.json b/package.json index b3fc85c..85135da 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "buildDocs": "tsdoc" }, "devDependencies": { - "@api.global/typedserver": "^3.0.20", + "@api.global/typedserver": "^3.0.23", "@git.zone/tsbuild": "^2.1.72", "@git.zone/tsbundle": "^2.0.15", "@git.zone/tsrun": "^1.2.44", @@ -24,7 +24,7 @@ "@types/node": "^20.11.19" }, "dependencies": { - "@api.global/typedrequest-interfaces": "^3.0.1", + "@api.global/typedrequest-interfaces": "^3.0.6", "@push.rocks/isounique": "^1.0.5", "@push.rocks/lik": "^6.0.12", "@push.rocks/smartdelay": "^3.0.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6985cf6..e731438 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@api.global/typedrequest-interfaces': - specifier: ^3.0.1 - version: 3.0.1 + specifier: ^3.0.6 + version: 3.0.6 '@push.rocks/isounique': specifier: ^1.0.5 version: 1.0.5 @@ -26,8 +26,8 @@ dependencies: devDependencies: '@api.global/typedserver': - specifier: ^3.0.20 - version: 3.0.20 + specifier: ^3.0.23 + version: 3.0.23 '@git.zone/tsbuild': specifier: ^2.1.72 version: 2.1.72 @@ -52,13 +52,13 @@ devDependencies: packages: - /@api.global/typedrequest-interfaces@3.0.1: - resolution: {integrity: sha512-eR2Cr01BYRwIq/X2ajOenWhm8l+/YE4A5kK/9V6I8ZnhtEBMFHG6YjF6Fg8npLJWbvhZXhOms+axZ6JKI71o8g==} + /@api.global/typedrequest-interfaces@3.0.6: + resolution: {integrity: sha512-WnyJx1SobjK4NcOY4GXnqIhBEZ76BvvMKbGI/oh1lukS3WKYb6/b1ne4CzPlPnaFtAyETRbkphPhlzMIe3sTZA==} /@api.global/typedrequest@3.0.4: resolution: {integrity: sha512-8UThH9c3MxdSLiON8UN1CPXooU6Mp0eleFhVS3QB2OUsYqgEGn/EzuMt+cMIv/+ESSS6zcTpHvAhZ8ZMLfpL8A==} dependencies: - '@api.global/typedrequest-interfaces': 3.0.1 + '@api.global/typedrequest-interfaces': 3.0.6 '@push.rocks/isounique': 1.0.5 '@push.rocks/lik': 6.0.12 '@push.rocks/smartdelay': 3.0.5 @@ -66,11 +66,11 @@ packages: '@push.rocks/webrequest': 3.0.34 dev: true - /@api.global/typedserver@3.0.20: - resolution: {integrity: sha512-bJA79KxGD24xqOMNZCovMK13Qf1x0hhzwQ+vlfbqvnKkMAieNbfiTfYcrMsfmTSMMDP0rEi9JEBW8tFSt4bn5g==} + /@api.global/typedserver@3.0.23: + resolution: {integrity: sha512-8n84MXIJXUxjEu6JVQulzdwQ+JYwXjhWbpqQQTDDeMNlpmaz3QEoE83rwehL8AyTaY++VwwYpkJqSXPGWQ+5ww==} dependencies: '@api.global/typedrequest': 3.0.4 - '@api.global/typedrequest-interfaces': 3.0.1 + '@api.global/typedrequest-interfaces': 3.0.6 '@api.global/typedsocket': 3.0.0 '@push.rocks/lik': 6.0.12 '@push.rocks/smartchok': 1.0.32 @@ -78,6 +78,7 @@ packages: '@push.rocks/smartenv': 5.0.12 '@push.rocks/smartfeed': 1.0.11 '@push.rocks/smartfile': 11.0.4 + '@push.rocks/smartjson': 5.0.10 '@push.rocks/smartlog': 3.0.3 '@push.rocks/smartlog-destination-devtools': 1.0.10 '@push.rocks/smartmanifest': 2.0.2 @@ -108,7 +109,7 @@ packages: resolution: {integrity: sha512-ui+6MLd99iTN/lC+iC/FKPRjzVyiZ4PrmlU6ptbCtbBj3cSOXHx+RRGF54+be2xHodf4FOgwFv/GZdW8LtO3vg==} dependencies: '@api.global/typedrequest': 3.0.4 - '@api.global/typedrequest-interfaces': 3.0.1 + '@api.global/typedrequest-interfaces': 3.0.6 '@push.rocks/isohash': 2.0.1 '@push.rocks/smartjson': 5.0.10 '@push.rocks/smartrx': 3.0.7 @@ -418,7 +419,7 @@ packages: resolution: {integrity: sha512-ec95MNeA21L+ob+lvLVCmwPTTC1BY+v/JHLYZ9DOZ9+9buLgx+cJ7VkwGBJCnlWJtqEtJosUrFKTih36iNuT3g==} hasBin: true dependencies: - '@api.global/typedserver': 3.0.20 + '@api.global/typedserver': 3.0.23 '@git.zone/tsbundle': 2.0.15 '@git.zone/tsrun': 1.2.46(@types/node@20.11.19) '@push.rocks/consolecolor': 2.0.1 @@ -938,8 +939,8 @@ packages: /@push.rocks/smartsocket@2.0.24: resolution: {integrity: sha512-Glqv1Zi5TXgD+04P8OvTpiytyfrQxTPv67qAwZizAVVQ2zWJJgKqnIuoHT1zKP8QiKRNer+D58LCxX0ZE2XfzQ==} dependencies: - '@api.global/typedrequest-interfaces': 3.0.1 - '@api.global/typedserver': 3.0.20 + '@api.global/typedrequest-interfaces': 3.0.6 + '@api.global/typedserver': 3.0.23 '@push.rocks/isohash': 2.0.1 '@push.rocks/isounique': 1.0.5 '@push.rocks/lik': 6.0.12 @@ -2324,7 +2325,6 @@ packages: function-bind: 1.1.2 get-intrinsic: 1.2.4 set-function-length: 1.2.1 - dev: true /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} @@ -2679,7 +2679,6 @@ packages: get-intrinsic: 1.2.1 gopd: 1.0.1 has-property-descriptors: 1.0.0 - dev: true /define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} @@ -2688,20 +2687,12 @@ packages: es-define-property: 1.0.0 es-errors: 1.3.0 gopd: 1.0.1 - dev: true /define-lazy-prop@2.0.0: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} dev: true - /define-properties@1.1.4: - resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} - engines: {node: '>= 0.4'} - dependencies: - has-property-descriptors: 1.0.0 - object-keys: 1.1.1 - /define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -2709,7 +2700,6 @@ packages: define-data-property: 1.1.1 has-property-descriptors: 1.0.0 object-keys: 1.1.1 - dev: true /delayed-stream@1.0.0: resolution: {integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk=} @@ -2917,12 +2907,10 @@ packages: engines: {node: '>= 0.4'} dependencies: get-intrinsic: 1.2.4 - dev: true /es-errors@1.3.0: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - dev: true /es-module-lexer@1.3.1: resolution: {integrity: sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==} @@ -3263,7 +3251,6 @@ packages: /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true /function.prototype.name@1.1.6: resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} @@ -3302,7 +3289,6 @@ packages: has: 1.0.4 has-proto: 1.0.1 has-symbols: 1.0.3 - dev: true /get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} @@ -3313,7 +3299,6 @@ packages: has-proto: 1.0.3 has-symbols: 1.0.3 hasown: 2.0.1 - dev: true /get-stream@5.2.0: resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} @@ -3399,7 +3384,6 @@ packages: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: get-intrinsic: 1.2.1 - dev: true /got@12.6.1: resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} @@ -3454,17 +3438,14 @@ packages: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} dependencies: es-define-property: 1.0.0 - dev: true /has-proto@1.0.1: resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} engines: {node: '>= 0.4'} - dev: true /has-proto@1.0.3: resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} engines: {node: '>= 0.4'} - dev: true /has-symbols@1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} @@ -3486,14 +3467,12 @@ packages: /has@1.0.4: resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} engines: {node: '>= 0.4.0'} - dev: true /hasown@2.0.1: resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==} engines: {node: '>= 0.4'} dependencies: function-bind: 1.1.2 - dev: true /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} @@ -3744,8 +3723,8 @@ packages: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 + call-bind: 1.0.7 + define-properties: 1.2.1 /is-negative-zero@2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} @@ -3931,7 +3910,7 @@ packages: dependencies: universalify: 2.0.0 optionalDependencies: - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 dev: true /just-extend@6.2.0: @@ -5088,7 +5067,6 @@ packages: get-intrinsic: 1.2.4 gopd: 1.0.1 has-property-descriptors: 1.0.2 - dev: true /set-function-name@2.0.1: resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} diff --git a/test/test.ts b/test/test.ts index 7e74f05..aa06527 100644 --- a/test/test.ts +++ b/test/test.ts @@ -4,6 +4,7 @@ import * as typedserver from '@api.global/typedserver'; import * as typedrequest from '../ts/index.js'; let testServer: typedserver.servertools.Server; +let testTypedRouter: typedrequest.TypedRouter; let testTypedHandler: typedrequest.TypedHandler; // lets define an interface @@ -17,6 +18,16 @@ interface ITestReqRes { }; } +interface ITestStream { + method: 'handleStream'; + request: { + requestStream: any; + }; + response: { + responseStream: any; + }; +} + tap.test('should create a typedHandler', async () => { // lets use the interface in a TypedHandler testTypedHandler = new typedrequest.TypedHandler('hi', async (reqArg) => { @@ -35,7 +46,7 @@ tap.test('should spawn a server to test with', async () => { }); tap.test('should define a testHandler', async () => { - const testTypedRouter = new typedrequest.TypedRouter(); // typed routers can broker typedrequests between handlers + testTypedRouter = new typedrequest.TypedRouter(); // typed routers can broker typedrequests between handlers testTypedRouter.addTypedHandler(testTypedHandler); testServer.addRoute( '/testroute', @@ -60,6 +71,24 @@ tap.test('should fire a request', async () => { expect(response.surname).toEqual('wow'); }); +tap.test('should allow VirtualStreams', async () => { + testTypedRouter.addTypedHandler(new typedrequest.TypedHandler('handleStream', async (reqArg) => { + console.log('hey there'); + console.log(reqArg.requestStream); + return { + responseStream: new typedrequest.VirtualStream(), + }; + })); + const typedRequest = new typedrequest.TypedRequest( + 'http://localhost:3000/testroute', + 'handleStream' + ); + const response = await typedRequest.fire({ + requestStream: new typedrequest.VirtualStream(), + }); + console.log(response.responseStream); +}) + tap.test('should end the server', async () => { await testServer.stop(); }); diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 1ff2226..1eece6c 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@api.global/typedrequest', - version: '3.0.5', + version: '3.0.6', description: 'make typed requests towards apis' } diff --git a/ts/index.ts b/ts/index.ts index b55a287..7af6e8e 100644 --- a/ts/index.ts +++ b/ts/index.ts @@ -3,3 +3,4 @@ export * from './typedrequest.classes.typedhandler.js'; export * from './typedrequest.classes.typedrouter.js'; export * from './typedrequest.classes.typedresponseerror.js'; export * from './typedrequest.classes.typedtarget.js'; +export * from './typedrequest.classes.virtualstream.js'; \ No newline at end of file diff --git a/ts/typedrequest.classes.streamobject.ts b/ts/typedrequest.classes.streamobject.ts deleted file mode 100644 index 3c80e82..0000000 --- a/ts/typedrequest.classes.streamobject.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as plugins from './plugins.js'; - -export class VirtualStream { - public streamId: string = plugins.isounique.uni(); - - constructor() {} - - public static encodePayloadForNetwork(objectPayload: any): any { - if (objectPayload instanceof VirtualStream) { - return { - _isVirtualStream: true, - streamId: objectPayload.streamId, - }; - } else if (Array.isArray(objectPayload)) { - return objectPayload.map(VirtualStream.encodePayloadForNetwork); - } else if (objectPayload !== null && typeof objectPayload === 'object') { - return Object.keys(objectPayload).reduce((acc, key) => { - acc[key] = VirtualStream.encodePayloadForNetwork(objectPayload[key]); - return acc; - }, {}); - } else { - return objectPayload; - } - } - - public static decodePayloadFromNetwork(objectPayload: any): any { - if (objectPayload !== null && typeof objectPayload === 'object') { - if (objectPayload._isVirtualStream) { - const virtualStream = new VirtualStream(); - virtualStream.streamId = objectPayload.streamId; - return virtualStream; - } else if (Array.isArray(objectPayload)) { - return objectPayload.map(VirtualStream.decodePayloadFromNetwork); - } else { - return Object.keys(objectPayload).reduce((acc, key) => { - acc[key] = VirtualStream.decodePayloadFromNetwork(objectPayload[key]); - return acc; - }, {}); - } - } else { - return objectPayload; - } - } -} diff --git a/ts/typedrequest.classes.typedrequest.ts b/ts/typedrequest.classes.typedrequest.ts index 5ba744e..5ef1024 100644 --- a/ts/typedrequest.classes.typedrequest.ts +++ b/ts/typedrequest.classes.typedrequest.ts @@ -1,4 +1,5 @@ import * as plugins from './plugins.js'; +import { VirtualStream } from './typedrequest.classes.virtualstream.js'; import { TypedResponseError } from './typedrequest.classes.typedresponseerror.js'; import { TypedRouter } from './typedrequest.classes.typedrouter.js'; import { TypedTarget } from './typedrequest.classes.typedtarget.js'; @@ -36,8 +37,7 @@ export class TypedRequest { - - let payload: plugins.typedRequestInterfaces.ITypedRequest = { + let payloadSending: plugins.typedRequestInterfaces.ITypedRequest = { method: this.method, request: fireArg, response: null, @@ -47,30 +47,58 @@ export class TypedRequest { + return this.postTrObject(payloadArg); + } + }); + + let payloadReceiving: plugins.typedRequestInterfaces.ITypedRequest; + payloadReceiving = await this.postTrObject(payloadSending, useCacheArg); + + // lets preprocess the response + payloadReceiving = VirtualStream.decodePayloadFromNetwork(payloadReceiving, { + sendMethod: (payloadArg: plugins.typedRequestInterfaces.ITypedRequest) => { + return this.postTrObject(payloadArg); + } + }); + return payloadReceiving.response; + } + + private async postTrObject(payloadSendingArg: plugins.typedRequestInterfaces.ITypedRequest, useCacheArg: boolean = false) { + let payloadReceiving: plugins.typedRequestInterfaces.ITypedRequest; if (this.urlEndPoint) { - const response = await webrequestInstance.postJson(this.urlEndPoint, payload, useCacheArg); - responseBody = response; + const response = await webrequestInstance.postJson( + this.urlEndPoint, + payloadSendingArg, + useCacheArg + ); + payloadReceiving = response; } else { - responseBody = await this.typedTarget.post(payload); + payloadReceiving = await this.typedTarget.post(payloadSendingArg); } - if (responseBody.error) { + if (payloadReceiving.error) { console.error( - `Got an error ${responseBody.error.text} with data ${JSON.stringify( - responseBody.error.data, null, 2 + `Got an error ${payloadReceiving.error.text} with data ${JSON.stringify( + payloadReceiving.error.data, + null, + 2 )}` ); - if (!responseBody.retry) { - throw new TypedResponseError(responseBody.error.text, responseBody.error.data); + if (!payloadReceiving.retry) { + throw new TypedResponseError(payloadReceiving.error.text, payloadReceiving.error.data); } return null; } - if (responseBody.retry) { - console.log(`server requested retry for the following reason: ${responseBody.retry.reason}`); - await plugins.smartdelay.delayFor(responseBody.retry.waitForMs); + if (payloadReceiving.retry) { + console.log( + `server requested retry for the following reason: ${payloadReceiving.retry.reason}` + ); + await plugins.smartdelay.delayFor(payloadReceiving.retry.waitForMs); // tslint:disable-next-line: no-return-await - return await this.fire(fireArg); + payloadReceiving = await this.postTrObject(payloadSendingArg, useCacheArg); } - return responseBody.response; + return payloadReceiving; } } diff --git a/ts/typedrequest.classes.typedrouter.ts b/ts/typedrequest.classes.typedrouter.ts index 7d725a7..585df0c 100644 --- a/ts/typedrequest.classes.typedrouter.ts +++ b/ts/typedrequest.classes.typedrouter.ts @@ -1,4 +1,5 @@ import * as plugins from './plugins.js'; +import { VirtualStream } from './typedrequest.classes.virtualstream.js'; import { TypedHandler } from './typedrequest.classes.typedhandler.js'; import { TypedRequest } from './typedrequest.classes.typedrequest.js'; @@ -13,6 +14,7 @@ export class TypedRouter { public handlerMap = new plugins.lik.ObjectMap< TypedHandler >(); + public registeredVirtualStreams = new plugins.lik.ObjectMap(); public fireEventInterestMap = new plugins.lik.InterestMap< string, @@ -89,6 +91,22 @@ export class TypedRouter { public async routeAndAddResponse< T extends plugins.typedRequestInterfaces.ITypedRequest = plugins.typedRequestInterfaces.ITypedRequest >(typedRequestArg: T, localRequestArg = false): Promise { + // decoding first + typedRequestArg = VirtualStream.decodePayloadFromNetwork(typedRequestArg, { + typedrouter: this, + }); + + // localdata second + typedRequestArg.localData = typedRequestArg.localData || {}; + typedRequestArg.localData.firstTypedrouter = this; + + // lets do stream processing + if (typedRequestArg.method === '##VirtualStream##') { + const result = await this.handleStreamTypedRequest(typedRequestArg as plugins.typedRequestInterfaces.IStreamRequest); + return result as T; + } + + // lets do normal routing if (typedRequestArg?.correlation?.phase === 'request' || localRequestArg) { const typedHandler = this.getTypedHandlerForMethod(typedRequestArg.method); @@ -99,10 +117,20 @@ export class TypedRouter { data: {}, }; typedRequestArg.correlation.phase = 'response'; + + // encode again before handing back + typedRequestArg = VirtualStream.encodePayloadForNetwork(typedRequestArg, { + typedrouter: this, + }); return typedRequestArg; } typedRequestArg = await typedHandler.addResponse(typedRequestArg); + typedRequestArg.localData = null; + // encode again before handing back + typedRequestArg = VirtualStream.encodePayloadForNetwork(typedRequestArg, { + typedrouter: this, + }); return typedRequestArg; } else if (typedRequestArg?.correlation?.phase === 'response') { this.fireEventInterestMap @@ -115,4 +143,16 @@ export class TypedRouter { return null; } } + + /** + * handle streaming + * @param streamTrArg + */ + public async handleStreamTypedRequest(streamTrArg: plugins.typedRequestInterfaces.IStreamRequest) { + const relevantVirtualStream = await this.registeredVirtualStreams.find(async virtualStreamArg => { + return virtualStreamArg.streamId === streamTrArg.request.streamId; + }); + const result = await relevantVirtualStream.handleStreamTr(streamTrArg); + return result; + } } diff --git a/ts/typedrequest.classes.virtualstream.ts b/ts/typedrequest.classes.virtualstream.ts new file mode 100644 index 0000000..507cd09 --- /dev/null +++ b/ts/typedrequest.classes.virtualstream.ts @@ -0,0 +1,100 @@ +import * as plugins from './plugins.js'; +import type { TypedRouter } from './typedrequest.classes.typedrouter.js'; + +export interface ICommFunctions { + sendMethod?: ( + sendPayload: plugins.typedRequestInterfaces.ITypedRequest + ) => Promise; + typedrouter?: TypedRouter; +} + +export class VirtualStream { + // STATIC + public static encodePayloadForNetwork( + objectPayload: any, + commFunctions: ICommFunctions + ): any { + if (objectPayload instanceof VirtualStream) { + if (!objectPayload.side && commFunctions.sendMethod) { + objectPayload.side = 'requesting'; + objectPayload.sendMethod = commFunctions.sendMethod; + } + if (!objectPayload.side && commFunctions.typedrouter) { + objectPayload.side = 'responding'; + objectPayload.typedrouter = commFunctions.typedrouter; + } + return { + _isVirtualStream: true, + streamId: objectPayload.streamId, + }; + } else if (Array.isArray(objectPayload)) { + const returnArray = []; + for (const item of objectPayload) { + returnArray.push(VirtualStream.encodePayloadForNetwork(item, commFunctions)); + } + return returnArray; + } else if (objectPayload !== null && typeof objectPayload === 'object') { + return Object.keys(objectPayload).reduce((acc, key) => { + acc[key] = VirtualStream.encodePayloadForNetwork(objectPayload[key], commFunctions); + return acc; + }, {}); + } else { + return objectPayload; + } + } + + public static decodePayloadFromNetwork(objectPayload: any, commFunctions: ICommFunctions): any { + if (objectPayload !== null && typeof objectPayload === 'object') { + if (objectPayload._isVirtualStream) { + const virtualStream = new VirtualStream(); + virtualStream.streamId = objectPayload.streamId; + if (!virtualStream.side && commFunctions.sendMethod) { + virtualStream.side = 'requesting'; + virtualStream.sendMethod = commFunctions.sendMethod; + } + if (!virtualStream.side && commFunctions.typedrouter) { + virtualStream.side = 'responding'; + virtualStream.typedrouter = commFunctions.typedrouter; + } + return virtualStream; + } else if (Array.isArray(objectPayload)) { + const returnArray = []; + for (const item of objectPayload) { + returnArray.push(VirtualStream.decodePayloadFromNetwork(item, commFunctions)); + } + return returnArray; + } else { + return Object.keys(objectPayload).reduce((acc, key) => { + acc[key] = VirtualStream.decodePayloadFromNetwork(objectPayload[key], commFunctions); + return acc; + }, {}); + } + } else { + return objectPayload; + } + } + + // INSTANCE + + public side: 'requesting' | 'responding'; + public streamId: string = plugins.isounique.uni(); + public typedrouter: TypedRouter; + public sendMethod: ( + sendPayloadArg: plugins.typedRequestInterfaces.ITypedRequest + ) => Promise; + + constructor() {} + + public async handleStreamTr(streamTrArg: plugins.typedRequestInterfaces.IStreamRequest) { + return streamTrArg; + } + + /** + * closes the virtual stream + */ + close() { + if (this.typedrouter) { + this.typedrouter.registeredVirtualStreams.remove(this); + } + } +} diff --git a/tsconfig.json b/tsconfig.json index 0e331cc..dfe5a55 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,8 +3,12 @@ "experimentalDecorators": true, "useDefineForClassFields": false, "target": "ES2022", - "module": "ES2022", - "moduleResolution": "nodenext", - "esModuleInterop": true - } + "module": "NodeNext", + "moduleResolution": "NodeNext", + "esModuleInterop": true, + "verbatimModuleSyntax": true + }, + "exclude": [ + "dist_*/**/*.d.ts" + ] }