diff --git a/Dockerfile b/Dockerfile index d28f856..4eec03d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -64,7 +64,7 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:4000/health || exit 1 # Expose port -EXPOSE 4000 +EXPOSE ${PORT:-4000} # Start the application with optimized flags CMD ["bun", "--smol", "run", "start"] \ No newline at end of file diff --git a/src/api/routes.ts b/src/api/routes.ts index 5defc13..dcc1628 100644 --- a/src/api/routes.ts +++ b/src/api/routes.ts @@ -115,7 +115,7 @@ router.get("/subscribe_events", middleware.wsRateLimiter, (req, res) => { res.writeHead(200, { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", - Connection: "keep-alive", + "Connection": "keep-alive", "Access-Control-Allow-Origin": "*", }); diff --git a/src/config/app.config.ts b/src/config/app.config.ts index b125125..1a1ef7d 100644 --- a/src/config/app.config.ts +++ b/src/config/app.config.ts @@ -12,7 +12,7 @@ export const AppConfigSchema = z.object({ .default("development"), /** Home Assistant Configuration */ - HASS_HOST: z.string().default("http://192.168.178.63:8123"), + HASS_HOST: z.string().default("http://homeassistant.local:8123"), HASS_TOKEN: z.string().optional(), /** Speech Features Configuration */ @@ -31,7 +31,7 @@ export const AppConfigSchema = z.object({ }), /** Security Configuration */ - JWT_SECRET: z.string().default("your-secret-key"), + JWT_SECRET: z.string().default("your-secret-key-must-be-32-char-min"), RATE_LIMIT: z.object({ /** Time window for rate limiting in milliseconds */ windowMs: z.number().default(15 * 60 * 1000), // 15 minutes diff --git a/src/config/boilerplate.config.ts b/src/config/boilerplate.config.ts deleted file mode 100644 index e1c9cda..0000000 --- a/src/config/boilerplate.config.ts +++ /dev/null @@ -1,35 +0,0 @@ -export const BOILERPLATE_CONFIG = { - configuration: { - LOG_LEVEL: { - type: "string" as const, - default: "debug", - description: "Logging level", - enum: ["error", "warn", "info", "debug", "trace"], - }, - CACHE_DIRECTORY: { - type: "string" as const, - default: ".cache", - description: "Directory for cache files", - }, - CONFIG_DIRECTORY: { - type: "string" as const, - default: ".config", - description: "Directory for configuration files", - }, - DATA_DIRECTORY: { - type: "string" as const, - default: ".data", - description: "Directory for data files", - }, - }, - internal: { - boilerplate: { - configuration: { - LOG_LEVEL: "debug", - CACHE_DIRECTORY: ".cache", - CONFIG_DIRECTORY: ".config", - DATA_DIRECTORY: ".data", - }, - }, - }, -}; diff --git a/test/setup.ts b/test/setup.ts deleted file mode 100644 index 6b223aa..0000000 --- a/test/setup.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { afterEach, mock, expect } from "bun:test"; - -// Setup global mocks -global.fetch = mock(() => Promise.resolve(new Response())); - -// Mock WebSocket -class MockWebSocket { - static CONNECTING = 0; - static OPEN = 1; - static CLOSING = 2; - static CLOSED = 3; - - url: string; - readyState: number = MockWebSocket.CLOSED; - onopen: ((event: any) => void) | null = null; - onclose: ((event: any) => void) | null = null; - onmessage: ((event: any) => void) | null = null; - onerror: ((event: any) => void) | null = null; - - constructor(url: string) { - this.url = url; - setTimeout(() => { - this.readyState = MockWebSocket.OPEN; - this.onopen?.({ type: 'open' }); - }, 0); - } - - send = mock((data: string) => { - if (this.readyState !== MockWebSocket.OPEN) { - throw new Error('WebSocket is not open'); - } - }); - - close = mock(() => { - this.readyState = MockWebSocket.CLOSED; - this.onclose?.({ type: 'close', code: 1000, reason: '', wasClean: true }); - }); -} - -// Add WebSocket to global -(global as any).WebSocket = MockWebSocket; - -// Reset all mocks after each test -afterEach(() => { - mock.restore(); -}); - -// Add custom matchers -expect.extend({ - toBeValidResponse(received: Response) { - const pass = received instanceof Response && received.ok; - return { - message: () => - `expected ${received instanceof Response ? 'Response' : typeof received} to${pass ? ' not' : ''} be a valid Response`, - pass - }; - }, - toBeValidWebSocket(received: any) { - const pass = received instanceof MockWebSocket; - return { - message: () => - `expected ${received instanceof MockWebSocket ? 'MockWebSocket' : typeof received} to${pass ? ' not' : ''} be a valid WebSocket`, - pass - }; - } -}); \ No newline at end of file