Files
claude-code-conduit/server/config.mjs
mikael-lovqvists-claude-agent 25891ece7e Add Google Calendar integration and Claude docs
- New server/google_calendar.mjs wrapping googleapis v3 with auto token refresh
- Four new actions: calendar-list-events (auto-accept), calendar-create/update/delete-event (queue)
- bin/ccc-gcal-auth.mjs one-time OAuth2 consent flow helper
- config.example.json updated with google_calendar block
- server/config.mjs, index.mjs wired up following the same pattern as SMTP/mailer
- Bump version to 1.2.0
- Add CLAUDE.md and claude-info/ with architecture reference, feature plans, and contributing checklist

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 15:33:36 +00:00

70 lines
1.9 KiB
JavaScript

import { readFileSync } from 'fs';
import { resolve } from 'path';
export function load_config(file_path) {
if (!file_path) {
throw new Error('--config <path> is required');
}
let raw;
try {
raw = readFileSync(file_path, 'utf8');
} catch (err) {
throw new Error(`Cannot read config file at ${file_path}: ${err.message}`);
}
let parsed;
try {
parsed = JSON.parse(raw);
} catch (err) {
throw new Error(`Config file is not valid JSON: ${err.message}`);
}
if (!parsed.secrets) {
throw new Error("Config file must have a 'secrets' field pointing to the secrets file");
}
// Resolve secrets path relative to the config file's directory
const config_dir = resolve(file_path, '..');
const secrets_path = resolve(config_dir, parsed.secrets);
let secrets_raw;
try {
secrets_raw = readFileSync(secrets_path, 'utf8');
} catch (err) {
throw new Error(`Cannot read secrets file at ${secrets_path}: ${err.message}`);
}
let secrets;
try {
secrets = JSON.parse(secrets_raw);
} catch (err) {
throw new Error(`Secrets file is not valid JSON: ${err.message}`);
}
if (!secrets.users || typeof secrets.users !== 'object') {
throw new Error("Secrets file must have a top-level 'users' object");
}
const mail_perms_path = parsed.mail_perms
? resolve(config_dir, parsed.mail_perms)
: null;
let google_calendar = null;
if (parsed.google_calendar) {
const { credentials, token } = parsed.google_calendar;
if (!credentials || !token) {
throw new Error("Config 'google_calendar' must have 'credentials' and 'token' fields");
}
google_calendar = {
credentials_path: resolve(config_dir, credentials),
token_path: resolve(config_dir, token),
};
}
return {
users: secrets.users,
smtp: parsed.smtp ?? null,
mail_perms_path,
google_calendar,
bind: parsed.bind ?? null,
port: parsed.port ?? null,
};
}