diff --git a/package-lock.json b/package-lock.json index 99846ac..d1896a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -134,6 +134,11 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -494,6 +499,14 @@ } } }, + "express-ws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/express-ws/-/express-ws-4.0.0.tgz", + "integrity": "sha512-KEyUw8AwRET2iFjFsI1EJQrJ/fHeGiJtgpYgEWG3yDv4l/To/m3a2GaYfeGyB3lsWdvbesjF5XCMx+SVBgAAYw==", + "requires": { + "ws": "^5.2.0" + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -1555,6 +1568,14 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, "xpc-connection": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/xpc-connection/-/xpc-connection-0.1.4.tgz", diff --git a/package.json b/package.json index 915a3ef..84e6f50 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "license": "ISC", "dependencies": { "express": "^4.17.1", + "express-ws": "^4.0.0", "iconsole-bike-client": "^0.1.3", "sqlite3": "^4.1.0", "underscore": "^1.9.1" diff --git a/src/api/workout.js b/src/api/workout.js index c0a19ed..83a86a7 100644 --- a/src/api/workout.js +++ b/src/api/workout.js @@ -174,5 +174,45 @@ module.exports = function workoutRouter(repo) { } }); + router.ws("/:id/subscribe", (ws, req) => { + console.log("HELLO!") + + const workout = workouts.find(w => w.id === req.params.id); + if (workout == null) { + ws.send(JSON.stringify({error: "workout not found"})); + ws.close(); + } + + workout.listMeasurements().then((list) => { + ws.send(JSON.stringify({workoutStatusBackfill: list})); + }).catch(err => { + ws.send(JSON.stringify({error: `could not list measurements: ${err.message || err}`})); + ws.close(); + }); + + const handler = (workotuStatus) => { + workotuStatus = {...workotuStatus}; + delete workotuStatus.id; + + ws.send(JSON.stringify({workotuStatus})) + } + + workout.events.on("workoutStatus", handler); + + ws.onclose = () => { + workout.events.removeListener("workoutStatus", handler); + ws.removeAllListeners(); + }; + + ws.send(JSON.stringify({ + workout: { + id: workout.id, + bike: workout.bike, + program: workout.program, + date: workout.date, + }, + })); + }) + return router; } \ No newline at end of file diff --git a/src/server.js b/src/server.js index 1c4ee9b..439c4e4 100644 --- a/src/server.js +++ b/src/server.js @@ -1,4 +1,6 @@ -const express = require('express'); +const express = require("express"); +const expressWs = require("express-ws"); + const SQLite3Repository = require("./repositories/sqlite3"); const repo = new SQLite3Repository("stuff.db"); @@ -11,6 +13,7 @@ repo.setup().catch(err => { }); const app = express(); +expressWs(app); app.use(express.json({strict: false})); diff --git a/src/systems/workout.js b/src/systems/workout.js index dfcd29e..42dc93c 100644 --- a/src/systems/workout.js +++ b/src/systems/workout.js @@ -85,7 +85,7 @@ class Workout { this.repo.insertMeasurement({...ws, workoutId: this.id}); - this.events.emit("workoutStatus", ws); + this.events.emit("workoutStatus", {...ws}); } /** @@ -95,7 +95,14 @@ class Workout { */ static async create(repo, bikeId, programId) { const bike = await repo.findBike(bikeId); + if (bike == null) { + throw new Error("bike not found"); + } const program = await repo.findProgram(programId); + if (program == null) { + throw new Error("program not found"); + } + const date = new Date(); const id = await repo.insertWorkout({ bikeId: bike.id, @@ -115,7 +122,7 @@ class Workout { const bike = await repo.findBike(data.bikeId); const program = await repo.findWorkout(data.workoutId); - const workout = new Workout(repo, parseInt(id), bike, program, new Date(data.date)); + const workout = new Workout(repo, id, bike, program, new Date(data.date)); const list = await repo.listMeasurements(id); if (list.length > 0) {