- Add comprehensive speech configuration in .env.example and app config - Update Docker speech Dockerfile for more flexible model handling - Create detailed README for speech-to-text examples - Implement example script demonstrating speech features - Improve speech service initialization and configuration management
139 lines
4.5 KiB
TypeScript
139 lines
4.5 KiB
TypeScript
import { config } from "dotenv";
|
|
import { resolve } from "path";
|
|
import { z } from "zod";
|
|
|
|
/**
|
|
* Load environment variables based on NODE_ENV
|
|
* Development: .env.development
|
|
* Test: .env.test
|
|
* Production: .env
|
|
*/
|
|
const envFile =
|
|
process.env.NODE_ENV === "production"
|
|
? ".env"
|
|
: process.env.NODE_ENV === "test"
|
|
? ".env.test"
|
|
: ".env.development";
|
|
|
|
console.log(`Loading environment from ${envFile}`);
|
|
config({ path: resolve(process.cwd(), envFile) });
|
|
|
|
/**
|
|
* Application configuration object
|
|
* Contains all configuration settings for the application
|
|
*/
|
|
export const AppConfigSchema = z.object({
|
|
/** Server Configuration */
|
|
PORT: z.number().default(4000),
|
|
NODE_ENV: z
|
|
.enum(["development", "production", "test"])
|
|
.default("development"),
|
|
|
|
/** Home Assistant Configuration */
|
|
HASS_HOST: z.string().default("http://192.168.178.63:8123"),
|
|
HASS_TOKEN: z.string().optional(),
|
|
|
|
/** Speech Features Configuration */
|
|
SPEECH: z.object({
|
|
ENABLED: z.boolean().default(false),
|
|
WAKE_WORD_ENABLED: z.boolean().default(false),
|
|
SPEECH_TO_TEXT_ENABLED: z.boolean().default(false),
|
|
WHISPER_MODEL_PATH: z.string().default("/models"),
|
|
WHISPER_MODEL_TYPE: z.string().default("base"),
|
|
}).default({
|
|
ENABLED: false,
|
|
WAKE_WORD_ENABLED: false,
|
|
SPEECH_TO_TEXT_ENABLED: false,
|
|
WHISPER_MODEL_PATH: "/models",
|
|
WHISPER_MODEL_TYPE: "base",
|
|
}),
|
|
|
|
/** Security Configuration */
|
|
JWT_SECRET: z.string().default("your-secret-key"),
|
|
RATE_LIMIT: z.object({
|
|
/** Time window for rate limiting in milliseconds */
|
|
windowMs: z.number().default(15 * 60 * 1000), // 15 minutes
|
|
/** Maximum number of requests per window */
|
|
max: z.number().default(100), // limit each IP to 100 requests per windowMs
|
|
}),
|
|
|
|
/** Server-Sent Events Configuration */
|
|
SSE: z.object({
|
|
/** Maximum number of concurrent SSE clients */
|
|
MAX_CLIENTS: z.number().default(1000),
|
|
/** Ping interval in milliseconds to keep connections alive */
|
|
PING_INTERVAL: z.number().default(30000), // 30 seconds
|
|
}),
|
|
|
|
/** Logging Configuration */
|
|
LOGGING: z.object({
|
|
/** Log level (error, warn, info, http, debug) */
|
|
LEVEL: z.enum(["error", "warn", "info", "debug", "trace"]).default("info"),
|
|
/** Directory for log files */
|
|
DIR: z.string().default("logs"),
|
|
/** Maximum log file size before rotation */
|
|
MAX_SIZE: z.string().default("20m"),
|
|
/** Maximum number of days to keep log files */
|
|
MAX_DAYS: z.string().default("14d"),
|
|
/** Whether to compress rotated logs */
|
|
COMPRESS: z.boolean().default(false),
|
|
/** Format for timestamps in logs */
|
|
TIMESTAMP_FORMAT: z.string().default("YYYY-MM-DD HH:mm:ss:ms"),
|
|
/** Whether to include request logging */
|
|
LOG_REQUESTS: z.boolean().default(false),
|
|
}),
|
|
|
|
/** Application Version */
|
|
VERSION: z.string().default("0.1.0"),
|
|
});
|
|
|
|
/** Type definition for the configuration object */
|
|
export type AppConfig = z.infer<typeof AppConfigSchema>;
|
|
|
|
/** Required environment variables that must be set */
|
|
const requiredEnvVars = ["HASS_TOKEN"] as const;
|
|
|
|
/**
|
|
* Validate that all required environment variables are set
|
|
* Throws an error if any required variable is missing
|
|
*/
|
|
for (const envVar of requiredEnvVars) {
|
|
if (!process.env[envVar]) {
|
|
throw new Error(`Missing required environment variable: ${envVar}`);
|
|
}
|
|
}
|
|
|
|
// Load and validate configuration
|
|
export const APP_CONFIG = AppConfigSchema.parse({
|
|
PORT: process.env.PORT || 4000,
|
|
NODE_ENV: process.env.NODE_ENV || "development",
|
|
HASS_HOST: process.env.HASS_HOST || "http://192.168.178.63:8123",
|
|
HASS_TOKEN: process.env.HASS_TOKEN,
|
|
JWT_SECRET: process.env.JWT_SECRET || "your-secret-key",
|
|
RATE_LIMIT: {
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 100, // limit each IP to 100 requests per windowMs
|
|
},
|
|
SSE: {
|
|
MAX_CLIENTS: 1000,
|
|
PING_INTERVAL: 30000, // 30 seconds
|
|
},
|
|
LOGGING: {
|
|
LEVEL: process.env.LOG_LEVEL || "info",
|
|
DIR: process.env.LOG_DIR || "logs",
|
|
MAX_SIZE: process.env.LOG_MAX_SIZE || "20m",
|
|
MAX_DAYS: process.env.LOG_MAX_DAYS || "14d",
|
|
COMPRESS: process.env.LOG_COMPRESS === "true",
|
|
TIMESTAMP_FORMAT: "YYYY-MM-DD HH:mm:ss:ms",
|
|
LOG_REQUESTS: process.env.LOG_REQUESTS === "true",
|
|
},
|
|
VERSION: "0.1.0",
|
|
SPEECH: {
|
|
ENABLED: process.env.ENABLE_SPEECH_FEATURES === "true",
|
|
WAKE_WORD_ENABLED: process.env.ENABLE_WAKE_WORD === "true",
|
|
SPEECH_TO_TEXT_ENABLED: process.env.ENABLE_SPEECH_TO_TEXT === "true",
|
|
WHISPER_MODEL_PATH: process.env.WHISPER_MODEL_PATH || "/models",
|
|
WHISPER_MODEL_TYPE: process.env.WHISPER_MODEL_TYPE || "base",
|
|
},
|
|
});
|