alexa-house-control/src/Config.zig

93 lines
3.3 KiB
Zig

//! Configuration management - loads from .env file and environment variables.
//! Environment variables take precedence over .env file values.
const std = @import("std");
const Config = @This();
allocator: std.mem.Allocator,
cognito_username: ?[]const u8,
cognito_password: ?[]const u8,
home_assistant_url: ?[]const u8,
home_assistant_token: ?[]const u8,
is_lambda: bool,
pub fn init(allocator: std.mem.Allocator) !Config {
var self = Config{
.allocator = allocator,
.cognito_username = null,
.cognito_password = null,
.home_assistant_url = null,
.home_assistant_token = null,
.is_lambda = false,
};
// Load .env file first (if present)
try self.loadEnvFile();
// Environment variables override .env
var env_map = try std.process.getEnvMap(allocator);
defer env_map.deinit();
if (env_map.get("COGNITO_USERNAME")) |v| {
if (self.cognito_username) |old| allocator.free(old);
self.cognito_username = try allocator.dupe(u8, v);
}
if (env_map.get("COGNITO_PASSWORD")) |v| {
if (self.cognito_password) |old| allocator.free(old);
self.cognito_password = try allocator.dupe(u8, v);
}
if (env_map.get("HOME_ASSISTANT_URL")) |v| {
if (self.home_assistant_url) |old| allocator.free(old);
self.home_assistant_url = try allocator.dupe(u8, v);
}
if (env_map.get("HOME_ASSISTANT_TOKEN")) |v| {
if (self.home_assistant_token) |old| allocator.free(old);
self.home_assistant_token = try allocator.dupe(u8, v);
}
// Detect Lambda environment
self.is_lambda = env_map.get("AWS_LAMBDA_RUNTIME_API") != null;
return self;
}
pub fn deinit(self: *Config) void {
if (self.cognito_username) |v| self.allocator.free(v);
if (self.cognito_password) |v| self.allocator.free(v);
if (self.home_assistant_url) |v| self.allocator.free(v);
if (self.home_assistant_token) |v| self.allocator.free(v);
self.cognito_username = null;
self.cognito_password = null;
self.home_assistant_url = null;
self.home_assistant_token = null;
}
fn loadEnvFile(self: *Config) !void {
const file = std.fs.cwd().openFile(".env", .{}) catch return;
defer file.close();
const content = try file.readToEndAlloc(self.allocator, 1024 * 1024);
defer self.allocator.free(content);
var lines = std.mem.tokenizeScalar(u8, content, '\n');
while (lines.next()) |line| {
const trimmed = std.mem.trim(u8, line, " \t\r");
if (trimmed.len == 0 or trimmed[0] == '#') continue;
if (std.mem.indexOf(u8, trimmed, "=")) |eq_idx| {
const key = trimmed[0..eq_idx];
const val = trimmed[eq_idx + 1 ..];
if (std.mem.eql(u8, key, "COGNITO_USERNAME")) {
self.cognito_username = try self.allocator.dupe(u8, val);
} else if (std.mem.eql(u8, key, "COGNITO_PASSWORD")) {
self.cognito_password = try self.allocator.dupe(u8, val);
} else if (std.mem.eql(u8, key, "HOME_ASSISTANT_URL")) {
self.home_assistant_url = try self.allocator.dupe(u8, val);
} else if (std.mem.eql(u8, key, "HOME_ASSISTANT_TOKEN")) {
self.home_assistant_token = try self.allocator.dupe(u8, val);
}
}
}
}