154 lines
3.8 KiB
TypeScript
154 lines
3.8 KiB
TypeScript
import path from "path";
|
|
|
|
interface Config {
|
|
// OpenAI Configuration
|
|
openai: {
|
|
apiKey: string;
|
|
endpoint: string;
|
|
modelName: string;
|
|
};
|
|
|
|
// VOICEVOX Configuration
|
|
voicevox: {
|
|
host: string;
|
|
styleId: number;
|
|
};
|
|
|
|
// Podcast Configuration
|
|
podcast: {
|
|
title: string;
|
|
link: string;
|
|
description: string;
|
|
language: string;
|
|
author: string;
|
|
categories: string;
|
|
ttl: string;
|
|
baseUrl: string;
|
|
};
|
|
|
|
// Admin Panel Configuration
|
|
admin: {
|
|
port: number;
|
|
username?: string;
|
|
password?: string;
|
|
};
|
|
|
|
// Batch Processing Configuration
|
|
batch: {
|
|
disableInitialRun: boolean;
|
|
};
|
|
|
|
// File paths
|
|
paths: {
|
|
projectRoot: string;
|
|
dataDir: string;
|
|
dbPath: string;
|
|
publicDir: string;
|
|
podcastAudioDir: string;
|
|
frontendBuildDir: string;
|
|
adminBuildDir: string;
|
|
feedUrlsFile: string;
|
|
};
|
|
}
|
|
|
|
function getRequiredEnv(key: string): string {
|
|
const value = import.meta.env[key];
|
|
if (!value) {
|
|
throw new Error(`Required environment variable ${key} is not set`);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function getOptionalEnv(key: string, defaultValue: string): string {
|
|
return import.meta.env[key] ?? defaultValue;
|
|
}
|
|
|
|
function createConfig(): Config {
|
|
const projectRoot = import.meta.dirname
|
|
? path.dirname(import.meta.dirname)
|
|
: process.cwd();
|
|
const dataDir = path.join(projectRoot, "data");
|
|
const publicDir = path.join(projectRoot, "public");
|
|
|
|
return {
|
|
openai: {
|
|
apiKey: getRequiredEnv("OPENAI_API_KEY"),
|
|
endpoint: getOptionalEnv(
|
|
"OPENAI_API_ENDPOINT",
|
|
"https://api.openai.com/v1",
|
|
),
|
|
modelName: getOptionalEnv("OPENAI_MODEL_NAME", "gpt-4o-mini"),
|
|
},
|
|
|
|
voicevox: {
|
|
host: getOptionalEnv("VOICEVOX_HOST", "http://localhost:50021"),
|
|
styleId: Number.parseInt(getOptionalEnv("VOICEVOX_STYLE_ID", "0")),
|
|
},
|
|
|
|
podcast: {
|
|
title: getOptionalEnv("PODCAST_TITLE", "自動生成ポッドキャスト"),
|
|
link: getOptionalEnv("PODCAST_LINK", "https://your-domain.com/podcast"),
|
|
description: getOptionalEnv(
|
|
"PODCAST_DESCRIPTION",
|
|
"RSSフィードから自動生成された音声ポッドキャスト",
|
|
),
|
|
language: getOptionalEnv("PODCAST_LANGUAGE", "ja"),
|
|
author: getOptionalEnv("PODCAST_AUTHOR", "管理者"),
|
|
categories: getOptionalEnv("PODCAST_CATEGORIES", "Technology"),
|
|
ttl: getOptionalEnv("PODCAST_TTL", "60"),
|
|
baseUrl: getOptionalEnv("PODCAST_BASE_URL", "https://your-domain.com"),
|
|
},
|
|
|
|
admin: {
|
|
port: Number.parseInt(getOptionalEnv("ADMIN_PORT", "3001")),
|
|
username: import.meta.env["ADMIN_USERNAME"],
|
|
password: import.meta.env["ADMIN_PASSWORD"],
|
|
},
|
|
|
|
batch: {
|
|
disableInitialRun:
|
|
getOptionalEnv("DISABLE_INITIAL_BATCH", "false") === "true",
|
|
},
|
|
|
|
paths: {
|
|
projectRoot,
|
|
dataDir,
|
|
dbPath: path.join(dataDir, "podcast.db"),
|
|
publicDir,
|
|
podcastAudioDir: path.join(publicDir, "podcast_audio"),
|
|
frontendBuildDir: path.join(projectRoot, "frontend", "dist"),
|
|
adminBuildDir: path.join(projectRoot, "admin-panel", "dist"),
|
|
feedUrlsFile: path.join(
|
|
projectRoot,
|
|
getOptionalEnv("FEED_URLS_FILE", "feed_urls.txt"),
|
|
),
|
|
},
|
|
};
|
|
}
|
|
|
|
export const config = createConfig();
|
|
|
|
export function validateConfig(): void {
|
|
// Validate required configuration
|
|
if (!config.openai.apiKey) {
|
|
throw new Error("OPENAI_API_KEY is required");
|
|
}
|
|
|
|
if (isNaN(config.voicevox.styleId)) {
|
|
throw new Error("VOICEVOX_STYLE_ID must be a valid number");
|
|
}
|
|
|
|
// Validate URLs
|
|
try {
|
|
new URL(config.voicevox.host);
|
|
} catch {
|
|
throw new Error("VOICEVOX_HOST must be a valid URL");
|
|
}
|
|
|
|
try {
|
|
new URL(config.openai.endpoint);
|
|
} catch {
|
|
throw new Error("OPENAI_API_ENDPOINT must be a valid URL");
|
|
}
|
|
}
|