meocord
Version:
Decorator-based Discord bot framework built on discord.js. Brings NestJS-style controllers, dependency injection, guards, and testing utilities to bot development — with a full CLI and TypeScript-first design.
76 lines (73 loc) • 2.85 kB
JavaScript
import path from 'path';
import { existsSync, readFileSync } from 'fs';
import { createJiti } from 'jiti';
import { fixJSON } from './json.util.js';
let cachedConfig;
let configLoaded = false;
/**
* Loads the MeoCord configuration, checking compiled output first then falling back to source.
*
* Resolution order:
* 1. `dist/meocord.config.mjs` — pre-compiled by `meocord build`, no tsconfig or source files needed
* 2. `meocord.config.ts` — loaded via jiti with tsconfig path aliases (dev mode)
*
* The result is cached after the first successful load.
*
* @returns {MeoCordConfig | undefined} The loaded configuration object, or undefined if loading fails.
*/ function loadMeoCordConfig() {
if (configLoaded) return cachedConfig;
configLoaded = true;
cachedConfig = loadCompiledConfig() ?? loadSourceConfig();
return cachedConfig;
}
/**
* Loads the pre-compiled config from dist/meocord.config.mjs.
* This file is generated by `meocord build` and requires no tsconfig or source files.
*/ function loadCompiledConfig() {
const compiledPath = path.resolve(process.cwd(), 'dist', 'meocord.config.mjs');
if (!existsSync(compiledPath)) return undefined;
try {
const jiti = createJiti(import.meta.url, {
interopDefault: true
});
return jiti(compiledPath);
} catch {
// Fall through to source config
return undefined;
}
}
/**
* Loads the source config from meocord.config.ts via jiti with tsconfig path alias resolution.
* Used in development mode where source files and tsconfig.json are available.
*/ function loadSourceConfig() {
const configPath = path.resolve(process.cwd(), 'meocord.config.ts');
if (!existsSync(configPath)) return undefined;
try {
const tsConfigPath = path.resolve(process.cwd(), 'tsconfig.json');
const aliases = {};
if (existsSync(tsConfigPath)) {
const tsConfig = JSON.parse(fixJSON(readFileSync(tsConfigPath, 'utf-8')));
const paths = tsConfig?.compilerOptions?.paths;
if (paths) {
for (const [key, values] of Object.entries(paths)){
const aliasKey = key.replace('/*', '');
aliases[aliasKey] = path.resolve(process.cwd(), values[0].replace('/*', ''));
}
}
}
const jiti = createJiti(import.meta.url, {
interopDefault: true,
alias: aliases,
moduleCache: false
});
return jiti(configPath);
} catch (error) {
if (error instanceof Error) {
console.error(`[MeoCord] Failed to load config: ${error.message}`);
} else {
console.error(`[MeoCord] Failed to load config: Unknown error`);
}
return undefined;
}
}
export { loadMeoCordConfig };