From 82009b651dee96169a8cd7affaa9659b0a49b531 Mon Sep 17 00:00:00 2001 From: WarstekHUN Date: Tue, 19 Dec 2023 15:12:48 +0100 Subject: [PATCH 1/8] Cookies --- .coverage-badges/badge-branches.svg | 2 +- .coverage-badges/badge-lines.svg | 2 +- .coverage-badges/badge-statements.svg | 2 +- CHANGELOG.md | 9 +++++- src/index.ts | 44 +++++++++++++++++++++++++-- 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/.coverage-badges/badge-branches.svg b/.coverage-badges/badge-branches.svg index e9dbd7c..ac488e3 100644 --- a/.coverage-badges/badge-branches.svg +++ b/.coverage-badges/badge-branches.svg @@ -1 +1 @@ -Coverage:branches: 100%Coverage:branches100% \ No newline at end of file +Coverage:branches: 91.83%Coverage:branches91.83% \ No newline at end of file diff --git a/.coverage-badges/badge-lines.svg b/.coverage-badges/badge-lines.svg index cbb01ce..d2c00bc 100644 --- a/.coverage-badges/badge-lines.svg +++ b/.coverage-badges/badge-lines.svg @@ -1 +1 @@ -Coverage:lines: 100%Coverage:lines100% \ No newline at end of file +Coverage:lines: 97.58%Coverage:lines97.58% \ No newline at end of file diff --git a/.coverage-badges/badge-statements.svg b/.coverage-badges/badge-statements.svg index 3f8ebb1..bca3e67 100644 --- a/.coverage-badges/badge-statements.svg +++ b/.coverage-badges/badge-statements.svg @@ -1 +1 @@ -Coverage:statements: 100%Coverage:statements100% \ No newline at end of file +Coverage:statements: 97.72%Coverage:statements97.72% \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index aed8f88..defbc43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1,8 @@ -- Babel security fix \ No newline at end of file +# New Features + +- Ability to set custom headers (only in Node) +- Ability to get custom headers +- The serverside (^1.2) can now set cookies. + - New local events: + - onCookieSet + - onCookieDelete diff --git a/src/index.ts b/src/index.ts index 75b4f41..420d801 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,6 +49,20 @@ interface ICallableLocalEvents { * @returns */ onRawMessageRecieved: (message: string) => void; + + /** + * Runs when the server sends down one or multiple new cookies. + * @param cookieString + * @returns + */ + onCookieSet: (cookieString: string) => void; + + /** + * Runs when the server deletes a cookie + * @param cookieName + * @returns + */ + onCookieDelete: (cookieName: string) => void; } export class ZilaConnection { @@ -147,7 +161,7 @@ export class ZilaConnection { if (this.errorCallback) this.errorCallback(reason); }; - this.connection.onmessage = (ev: any) => { + this.connection.onmessage = (ev: MessageEvent) => { this.callEventHandler(ev.data.toString()); }; } @@ -165,8 +179,32 @@ export class ZilaConnection { const msgObj: WSMessage = JSON.parse(msg); - if (!errorHappened) { - errorHappened = true; + if (msgObj.identifier[0] == "@") { + if (msgObj.identifier == "@SetCookie") { + /* istanbul ignore next */ + if (typeof window !== "undefined" && typeof window.document !== "undefined") { + const cookieString = msgObj.message as unknown as string; + document.cookie = cookieString; + + if (this.localEventCallbacks.onCookieSet) + for (const cb of this.localEventCallbacks.onCookieSet) { + cb(cookieString); + } + } + } else if (msgObj.identifier == "@DelCookie") { + /* istanbul ignore next */ + if (typeof window !== "undefined" && typeof window.document !== "undefined") { + const cookieName = msgObj.message as unknown as string; + document.cookie = `${cookieName}=; expires=${new Date(0)}; path=/;`; + + if (this.localEventCallbacks.onCookieDelete) + for (const cb of this.localEventCallbacks.onCookieDelete) { + cb(cookieName); + } + } + } + + return; } if (this.localEventCallbacks.onMessageRecieved) { From 2a09ffc454a4bb4f0896522276500d4d00a875eb Mon Sep 17 00:00:00 2001 From: WarstekHUN Date: Thu, 21 Dec 2023 02:09:25 +0100 Subject: [PATCH 2/8] Manual browser testing is needed --- .coverage-badges/badge-branches.svg | 2 +- .coverage-badges/badge-lines.svg | 2 +- .coverage-badges/badge-statements.svg | 2 +- CHANGELOG.md | 2 - src/index.ts | 4 + test/index.test.ts | 151 ++++---------------------- 6 files changed, 28 insertions(+), 135 deletions(-) diff --git a/.coverage-badges/badge-branches.svg b/.coverage-badges/badge-branches.svg index ac488e3..c43f36b 100644 --- a/.coverage-badges/badge-branches.svg +++ b/.coverage-badges/badge-branches.svg @@ -1 +1 @@ -Coverage:branches: 91.83%Coverage:branches91.83% \ No newline at end of file +Coverage:branches: 91.66%Coverage:branches91.66% \ No newline at end of file diff --git a/.coverage-badges/badge-lines.svg b/.coverage-badges/badge-lines.svg index d2c00bc..5c716cf 100644 --- a/.coverage-badges/badge-lines.svg +++ b/.coverage-badges/badge-lines.svg @@ -1 +1 @@ -Coverage:lines: 97.58%Coverage:lines97.58% \ No newline at end of file +Coverage:lines: 97.54%Coverage:lines97.54% \ No newline at end of file diff --git a/.coverage-badges/badge-statements.svg b/.coverage-badges/badge-statements.svg index bca3e67..6b0f0fc 100644 --- a/.coverage-badges/badge-statements.svg +++ b/.coverage-badges/badge-statements.svg @@ -1 +1 @@ -Coverage:statements: 97.72%Coverage:statements97.72% \ No newline at end of file +Coverage:statements: 97.69%Coverage:statements97.69% \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index defbc43..cb12f5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,5 @@ # New Features -- Ability to set custom headers (only in Node) -- Ability to get custom headers - The serverside (^1.2) can now set cookies. - New local events: - onCookieSet diff --git a/src/index.ts b/src/index.ts index 420d801..2bac405 100644 --- a/src/index.ts +++ b/src/index.ts @@ -107,12 +107,16 @@ export class ZilaConnection { let ws: WebSocket | globalThis.WebSocket | undefined; try { + //Can't test this with Node. /* istanbul ignore next */ if (typeof window !== "undefined" && typeof window.document !== "undefined") { ws = new window.WebSocket(wsUrl); } else { ws = new WebSocket(wsUrl, { rejectUnauthorized: !allowSelfSignedCert, + headers: { + "s-type": 1 + } }); } } catch (error) { diff --git a/test/index.test.ts b/test/index.test.ts index 622fc09..337f68b 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -77,6 +77,26 @@ describe("WebSocket connection", () => { server.send(clientSocket, "THISSHOULDNOTEXIST", "SMTH"); }); + test("Recieving cookies", () => { + client.onceEventListener("onCookieSet", (cookieStr) => { + expect(cookieStr).toEqual("MyCookie=ExampleValue; Path=/"); + }); + + clientSocket.setCookie({ + name: "MyCookie", + value: "ExampleValue", + path: "/" + }); + }); + + test("Cookie deletion", () => { + client.onceEventListener("onCookieDelete", (cookieName) => { + expect(cookieName).toEqual("MyCookie"); + }); + + clientSocket.removeCookie("MyCookie"); + }); + test.failing("Client-Server but with a function", () => { server.setMessageHandler("Client-Server", (socket, obj: { smth: any }) => {}); client.send("Client-Server", () => { @@ -174,133 +194,4 @@ describe("WebSocket connection", () => { await client.disconnectAsync(); await server.stopServerAsync(); }); -}); - -describe("WebSocket connection", () => { - beforeAll(async () => { - server = new ZilaServer({ - port: 6589, - logger: true, - verbose: true, - }); - - client = await connectTo("ws://127.0.0.1:6589", (reason?: string) => { - console.log("Error " + reason); - }); - }); - - test("RemoveEventListener nothing to remove", () => { - client.removeEventListener("onStatusChange", func); - }); - - test("RemoveEventListener not existing callback", () => { - function loc(asd: WSStatus) { - return null; - } - client.addEventListener("onStatusChange", loc); - client.removeEventListener("onStatusChange", () => { - return 1; - }); - client.removeEventListener("onStatusChange", loc); - }); - - test("Connection status is open", () => { - expect(client.status).toBe(WSStatus.OPEN); - }); - - test("Client Async Waiter", async () => { - server.setMessageHandler("sample", (socket, text: string) => { - clientSocket = socket; - return text + " success"; - }); - expect(await client.waiter("sample", "sampleData")).toBe("sampleData success"); - }); - - test("Server-Client", () => { - client.setMessageHandler("clientSample", (text: string) => { - expect(text).toBe("sampleText"); - }); - server.send(clientSocket, "clientSample", "sampleText"); - }); - - test("Client-Server", () => { - server.setMessageHandler("Client-Server", (socket, obj: { smth: boolean }) => { - expect(obj).toEqual({ smth: true }); - }); - client.send("Client-Server", { smth: true }); - }); - - test.failing("Client-Server but with a function", () => { - server.setMessageHandler("Client-Server", (socket, obj: { smth: any }) => {}); - client.send("Client-Server", () => { - console.log("I'm a function!"); - }); - }); - - test.failing("Waiter but with a function", async () => { - await client.waiter("SMTH", () => { - console.log("I'm a function!"); - }); - }); - - test.failing("Multiple EventListeners with same credintals", () => { - client.addEventListener("onStatusChange", func); - client.addEventListener("onStatusChange", func); - }); - - test.failing("Connecting error handler 1", async () => { - await connectTo("127.0.0.1", (err) => {}); - }); - - test.failing("Connecting error handler 2", async () => { - await connectTo("ws://127.0.0.1:123", (err) => {}); - }); - - test.failing("Connecting error handler 3", async () => { - await connectTo("wss://127.0.0.1:123", (err) => {}); - }); - - test("Server-Client Asnyc Waiter With String", async () => { - client.setMessageHandler("clientSampleAsyncString", (text: string) => { - return text + " success"; - }); - expect(await server.waiter(clientSocket, "clientSampleAsyncString", "sampleString")).toBe( - "sampleString success" - ); - }); - - test("OnceMessageHandler", () => { - client.onceMessageHandler("ONCEMESSAGE", (arg1: number) => { - console.log(arg1++); - expect(arg1).toEqual(35.67); - }); - server.send(clientSocket, "ONCEMESSAGE", 34.67); - }); - - test("SetErrorHandler", () => { - client.setErrorHandler((error) => { - console.error(error); - }); - }); - - test("Simple Disconnect", async () => { - const locClient = await connectTo("ws://127.0.0.1:6589"); - await new Promise((res) => { - locClient.onceEventListener("onStatusChange", () => { - res(); - }); - locClient.disconnect(); - }); - }); - - test("Client Already AsyncDisconnected", async () => { - const locClient = await connectTo("ws://127.0.0.1:6589"); - await locClient.disconnectAsync(); - await locClient.disconnectAsync(); - }); - - afterAll(async () => { - await client.disconnectAsync(); - await server.stopServerAsync(); - }); -}); +}); \ No newline at end of file From 9d87c2a046fefad6598d12d2af25aed017696dfb Mon Sep 17 00:00:00 2001 From: WarstekHUN Date: Thu, 21 Dec 2023 02:33:45 +0100 Subject: [PATCH 3/8] Typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6076597..f2c86e1 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@

Looking for the zilaws-server package?

-

ZilaWS can estabilish WS connection to a non zilaws server, but won't work as expected.

+

ZilaWS can establish WS connection to a non zilaws server, but won't work as expected.

Waiter example From 0c9e1644df3bc12638cffa3a7a0fed607ea1362b Mon Sep 17 00:00:00 2001 From: WarstekHUN Date: Thu, 21 Dec 2023 13:49:06 +0100 Subject: [PATCH 4/8] Browser testing is done --- .coverage-badges/badge-lines.svg | 2 +- .coverage-badges/badge-statements.svg | 2 +- src/index.ts | 24 +++++++++++++++++------- test/index.test.ts | 4 ++-- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/.coverage-badges/badge-lines.svg b/.coverage-badges/badge-lines.svg index 5c716cf..61420d0 100644 --- a/.coverage-badges/badge-lines.svg +++ b/.coverage-badges/badge-lines.svg @@ -1 +1 @@ -Coverage:lines: 97.54%Coverage:lines97.54% \ No newline at end of file +Coverage:lines: 97.45%Coverage:lines97.45% \ No newline at end of file diff --git a/.coverage-badges/badge-statements.svg b/.coverage-badges/badge-statements.svg index 6b0f0fc..76595ff 100644 --- a/.coverage-badges/badge-statements.svg +++ b/.coverage-badges/badge-statements.svg @@ -1 +1 @@ -Coverage:statements: 97.69%Coverage:statements97.69% \ No newline at end of file +Coverage:statements: 97.61%Coverage:statements97.61% \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 2bac405..c1191a3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -111,13 +111,24 @@ export class ZilaConnection { /* istanbul ignore next */ if (typeof window !== "undefined" && typeof window.document !== "undefined") { ws = new window.WebSocket(wsUrl); + ws.onerror = (ev) => { + console.error(JSON.stringify(ev)); + errorCallback?.call(ev.type); + console.error("Disconnected from WebSocket server."); + }; } else { ws = new WebSocket(wsUrl, { rejectUnauthorized: !allowSelfSignedCert, headers: { - "s-type": 1 - } + "s-type": 1, + }, }); + + ws.onerror = (ev) => { + console.error(JSON.stringify(ev)); + errorCallback?.call(ev.message); + console.error("Disconnected from WebSocket server."); + }; } } catch (error) { const errorMessage = (error as Error).stack?.split("\n")[0]; @@ -142,13 +153,13 @@ export class ZilaConnection { this.errorCallback = errorCallback; this._status = WSStatus.OPENING; - this.connection.onerror = async () => { + /*this.connection.onerror = async () => { this.status = WSStatus.ERROR; this.errorCallback?.call(undefined); - console.error("Disconnected from WebSocket server."); - }; + + };*/ this.connection.onopen = () => { this.status = WSStatus.OPEN; @@ -183,9 +194,9 @@ export class ZilaConnection { const msgObj: WSMessage = JSON.parse(msg); + /* istanbul ignore next */ if (msgObj.identifier[0] == "@") { if (msgObj.identifier == "@SetCookie") { - /* istanbul ignore next */ if (typeof window !== "undefined" && typeof window.document !== "undefined") { const cookieString = msgObj.message as unknown as string; document.cookie = cookieString; @@ -196,7 +207,6 @@ export class ZilaConnection { } } } else if (msgObj.identifier == "@DelCookie") { - /* istanbul ignore next */ if (typeof window !== "undefined" && typeof window.document !== "undefined") { const cookieName = msgObj.message as unknown as string; document.cookie = `${cookieName}=; expires=${new Date(0)}; path=/;`; diff --git a/test/index.test.ts b/test/index.test.ts index 337f68b..cd11789 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -85,7 +85,7 @@ describe("WebSocket connection", () => { clientSocket.setCookie({ name: "MyCookie", value: "ExampleValue", - path: "/" + path: "/", }); }); @@ -194,4 +194,4 @@ describe("WebSocket connection", () => { await client.disconnectAsync(); await server.stopServerAsync(); }); -}); \ No newline at end of file +}); From 56a66876fe24cc15ca8a9d791a509f67fab64b72 Mon Sep 17 00:00:00 2001 From: WarstekHUN Date: Fri, 22 Dec 2023 14:00:51 +0100 Subject: [PATCH 5/8] Cookie system is manually tested from now Had to ignore the cookie system from coverage testing because the testing environment lacks browser testing capabilities. If you are interested in creating such environment, please open an issue and we'll figure something out. --- package-lock.json | 56 ++++++++++++++++++------------------- package.json | 1 + src/index.ts | 70 +++++++++++++++++++++++++++++----------------- test/index.test.ts | 27 ------------------ 4 files changed, 73 insertions(+), 81 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3d00e9f..6691dd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1059,15 +1059,15 @@ } }, "node_modules/@jest/environment": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.4.tgz", - "integrity": "sha512-sQ0SULEjA1XUTHmkBRl7A1dyITM9yb1yb3ZNKPX3KlTd6IG7mWUe3e2yfExtC2Zz1Q+mMckOLHmL/qLiuQJrBQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.6.4", + "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.3" + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -1099,17 +1099,17 @@ } }, "node_modules/@jest/fake-timers": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.4.tgz", - "integrity": "sha512-6UkCwzoBK60edXIIWb0/KWkuj7R7Qq91vVInOe3De6DSpaEiqjKcJw4F7XUet24Wupahj9J6PlR09JqJ5ySDHw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "dependencies": { "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.6.3", - "jest-mock": "^29.6.3", - "jest-util": "^29.6.3" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4389,9 +4389,9 @@ } }, "node_modules/jest-message-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.3.tgz", - "integrity": "sha512-FtzaEEHzjDpQp51HX4UMkPZjy46ati4T5pEMyM6Ik48ztu4T9LQplZ6OsimHx7EuM9dfEh5HJa6D3trEftu3dA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", @@ -4400,7 +4400,7 @@ "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.6.3", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -4409,14 +4409,14 @@ } }, "node_modules/jest-mock": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.3.tgz", - "integrity": "sha512-Z7Gs/mOyTSR4yPsaZ72a/MtuK6RnC3JYqWONe48oLaoEcYwEDxqvbXz85G4SJrm2Z5Ar9zp6MiHF4AlFlRM4Pg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.6.3" + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4633,9 +4633,9 @@ } }, "node_modules/jest-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.3.tgz", - "integrity": "sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "dependencies": { "@jest/types": "^29.6.3", @@ -5329,9 +5329,9 @@ } }, "node_modules/pretty-format": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.3.tgz", - "integrity": "sha512-ZsBgjVhFAj5KeK+nHfF1305/By3lechHQSMWCTl8iHSbfOm2TN5nHEtFc/+W7fAyUeCs2n5iow72gld4gW0xDw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { "@jest/schemas": "^29.6.3", @@ -5384,9 +5384,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" diff --git a/package.json b/package.json index ccc6335..3b179af 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "browser": "dist/umd/index.js", "scripts": { "build": "npm run format:fix && npm run test:cov-build && npm run format:fix && npm run build:cjs && npm run build:esm && npm run build:umd && npm run build:types", + "forcebuild": "npm run format:fix && npm run build:cjs && npm run build:esm && npm run build:umd && npm run build:types", "build:cjs": "rimraf ./dist/cjs && tsc -p config/tsconfig.cjs.json", "build:esm": "rimraf ./dist/esm && tsc -p config/tsconfig.esm.json", "build:umd": "rimraf ./dist/umd && webpack --config config/webpack.config.js", diff --git a/src/index.ts b/src/index.ts index c1191a3..2a917e8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,8 +9,6 @@ import { WebSocket } from "ws"; import { v4 as randomUUID } from "uuid"; import { CloseCodes } from "./CloseCodes"; -let errorHappened = false; - type errorCallbackType = (reason?: string) => void; type ZilaWSCallback = (...args: any[]) => any; @@ -24,7 +22,7 @@ export enum WSStatus { interface WSMessage { identifier: string; - message: any[] | null; + message: any[] | any | null; callbackId: string | null; } @@ -121,7 +119,7 @@ export class ZilaConnection { rejectUnauthorized: !allowSelfSignedCert, headers: { "s-type": 1, - }, + } }); ws.onerror = (ev) => { @@ -237,23 +235,45 @@ export class ZilaConnection { } } + /** + * Returns a JSON serialized message object. + * @param identifier + * @param data + * @param callbackId + * @param isBuiltIn + * @returns + */ + private getMessageJSON( + identifier: string, + data: any[] | null, + callbackId: string | null, + isBuiltIn: boolean = false + ): string { + /* istanbul ignore next */ + return JSON.stringify({ + identifier: isBuiltIn ? identifier : "@" + identifier, + message: data, + callbackId: callbackId, + }); + } + + /** + * Send function for built-in systems + * @param {string} identifier The callback's name on the serverside. + * @param {any|undefined} data Arguments that shall be passed to the callback as parameters (optional) + */ + /* istanbul ignore next */ + private bSend(identifier: string, ...data: any[]) { + this.connection!.send(this.getMessageJSON(identifier, data, null, true)); + } + /** * Calls an eventhandler on the serverside. * @param {string} identifier The callback's name on the serverside. * @param {any|undefined} data Arguments that shall be passed to the callback as parameters (optional) */ public send(identifier: string, ...data: any[]): void { - if (typeof data == "function" || data.filter((el) => typeof el == "function").length > 0) { - throw new Error("Passing functions to the server is prohibited."); - } - - const msg: WSMessage = { - callbackId: null, - message: data, - identifier: identifier, - }; - - this.connection!.send(JSON.stringify(msg)); + this.connection!.send(this.getMessageJSON(identifier, data, null)); } /** @@ -264,26 +284,24 @@ export class ZilaConnection { */ public async waiter(identifier: string, ...data: any[]): Promise { return new Promise((resolve) => { - if (typeof data == "function" || data.filter((el) => typeof el == "function").length > 0) { - throw new Error("Passing functions to the server is prohibited."); - } - const uuid = randomUUID(); this.onceMessageHandler(uuid, (args: any): void => { resolve(args); }); - const msg: WSMessage = { - callbackId: uuid, - message: data, - identifier: identifier, - }; - - this.connection!.send(JSON.stringify(msg)); + this.connection!.send(this.getMessageJSON(identifier, data, uuid)); }); } + /** + * Sync cookies to the serverside. + */ + /* istanbul ignore next */ + public syncCookies() { + this.bSend("SyncCookies", document.cookie); + } + /** * Registers a new EventListener. * diff --git a/test/index.test.ts b/test/index.test.ts index cd11789..cf93074 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -77,33 +77,6 @@ describe("WebSocket connection", () => { server.send(clientSocket, "THISSHOULDNOTEXIST", "SMTH"); }); - test("Recieving cookies", () => { - client.onceEventListener("onCookieSet", (cookieStr) => { - expect(cookieStr).toEqual("MyCookie=ExampleValue; Path=/"); - }); - - clientSocket.setCookie({ - name: "MyCookie", - value: "ExampleValue", - path: "/", - }); - }); - - test("Cookie deletion", () => { - client.onceEventListener("onCookieDelete", (cookieName) => { - expect(cookieName).toEqual("MyCookie"); - }); - - clientSocket.removeCookie("MyCookie"); - }); - - test.failing("Client-Server but with a function", () => { - server.setMessageHandler("Client-Server", (socket, obj: { smth: any }) => {}); - client.send("Client-Server", () => { - console.log("I'm a function!"); - }); - }); - test.failing("Waiter but with a function", async () => { await client.waiter("SMTH", () => { console.log("I'm a function!"); From 3fb2a9310b692d9b8c8421eebf761123aa8052f4 Mon Sep 17 00:00:00 2001 From: WarstekHUN Date: Sat, 23 Dec 2023 13:21:08 +0100 Subject: [PATCH 6/8] Removed some comments --- CHANGELOG.md | 2 ++ src/index.ts | 18 +----------------- test/index.test.ts | 6 ------ 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb12f5b..ed52e49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,3 +4,5 @@ - New local events: - onCookieSet - onCookieDelete + - Cookie syncing: `syncCookies` + \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 2a917e8..9c08371 100644 --- a/src/index.ts +++ b/src/index.ts @@ -151,14 +151,6 @@ export class ZilaConnection { this.errorCallback = errorCallback; this._status = WSStatus.OPENING; - /*this.connection.onerror = async () => { - this.status = WSStatus.ERROR; - - this.errorCallback?.call(undefined); - - - };*/ - this.connection.onopen = () => { this.status = WSStatus.OPEN; }; @@ -388,10 +380,7 @@ export class ZilaConnection { public onceMessageHandler(identifier: string, callback: ZilaWSCallback): void { this.callbacks[identifier] = async (...args: any[]) => { this.removeMessageHandler(identifier); - //const ret = callback(...args); - const ret = await Promise.resolve(callback(...args)); - return ret; }; } @@ -452,9 +441,4 @@ export class ZilaConnection { */ export async function connectTo(wsUrl: string, errorCallback?: errorCallbackType): Promise { return ZilaConnection.connectTo(wsUrl, errorCallback); -} -// const exporter = { -// connectTo: connectTo, -// WSStatus: WSStatus, -// ZilaConnection: ZilaConnection, -// }; +} \ No newline at end of file diff --git a/test/index.test.ts b/test/index.test.ts index cf93074..53024e1 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -77,12 +77,6 @@ describe("WebSocket connection", () => { server.send(clientSocket, "THISSHOULDNOTEXIST", "SMTH"); }); - test.failing("Waiter but with a function", async () => { - await client.waiter("SMTH", () => { - console.log("I'm a function!"); - }); - }); - test.failing("Multiple EventListeners with same credintals", () => { client.addEventListener("onStatusChange", func); client.addEventListener("onStatusChange", func); From aea00066eeb7a31bd8976dc6fd1a163000c81ebf Mon Sep 17 00:00:00 2001 From: WarstekHUN Date: Sat, 23 Dec 2023 18:17:38 +0100 Subject: [PATCH 7/8] Typo fixes --- CHANGELOG.md | 2 +- README.md | 2 +- package.json | 2 +- src/index.ts | 24 ++++++++++++------------ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed52e49..cb47ffd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # New Features -- The serverside (^1.2) can now set cookies. +- The server-side (^1.2) can now set cookies. - New local events: - onCookieSet - onCookieDelete diff --git a/README.md b/README.md index f2c86e1..719f0fc 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # ZilaWS Client -### ZilaWS is a blazingly fast and very lightweight library that provides an extremely easy-to-use way to transmit data via websockets between clientside and serverside using eventhandlers and async waiters. +### ZilaWS is a blazingly fast and very lightweight library that provides an extremely easy-to-use way to transmit data via websockets between client-side and server-side using eventhandlers and async waiters.
diff --git a/package.json b/package.json index 3b179af..5a3bd84 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "$schema": "https://json.schemastore.org/package", "name": "zilaws-client", "version": "1.1.3", - "description": "ZilaWS is a blazingly fast and very lightweight library that provides an extremely easy-to-use way to transmit data via websockets between clientside and serverside using eventhandlers and async waiters.", + "description": "ZilaWS is a blazingly fast and very lightweight library that provides an extremely easy-to-use way to transmit data via websockets between client-side and server-side using eventhandlers and async waiters.", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", "umd:main": "dist/umd/index.js", diff --git a/src/index.ts b/src/index.ts index 9c08371..55316bf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -119,7 +119,7 @@ export class ZilaConnection { rejectUnauthorized: !allowSelfSignedCert, headers: { "s-type": 1, - } + }, }); ws.onerror = (ev) => { @@ -251,7 +251,7 @@ export class ZilaConnection { /** * Send function for built-in systems - * @param {string} identifier The callback's name on the serverside. + * @param {string} identifier The callback's name on the server-side. * @param {any|undefined} data Arguments that shall be passed to the callback as parameters (optional) */ /* istanbul ignore next */ @@ -260,8 +260,8 @@ export class ZilaConnection { } /** - * Calls an eventhandler on the serverside. - * @param {string} identifier The callback's name on the serverside. + * Calls an eventhandler on the server-side. + * @param {string} identifier The callback's name on the server-side. * @param {any|undefined} data Arguments that shall be passed to the callback as parameters (optional) */ public send(identifier: string, ...data: any[]): void { @@ -269,8 +269,8 @@ export class ZilaConnection { } /** - * Calls an async callback on the serverside. Gets a value back from the serverside or just waits for the eventhandler to finish. - * @param {string} identifier The callback's name on the serverside. + * Calls an async callback on the server-side. Gets a value back from the server-side or just waits for the eventhandler to finish. + * @param {string} identifier The callback's name on the server-side. * @param {any|undefined} data Arguments that shall be passed to the callback as parameters (optional) * @returns {Promise} */ @@ -287,7 +287,7 @@ export class ZilaConnection { } /** - * Sync cookies to the serverside. + * Sync cookies to the server-side. */ /* istanbul ignore next */ public syncCookies() { @@ -299,7 +299,7 @@ export class ZilaConnection { * * EventListeners are made for local events only like for example: `onStatusChanged` that runs when the WebSocket client's connection status gets changed. * - * IF YOU WANT TO REGISTER A **MessageHandler**, THAT RUNS WHEN THE **SERVERSIDE** ASKS FOR IT, YOU **SHOULD** USE `registerMessageHandler` + * IF YOU WANT TO REGISTER A **MessageHandler**, THAT RUNS WHEN THE **server-side** ASKS FOR IT, YOU **SHOULD** USE `registerMessageHandler` * @param eventType * @param callback */ @@ -339,7 +339,7 @@ export class ZilaConnection { /** * Registers an EventListener that can be called only once. * - * If you want to register a MessageListener (what is called by serverside) only once you should use `onceMessageHandler` + * If you want to register a MessageListener (what is called by server-side) only once you should use `onceMessageHandler` * @param eventType * @param callback */ @@ -355,7 +355,7 @@ export class ZilaConnection { } /** - * Registers an eventhandler on the clientside that'll run when the server asks for it. + * Registers an eventhandler on the client-side that'll run when the server asks for it. * Can get overrided with using the same identifier. * @param identifier The eventhandler's name. **Must not start with `[ZilaWS]:`!** * @param callback The eventhandler. @@ -365,7 +365,7 @@ export class ZilaConnection { } /** - * Removes a clientside MessageHandler. + * Removes a client-side MessageHandler. * @param identifier */ public removeMessageHandler(identifier: string): void { @@ -441,4 +441,4 @@ export class ZilaConnection { */ export async function connectTo(wsUrl: string, errorCallback?: errorCallbackType): Promise { return ZilaConnection.connectTo(wsUrl, errorCallback); -} \ No newline at end of file +} From 670655657e20fe3eb0f07a8e4bd491af1cbb18a8 Mon Sep 17 00:00:00 2001 From: WarstekHUN Date: Sat, 23 Dec 2023 18:29:56 +0100 Subject: [PATCH 8/8] Timeout for waiters --- CHANGELOG.md | 4 ++++ src/index.ts | 60 ++++++++++++++++++++++++++++++++++++++++++---- test/index.test.ts | 17 +++++++++++++ 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb47ffd..7f2d8f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # New Features +- Timeout for waiters + - Set the timeout with `client.maxWaiterTime` + - `waiterTimeout` function with a max waiting time parameter + - The server-side (^1.2) can now set cookies. - New local events: - onCookieSet diff --git a/src/index.ts b/src/index.ts index 55316bf..e533066 100644 --- a/src/index.ts +++ b/src/index.ts @@ -71,6 +71,7 @@ export class ZilaConnection { private connection: WebSocket | globalThis.WebSocket | undefined; private errorCallback: errorCallbackType | undefined; private _status: WSStatus = WSStatus.OPENING; + public maxWaiterTime: number = 1200; public get status(): WSStatus { return this._status; @@ -274,18 +275,67 @@ export class ZilaConnection { * @param {any|undefined} data Arguments that shall be passed to the callback as parameters (optional) * @returns {Promise} */ - public async waiter(identifier: string, ...data: any[]): Promise { - return new Promise((resolve) => { + public async waiter(identifier: string, ...data: any[]): Promise { + return new Promise(async (resolve) => { const uuid = randomUUID(); - this.onceMessageHandler(uuid, (args: any): void => { - resolve(args); - }); + let timeout: NodeJS.Timeout; + + resolve( + Promise.any([ + new Promise(r => { + this.setMessageHandler(uuid, (args: any[]): void => { + clearTimeout(timeout); + this.removeMessageHandler(uuid); + r(args); + }); + }), + new Promise((_r) => { + timeout = setTimeout(() => { + _r(undefined); + }, this.maxWaiterTime); + }) + ]) as Promise + ); this.connection!.send(this.getMessageJSON(identifier, data, uuid)); }); } + /** + * Calls an eventhandler on the server-side for the specified client. Gets a value of T type back from the client or just waits for the eventhandler to finish. + * @param {string} identifier The callback's name on the client-side. + * @param {number} maxWaitingTime The maximum time this waiter will wait for the client. + * @param {any|undefined} data Arguments that shall be passed to the callback as parameters (optional) + * @returns {Promise} + */ + public waiterTimeout(identifier: string, maxWaitingTime: number, ...data: any[]): Promise { + return new Promise(async (resolve) => { + const uuid = randomUUID(); + + let timeout: NodeJS.Timeout; + + resolve( + Promise.any([ + new Promise(r => { + this.setMessageHandler(uuid, (args: any[]): void => { + clearTimeout(timeout); + this.removeMessageHandler(uuid); + r(args); + }); + }), + new Promise((_r) => { + timeout = setTimeout(() => { + _r(undefined); + }, maxWaitingTime); + }) + ]) as Promise + ); + + this.connection!.send(this.getMessageJSON(identifier, data, uuid)); + }); + } + /** * Sync cookies to the server-side. */ diff --git a/test/index.test.ts b/test/index.test.ts index 53024e1..bd1f13e 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -77,6 +77,23 @@ describe("WebSocket connection", () => { server.send(clientSocket, "THISSHOULDNOTEXIST", "SMTH"); }); + test("Client Async Waiter but no response", async () => { + expect(await client.waiter("This doesn't exist", "sampleData")).toBe(undefined); + }); + + test("Client Async WaiterTimeout", async () => { + server.setMessageHandler("WaiterTimeout", (socket, data: string) => { + expect(data).toEqual("sampleData") + return data + " success"; + }); + + expect(await client.waiterTimeout("WaiterTimeout", 80, "sampleData")).toBe("sampleData success"); + }); + + test("Client Async WaiterTimeout but no response", async () => { + expect(await client.waiterTimeout("This doesn't exist", 80, "sampleData")).toBe(undefined); + }); + test.failing("Multiple EventListeners with same credintals", () => { client.addEventListener("onStatusChange", func); client.addEventListener("onStatusChange", func);