You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

@anephenix/sarus

Package Overview
Dependencies
Maintainers
1
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@anephenix/sarus - npm Package Compare versions

Comparing version

to
0.6.16

63

__tests__/index/messageQueue.test.ts

@@ -141,2 +141,65 @@ // File Dependencies

});
it("should queue and deliver ArrayBuffer messages", async () => {
const server: WS = new WS(url);
const sarus: Sarus = new Sarus({ url });
await server.connected;
const buffer = new Uint8Array([1, 2, 3, 4]).buffer;
sarus.send(buffer);
const received = await server.nextMessage;
// WebSocket mock returns ArrayBuffer for binary
expect(received instanceof ArrayBuffer).toBe(true);
expect(new Uint8Array(received as ArrayBuffer)).toEqual(
new Uint8Array([1, 2, 3, 4]),
);
await server.close();
});
it("should queue and deliver Uint8Array messages", async () => {
const server: WS = new WS(url);
const sarus: Sarus = new Sarus({ url });
await server.connected;
const arr = new Uint8Array([5, 6, 7, 8]);
sarus.send(arr);
const received = await server.nextMessage;
// Always expect ArrayBuffer for binary
// Just check that it can be wrapped and matches
expect(new Uint8Array(received as ArrayBuffer)).toEqual(arr);
await server.close();
});
it("should persist and restore ArrayBuffer messages in localStorage", async () => {
localStorage.clear();
const sarus: Sarus = new Sarus({ url, storageType: "local" });
const buffer = new Uint8Array([9, 10, 11]).buffer;
sarus.send(buffer);
sarus.disconnect();
// Simulate page reload
const sarus2: Sarus = new Sarus({ url, storageType: "local" });
expect(sarus2.messages.length).toBe(1);
expect(new Uint8Array(sarus2.messages[0] as ArrayBuffer)).toEqual(
new Uint8Array([9, 10, 11]),
);
localStorage.clear();
});
it("should persist and restore Uint8Array messages in sessionStorage", async () => {
sessionStorage.clear();
const sarus: Sarus = new Sarus({ url, storageType: "session" });
const arr = new Uint8Array([12, 13, 14]);
sarus.send(arr);
sarus.disconnect();
// Simulate page reload
const sarus2: Sarus = new Sarus({ url, storageType: "session" });
expect(sarus2.messages.length).toBe(1);
expect(new Uint8Array(sarus2.messages[0] as ArrayBuffer)).toEqual(arr);
sessionStorage.clear();
});
// Ensure mock server is closed between tests to avoid port conflicts
afterEach(() => {
WS.clean();
localStorage.clear();
sessionStorage.clear();
});
});
# CHANGELOG
### 0.6.16 - Tuesday 20th May, 2025
- Merge pull request #547 from anephenix/feature/#546-binary-support-in-message-queue
- Linting fixes and moved test code to right location
- Added support for storing binary messages in the message queue
- Merge pull request #545 from anephenix/dependabot/npm_and_yarn/types/node-22.15.19
- Merge pull request #544 from anephenix/dependabot/npm_and_yarn/ts-jest-29.3.4
- Bump @types/node from 22.15.18 to 22.15.19
- Bump ts-jest from 29.3.3 to 29.3.4
- Merge pull request #543 from anephenix/dependabot/npm_and_yarn/ts-jest-29.3.3
- Bump ts-jest from 29.3.2 to 29.3.3
- Removed an unnecessary dependency
- Merge pull request #542 from anephenix/dependabot/npm_and_yarn/types/node-22.15.18
- Bump @types/node from 22.15.17 to 22.15.18
- Merge pull request #541 from anephenix/dependabot/npm_and_yarn/types/node-22.15.17
- Bump @types/node from 22.15.16 to 22.15.17
- Merge pull request #540 from anephenix/dependabot/npm_and_yarn/types/node-22.15.16
- Bump @types/node from 22.15.14 to 22.15.16
- Merge pull request #539 from anephenix/dependabot/npm_and_yarn/babel/parser-7.27.2
- Merge pull request #538 from anephenix/dependabot/npm_and_yarn/types/node-22.15.14
- Bump @babel/parser from 7.27.1 to 7.27.2
- Bump @types/node from 22.15.11 to 22.15.14
- Merge pull request #537 from anephenix/dependabot/npm_and_yarn/types/node-22.15.11
- Bump @types/node from 22.15.3 to 22.15.11
- Merge pull request #536 from anephenix/dependabot/npm_and_yarn/babel/parser-7.27.1
- Merge pull request #535 from anephenix/dependabot/npm_and_yarn/babel/types-7.27.1
- Bump @babel/parser from 7.27.0 to 7.27.1
- Bump @babel/types from 7.27.0 to 7.27.1
- Merge pull request #534 from anephenix/dependabot/npm_and_yarn/types/node-22.15.3
- Bump @types/node from 22.15.2 to 22.15.3
- Merge pull request #533 from anephenix/dependabot/npm_and_yarn/types/node-22.15.2
- Bump @types/node from 22.15.1 to 22.15.2
- Merge pull request #532 from anephenix/dependabot/npm_and_yarn/types/node-22.15.1
- Bump @types/node from 22.14.1 to 22.15.1
- Merge pull request #531 from anephenix/dependabot/npm_and_yarn/jsdom-26.1.0
- Merge pull request #530 from anephenix/dependabot/npm_and_yarn/types/node-22.14.1
- Merge pull request #529 from anephenix/dependabot/npm_and_yarn/ts-jest-29.3.2
- Bump jsdom from 26.0.0 to 26.1.0
- Bump @types/node from 22.14.0 to 22.14.1
- Bump ts-jest from 29.3.1 to 29.3.2
### 0.6.15 - Tuesday 8th April, 2025

@@ -4,0 +45,0 @@

@@ -401,2 +401,10 @@ "use strict";

var self = this;
// If the message is a base64-wrapped object (from legacy or manual insert), decode it
if (data &&
typeof data === "object" &&
data.__sarus_type === "binary" &&
typeof data.data === "string") {
// Reuse the deserializer for a single message
data = require("./lib/dataTransformer").deserialize(JSON.stringify(data));
}
self.ws.send(data);

@@ -403,0 +411,0 @@ self.removeMessage();

5

dist/lib/dataTransformer.d.ts

@@ -1,6 +0,1 @@

/**
* Serializes the data for storing in sessionStorage/localStorage
* @param {*} data - the data that we want to serialize
* @returns {string} - the serialized data
*/
export declare const serialize: (data: unknown) => string;

@@ -7,0 +2,0 @@ /**

66

dist/lib/dataTransformer.js

@@ -9,4 +9,51 @@ "use strict";

*/
var serialize = function (data) { return JSON.stringify(data); };
// Helper: ArrayBuffer/Uint8Array to base64
function bufferToBase64(buffer) {
var binary = "";
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
// Helper: base64 to ArrayBuffer
function base64ToBuffer(base64) {
var binary = atob(base64);
var len = binary.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes.buffer;
}
// Helper: Blob to base64 (async, but we use ArrayBuffer for storage)
var serialize = function (data) {
// If it's an array, serialize each element
if (Array.isArray(data)) {
return JSON.stringify(data.map(serializeSingle));
}
return JSON.stringify(serializeSingle(data));
};
exports.serialize = serialize;
function serializeSingle(data) {
if (data instanceof ArrayBuffer) {
return {
__sarus_type: "binary",
format: "arraybuffer",
data: bufferToBase64(data),
};
}
if (data instanceof Uint8Array) {
return {
__sarus_type: "binary",
format: "uint8array",
data: bufferToBase64(data.buffer),
};
}
if (typeof Blob !== "undefined" && data instanceof Blob) {
throw new Error("Blob serialization is not supported synchronously. Convert Blob to ArrayBuffer or Uint8Array before sending.");
}
return data;
}
/**

@@ -20,4 +67,19 @@ * Deserializes the data stored in sessionStorage/localStorage

return null;
return JSON.parse(data);
var parsed = JSON.parse(data);
if (Array.isArray(parsed)) {
return parsed.map(deserializeSingle);
}
return deserializeSingle(parsed);
};
exports.deserialize = deserialize;
function deserializeSingle(parsed) {
if (parsed && parsed.__sarus_type === "binary") {
if (parsed.format === "arraybuffer") {
return base64ToBuffer(parsed.data);
}
if (parsed.format === "uint8array") {
return new Uint8Array(base64ToBuffer(parsed.data));
}
}
return parsed;
}
{
"name": "@anephenix/sarus",
"version": "0.6.15",
"version": "0.6.16",
"description": "A WebSocket JavaScript library",

@@ -38,3 +38,2 @@ "main": "dist/index.js",

"jsdom": "^26.0.0",
"mock-socket": "^9.2.1",
"prettier": "^3.0.3",

@@ -41,0 +40,0 @@ "size-limit": "^11.1.6",

@@ -495,2 +495,14 @@ // File Dependencies

const self: any = this;
// If the message is a base64-wrapped object (from legacy or manual insert), decode it
if (
data &&
typeof data === "object" &&
(data as any).__sarus_type === "binary" &&
typeof (data as any).data === "string"
) {
// Reuse the deserializer for a single message
data = (require("./lib/dataTransformer") as any).deserialize(
JSON.stringify(data),
);
}
self.ws.send(data);

@@ -497,0 +509,0 @@ self.removeMessage();

@@ -6,4 +6,57 @@ /**

*/
export const serialize = (data: unknown) => JSON.stringify(data);
// Helper: ArrayBuffer/Uint8Array to base64
function bufferToBase64(buffer: ArrayBuffer): string {
let binary = "";
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
// Helper: base64 to ArrayBuffer
function base64ToBuffer(base64: string): ArrayBuffer {
const binary = atob(base64);
const len = binary.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes.buffer;
}
// Helper: Blob to base64 (async, but we use ArrayBuffer for storage)
export const serialize = (data: unknown) => {
// If it's an array, serialize each element
if (Array.isArray(data)) {
return JSON.stringify(data.map(serializeSingle));
}
return JSON.stringify(serializeSingle(data));
};
function serializeSingle(data: unknown): any {
if (data instanceof ArrayBuffer) {
return {
__sarus_type: "binary",
format: "arraybuffer",
data: bufferToBase64(data),
};
}
if (data instanceof Uint8Array) {
return {
__sarus_type: "binary",
format: "uint8array",
data: bufferToBase64(data.buffer),
};
}
if (typeof Blob !== "undefined" && data instanceof Blob) {
throw new Error(
"Blob serialization is not supported synchronously. Convert Blob to ArrayBuffer or Uint8Array before sending.",
);
}
return data;
}
/**

@@ -16,3 +69,19 @@ * Deserializes the data stored in sessionStorage/localStorage

if (!data) return null;
return JSON.parse(data);
const parsed = JSON.parse(data);
if (Array.isArray(parsed)) {
return parsed.map(deserializeSingle);
}
return deserializeSingle(parsed);
};
function deserializeSingle(parsed: any): any {
if (parsed && parsed.__sarus_type === "binary") {
if (parsed.format === "arraybuffer") {
return base64ToBuffer(parsed.data);
}
if (parsed.format === "uint8array") {
return new Uint8Array(base64ToBuffer(parsed.data));
}
}
return parsed;
}