diff --git a/.smartconfig.json b/.smartconfig.json new file mode 100644 index 0000000..6dd6c19 --- /dev/null +++ b/.smartconfig.json @@ -0,0 +1,11 @@ +{ + "@git.zone/cli": { + "release": { + "registries": [ + "https://verdaccio.lossless.digital", + "https://registry.npmjs.org" + ], + "accessLevel": "public" + } + } +} \ No newline at end of file diff --git a/changelog.md b/changelog.md index 3c77ff5..61f5578 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2026-05-08 - 3.3.1 - fix(virtualstream) +support reconstituting smartjson encoded binary stream chunks + +- Add VirtualStream handling for EncodedBuffer payloads encoded as base64. +- Keep support for JSON-serialized Buffer payloads and add test coverage for both binary chunk formats. +- Add release registry configuration for package publishing. + ## 2026-03-03 - 3.3.0 - feat(typedrouter) add middleware support to TypedRouter and export middleware type diff --git a/test/test.ts b/test/test.ts index c9c7a22..597c4b2 100644 --- a/test/test.ts +++ b/test/test.ts @@ -68,6 +68,21 @@ tap.test('should fire a request', async () => { expect(response.surname).toEqual('wow'); }); +tap.test('should reconstitute serialized stream chunks', async () => { + const reconstituteBinaryData = (typedrequest.VirtualStream as any).reconstituteBinaryData as (dataArg: any) => Uint8Array; + const encodedBuffer = reconstituteBinaryData({ + type: 'EncodedBuffer', + data: `base64:${Buffer.from('hello').toString('base64')}`, + }); + const serializedBuffer = reconstituteBinaryData({ + type: 'Buffer', + data: [104, 101, 108, 108, 111], + }); + + expect(new TextDecoder().decode(encodedBuffer)).toEqual('hello'); + expect(new TextDecoder().decode(serializedBuffer)).toEqual('hello'); +}); + tap.test('should allow VirtualStreams', async () => { const newRequestingVS = new typedrequest.VirtualStream(); const newRespondingVS = new typedrequest.VirtualStream(); @@ -92,7 +107,6 @@ tap.test('should allow VirtualStreams', async () => { newRequestingVS.sendData(Buffer.from('hello')); const data: any = await generatedRequestingVS.fetchData(); - // Data may arrive as Uint8Array or as JSON-serialized Buffer {type: "Buffer", data: [...]} const resolvedData = data instanceof Uint8Array || Buffer.isBuffer(data) ? data : data?.type === 'Buffer' && Array.isArray(data.data) diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index dbe07d6..15ed26b 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.3.0', + version: '3.3.1', description: 'A TypeScript library for making typed requests towards APIs, including facilities for handling requests, routing, and virtual stream handling.' } diff --git a/ts/classes.virtualstream.ts b/ts/classes.virtualstream.ts index 7e8d7c3..bf7b8c5 100644 --- a/ts/classes.virtualstream.ts +++ b/ts/classes.virtualstream.ts @@ -168,6 +168,15 @@ export class VirtualStream implements plugins.typedRequestInterf return data; } if (typeof data === 'object') { + // Handle @push.rocks/smartjson encoded binary data. + if (data.type === 'EncodedBuffer' && typeof data.data === 'string' && data.data.startsWith('base64:')) { + const base64Data = data.data.slice('base64:'.length); + if (typeof Buffer !== 'undefined') { + const buffer = Buffer.from(base64Data, 'base64'); + return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength); + } + return new Uint8Array(Array.from(atob(base64Data)).map((char) => char.charCodeAt(0))); + } // Handle JSON-serialized Node.js Buffer: {type: "Buffer", data: [...]} if (data.type === 'Buffer' && Array.isArray(data.data)) { return new Uint8Array(data.data);