From e1ef661a7a4a67823bf3d458262f6264f80eb6bd Mon Sep 17 00:00:00 2001 From: Darius Date: Fri, 6 Feb 2026 18:59:34 +0100 Subject: [PATCH] formatting and grist --- .env.example | 3 +- package-lock.json | 10 +++---- package.json | 2 +- src/config.ts | 16 +++++++---- src/grist/client.ts | 15 ++++++++++ src/grist/routes.ts | 39 ++++++++++++++++++++++++++ src/grist/service.ts | 53 ++++++++++++++++++++++++++++++++++++ src/homeassistant/service.ts | 4 +-- src/index.ts | 15 +++++++++- 9 files changed, 141 insertions(+), 16 deletions(-) create mode 100644 src/grist/client.ts create mode 100644 src/grist/routes.ts create mode 100644 src/grist/service.ts diff --git a/.env.example b/.env.example index 55c17e9..1747329 100644 --- a/.env.example +++ b/.env.example @@ -2,8 +2,7 @@ API_KEY=apiKey PORT= ENV_DEV=true -TIDAL_HOST=http://localhost -TIDAL_PORT=47836 +TIDAL_HOST=http://localhost:47836 HA_API_URL=http://homeassistant.com/api/states/ HA_API_TOKEN=Nina hätte hier jetzt ihr Token ausversehen stehen hihi diff --git a/package-lock.json b/package-lock.json index faeb1f1..f18c106 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,8 +28,8 @@ } }, "node_modules/@dpu/shared": { - "version": "1.7.1", - "resolved": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git#cd95b631746e3f5d50120c68f69b934cf7f8e87b", + "version": "1.8.1", + "resolved": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git#27dc6f2b1214b8e2aff65de510caea402c2f88db", "dependencies": { "@types/ws": "^8.18.1", "axios": "^1.7.9", @@ -1383,9 +1383,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.13.5", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.5.tgz", - "integrity": "sha512-v4/4xAEpBRp6SvCkWhnGCaLkJf9IwWzrsygJPxD/+p2/xPE3C5m2fA9FD0Ry9tG+Rqqq3gBzHSl6y1/T9V/tMQ==", + "version": "4.13.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", + "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 0fc72b9..bac2030 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "clean": "rimraf dist", "build": "npm run clean && tsc", "start": "node dist/index.js", - "dev": "tsx watch src/index.ts" + "dev": "tsx watch --inspect-brk src/index.ts" }, "keywords": [], "author": "Darius", diff --git a/src/config.ts b/src/config.ts index 22682c3..e254d71 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,18 +7,24 @@ export const Config = { port: process.env.PORT || "8080", env_dev: process.env.ENV_DEV || false, - tidal: { - host: process.env.TIDAL_HOST || "", - port: process.env.TIDAL_PORT || "", + grist: { + api_url: process.env.GRIST_API_URL || "", + api_token: process.env.GRIST_API_TOKEN || "", + + table_personal_goals_path: process.env.GRIST_TPG_PATH || "", }, homeassistant: { api_url: process.env.HA_API_URL || "", api_token: process.env.HA_API_TOKEN || "", - id_desk_sensor_binary: process.env.HA_DESK_SENSOR_BINARY || "", - id_room_sensors: process.env.HA_ROOMTEMP_SENSOR_IDS?.split(",") || [], + id_sensor_desk_binary: process.env.HA_SENSOR_DESK_BINARY || "", + id_sensors_roomtemp: process.env.HA_SENSORS_ROOMTEMP?.split(",") || [], id_webhook_stand: process.env.HA_STANDING_WEBHOOK || "", }, + + tidal: { + address: process.env.TIDAL_ADDRESS || "", + }, } as const; diff --git a/src/grist/client.ts b/src/grist/client.ts new file mode 100644 index 0000000..bfc85aa --- /dev/null +++ b/src/grist/client.ts @@ -0,0 +1,15 @@ +import { BaseClient } from "@dpu/shared"; +import { printNetworkError } from "@dpu/shared/dist/logger.js"; + +export class GristClient extends BaseClient { + async get(endpoint: string): Promise { + try { + const response = await this.getAxios().get(`${endpoint}`); + + return response.data; + } catch (error) { + printNetworkError(error); + throw error; + } + } +} diff --git a/src/grist/routes.ts b/src/grist/routes.ts new file mode 100644 index 0000000..a38c9e4 --- /dev/null +++ b/src/grist/routes.ts @@ -0,0 +1,39 @@ +import type { GristRecord_PersonalGoals } from "@dpu/shared"; +import type { FastifyInstance } from "fastify"; +import { z } from "zod"; +import type { GristService } from "./service"; + +export async function gristRoutes( + fastify: FastifyInstance, + { + gristService, + }: { + gristService: GristService; + }, +) { + fastify.get( + "/grist/today", + { + schema: { + description: "Get goals for today", + tags: ["grist"], + response: { + 200: z.custom(), + 418: z.object({ + error: z.string(), + }), + }, + }, + }, + async (_request, reply) => { + const service_result = await gristService.getToday(); + + if (!service_result.successful) { + reply.code(418); + return { error: service_result.result }; + } + + return service_result.result; + }, + ); +} diff --git a/src/grist/service.ts b/src/grist/service.ts new file mode 100644 index 0000000..7c7c90a --- /dev/null +++ b/src/grist/service.ts @@ -0,0 +1,53 @@ +import { + BaseService, + type GristRecord_PersonalGoals, + logWarning, + type ServiceResult, +} from "@dpu/shared"; +import { Config } from "../config.js"; +import type { GristClient } from "./client.js"; + +export class GristService extends BaseService { + async getToday(): Promise> { + try { + const filter_string = encodeURIComponent( + `{ "id": [${this.getTodayAsId()}]}`, + ); + const query = `${Config.grist.table_personal_goals_path}?filter=${filter_string}`; + + const response = + await this.getClient().get>(query); + + return this.getSuccessfulResult(this.transformToPersonalGoals(response)); + } catch { + const error_message = "error getting record from grist"; + logWarning(error_message); + return this.getErrorResult(error_message); + } + } + + getTodayAsId(date = new Date()) { + const start = new Date(date.getFullYear(), 0, 0); + const diff = date.getTime() - start.getTime(); + return Math.floor(diff / 86400000); + } + + transformToPersonalGoals( + obj: Record, + ): GristRecord_PersonalGoals { + return { + went_outside: (obj.went_outside as boolean) ?? false, + standing: (obj.standing as boolean) ?? false, + standing_goal: (obj.standing_goal as number) ?? 0, + steps: (obj.steps as boolean) ?? false, + steps_goal: (obj.steps_goal as number) ?? 0, + pushups: (obj.pushups as boolean) ?? false, + squats: (obj.squats as boolean) ?? false, + leg_raises: (obj.leg_raises as boolean) ?? false, + reps_goal: (obj.reps_goal as number) ?? 0, + stairs: (obj.stairs as boolean) ?? false, + stairs_goal: (obj.stairs_goal as number) ?? 0, + is_workday: (obj.WeekdayHelper as number) === 1, + }; + } +} diff --git a/src/homeassistant/service.ts b/src/homeassistant/service.ts index 9a934c8..6622644 100644 --- a/src/homeassistant/service.ts +++ b/src/homeassistant/service.ts @@ -48,7 +48,7 @@ export class HomeAssistantService extends BaseService { > { try { const raw = await this.getClient().getEntityState( - Config.homeassistant.id_desk_sensor_binary, + Config.homeassistant.id_sensor_desk_binary, ); const position = Number(raw.state); @@ -108,7 +108,7 @@ export class HomeAssistantService extends BaseService { private async getTemperatures(): Promise { try { return await this.getClient().getEntityStates( - Config.homeassistant.id_room_sensors, + Config.homeassistant.id_sensors_roomtemp, ); } catch (error) { logWarning("error getting temperatures:", error); diff --git a/src/index.ts b/src/index.ts index 229bd71..d9db248 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,6 +16,9 @@ import { import { SwaggerTheme, SwaggerThemeNameEnum } from "swagger-themes"; import { z } from "zod"; import { Config } from "./config.js"; +import { GristClient } from "./grist/client.js"; +import { gristRoutes } from "./grist/routes.js"; +import { GristService } from "./grist/service.js"; import { HomeAssistantClient } from "./homeassistant/client.js"; import { homeAssistantRoutes } from "./homeassistant/routes.js"; import { HomeAssistantService } from "./homeassistant/service.js"; @@ -69,6 +72,12 @@ await fastify.register(fastifySwaggerUi, { await fastify.register(fastifyAxios, { clients: { + grist: { + baseURL: Config.grist.api_url, + headers: { + Authorization: `Bearer ${Config.grist.api_token}`, + }, + }, homeassistant: { baseURL: Config.homeassistant.api_url, headers: { @@ -76,13 +85,16 @@ await fastify.register(fastifyAxios, { }, }, tidal: { - baseURL: `${Config.tidal.host}:${Config.tidal.port}`, + baseURL: `${Config.tidal.address}`, }, }, }); await fastify.register(fastifyWebsocket); +const gristClient = new GristClient(fastify.axios.grist); +const gristService = new GristService(gristClient); + const haClient = new HomeAssistantClient(fastify.axios.homeassistant); const haService = new HomeAssistantService(haClient); @@ -108,6 +120,7 @@ async function verifyAPIKey( const port = parseInt(Config.port, 10); // Register routes +await fastify.register(gristRoutes, { gristService }); await fastify.register(homeAssistantRoutes, { haService, verifyAPIKey }); await fastify.register(tidalRoutes, { tidalService, verifyAPIKey }); await fastify.register(wsRoutes, { wsService });