sse => ws
This commit is contained in:
145
package-lock.json
generated
145
package-lock.json
generated
@@ -13,6 +13,7 @@
|
|||||||
"@fastify/sse": "^0.4.0",
|
"@fastify/sse": "^0.4.0",
|
||||||
"@fastify/swagger": "^9.6.1",
|
"@fastify/swagger": "^9.6.1",
|
||||||
"@fastify/swagger-ui": "^5.2.3",
|
"@fastify/swagger-ui": "^5.2.3",
|
||||||
|
"@fastify/websocket": "^11.2.0",
|
||||||
"dotenv": "^17.2.2",
|
"dotenv": "^17.2.2",
|
||||||
"fastify": "^5.6.2",
|
"fastify": "^5.6.2",
|
||||||
"fastify-axios": "^1.3.0",
|
"fastify-axios": "^1.3.0",
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^24.10.1",
|
"@types/node": "^24.10.1",
|
||||||
|
"@types/ws": "^8.18.1",
|
||||||
"tsx": "^4.20.6",
|
"tsx": "^4.20.6",
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
}
|
}
|
||||||
@@ -736,6 +738,27 @@
|
|||||||
"yaml": "^2.4.1"
|
"yaml": "^2.4.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@fastify/websocket": {
|
||||||
|
"version": "11.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fastify/websocket/-/websocket-11.2.0.tgz",
|
||||||
|
"integrity": "sha512-3HrDPbAG1CzUCqnslgJxppvzaAZffieOVbLp1DAy1huCSynUWPifSvfdEDUR8HlJLp3sp1A36uOM2tJogADS8w==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fastify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/fastify"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"duplexify": "^4.1.3",
|
||||||
|
"fastify-plugin": "^5.0.0",
|
||||||
|
"ws": "^8.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@isaacs/balanced-match": {
|
"node_modules/@isaacs/balanced-match": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
||||||
@@ -782,6 +805,16 @@
|
|||||||
"undici-types": "~7.16.0"
|
"undici-types": "~7.16.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ws": {
|
||||||
|
"version": "8.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||||
|
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/abstract-logging": {
|
"node_modules/abstract-logging": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz",
|
||||||
@@ -990,6 +1023,27 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/duplexify": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"end-of-stream": "^1.4.1",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^3.1.1",
|
||||||
|
"stream-shift": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/end-of-stream": {
|
||||||
|
"version": "1.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
||||||
|
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/es-define-property": {
|
"node_modules/es-define-property": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
@@ -1630,6 +1684,15 @@
|
|||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/openapi-types": {
|
"node_modules/openapi-types": {
|
||||||
"version": "12.1.3",
|
"version": "12.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
|
||||||
@@ -1724,6 +1787,20 @@
|
|||||||
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==",
|
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/readable-stream": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/real-require": {
|
"node_modules/real-require": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
|
||||||
@@ -1796,6 +1873,26 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/safe-regex2": {
|
"node_modules/safe-regex2": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-5.0.0.tgz",
|
||||||
@@ -1891,6 +1988,21 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/stream-shift": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/string_decoder": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/swagger-themes": {
|
"node_modules/swagger-themes": {
|
||||||
"version": "1.4.3",
|
"version": "1.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/swagger-themes/-/swagger-themes-1.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/swagger-themes/-/swagger-themes-1.4.3.tgz",
|
||||||
@@ -1968,6 +2080,39 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
|
||||||
|
"integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": ">=5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/yaml": {
|
"node_modules/yaml": {
|
||||||
"version": "2.8.2",
|
"version": "2.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
|
||||||
|
|||||||
63
package.json
63
package.json
@@ -1,33 +1,34 @@
|
|||||||
{
|
{
|
||||||
"name": "@dpu/api",
|
"name": "@dpu/api",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
"build": "npm run clean && tsc",
|
"build": "npm run clean && tsc",
|
||||||
"start": "node dist/index.js",
|
"start": "node dist/index.js",
|
||||||
"dev": "tsx watch src/index.ts"
|
"dev": "tsx watch src/index.ts"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "Darius",
|
"author": "Darius",
|
||||||
"license": "",
|
"license": "",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dpu/shared": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git",
|
"@dpu/shared": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git",
|
||||||
"@fastify/cors": "^11.2.0",
|
"@fastify/cors": "^11.2.0",
|
||||||
"@fastify/sse": "^0.4.0",
|
"@fastify/swagger": "^9.6.1",
|
||||||
"@fastify/swagger": "^9.6.1",
|
"@fastify/swagger-ui": "^5.2.3",
|
||||||
"@fastify/swagger-ui": "^5.2.3",
|
"@fastify/websocket": "^11.2.0",
|
||||||
"dotenv": "^17.2.2",
|
"dotenv": "^17.2.2",
|
||||||
"fastify": "^5.6.2",
|
"fastify": "^5.6.2",
|
||||||
"fastify-axios": "^1.3.0",
|
"fastify-axios": "^1.3.0",
|
||||||
"fastify-type-provider-zod": "^6.1.0",
|
"fastify-type-provider-zod": "^6.1.0",
|
||||||
"swagger-themes": "^1.4.3",
|
"swagger-themes": "^1.4.3",
|
||||||
"zod": "^4.1.12"
|
"zod": "^4.1.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^24.10.1",
|
"@types/node": "^24.10.1",
|
||||||
"tsx": "^4.20.6",
|
"@types/ws": "^8.18.1",
|
||||||
"typescript": "^5.9.3"
|
"tsx": "^4.20.6",
|
||||||
}
|
"typescript": "^5.9.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ import { HomeAssistantService } from "./homeassistant/service.js";
|
|||||||
import { TidalClient } from "./tidal/client.js";
|
import { TidalClient } from "./tidal/client.js";
|
||||||
import { TidalService } from "./tidal/service.js";
|
import { TidalService } from "./tidal/service.js";
|
||||||
import { tidalRoutes } from "./tidal/routes.js";
|
import { tidalRoutes } from "./tidal/routes.js";
|
||||||
import { sseRoutes } from "./sse/routes.js";
|
import { sseRoutes } from "./websocket/routes.js";
|
||||||
import { SseService } from "@dpu/shared";
|
import { SseService } from "@dpu/shared";
|
||||||
import { HomepageService } from "./homepage/service.js";
|
import { HomepageService } from "./homepage/service.js";
|
||||||
import { homepageRoutes } from "./homepage/routes.js";
|
import { homepageRoutes } from "./homepage/routes.js";
|
||||||
import fastifySSE from "@fastify/sse";
|
|
||||||
import fastifyCors from "@fastify/cors";
|
import fastifyCors from "@fastify/cors";
|
||||||
|
import fastifyWebsocket from "@fastify/websocket";
|
||||||
|
|
||||||
const fastify = Fastify().withTypeProvider<ZodTypeProvider>();
|
const fastify = Fastify().withTypeProvider<ZodTypeProvider>();
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ await fastify.register(fastifyAxios, {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await fastify.register(fastifySSE);
|
await fastify.register(fastifyWebsocket);
|
||||||
|
|
||||||
const haClient = new HomeAssistantClient(fastify.axios.homeassistant);
|
const haClient = new HomeAssistantClient(fastify.axios.homeassistant);
|
||||||
const haService = new HomeAssistantService(haClient);
|
const haService = new HomeAssistantService(haClient);
|
||||||
|
|||||||
@@ -14,29 +14,26 @@ export async function sseRoutes(
|
|||||||
"/dpu/events",
|
"/dpu/events",
|
||||||
{
|
{
|
||||||
schema: {
|
schema: {
|
||||||
description: "Register for SSE",
|
description: "Register for WebSocket events",
|
||||||
tags: ["sse"],
|
tags: ["ws"],
|
||||||
hide: true,
|
hide: true,
|
||||||
},
|
},
|
||||||
sse: true,
|
websocket: true,
|
||||||
},
|
},
|
||||||
async (_request, reply) => {
|
(socket, _request) => {
|
||||||
reply.sse.keepAlive();
|
|
||||||
|
|
||||||
const clientId = randomUUID();
|
const clientId = randomUUID();
|
||||||
const sendEvent = (event: SseEvent) => {
|
const sendEvent = (event: SseEvent) => {
|
||||||
reply.sse.send({
|
if (socket.readyState === socket.OPEN) {
|
||||||
event: event.type,
|
socket.send(JSON.stringify({ event: event.type, data: event.data }));
|
||||||
data: JSON.stringify(event.data),
|
}
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
sseService.addClient({ id: clientId, send: sendEvent });
|
sseService.addClient({ id: clientId, send: sendEvent });
|
||||||
|
|
||||||
await reply.sse.send({ data: "Connected" });
|
socket.send(JSON.stringify({ event: "connected", data: "Connected" }));
|
||||||
logInfo(`Connection for client ${clientId} established`);
|
logInfo(`Connection for client ${clientId} established`);
|
||||||
|
|
||||||
reply.sse.onClose(() => {
|
socket.on("close", () => {
|
||||||
sseService.removeClient(clientId);
|
sseService.removeClient(clientId);
|
||||||
logInfo(`Connection for client ${clientId} closed`);
|
logInfo(`Connection for client ${clientId} closed`);
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user