UNPKG

@anyme/anymejs

Version:
156 lines (153 loc) 5.71 kB
import { CONFIG, ENV_KEY_VALUES } from './default.config.js'; import { extname, basename, resolve, join } from 'node:path'; import fg from '../_virtual/index.js'; import { isEmpty, deepMerge, all, importJson, importModule, isFunction, ctx, set, getAbsolutePath } from '../utils/index.js'; class Config { #config = CONFIG; fileGroups = new Map(); configs = new Map(); path = process.env.CONFIG_PATH || "./config"; env = process.env.NODE_ENV || "development"; ignore = ["**/node_modules/**", "**/dist/**", "**/*.d.ts"]; order = [".ts", ".js", ".mjs", ".cjs", ".json"]; constructor() { this.fileGroups = this.groupConfigs(this.loadPaths()); } async get(name) { if (!name) return await this.loadCore(); if (this.configs.has(name)) return this.configs.get(name); if (this.fileGroups.has(name)) { const module = await this.importConfig(this.fileGroups.get(name)); if (!isEmpty(module)) { this.configs.set(name, module); return module; } } return undefined; } async loadCore() { if (this.configs.has("core") || isEmpty(this.fileGroups)) return this.#config; await this.loadAllConfigs(); this.#config = deepMerge(this.#config, ...this.getCoreConfigs()); this.loadEnvConfig(); this.resolveServerPaths(); this.validate(); this.configs.set("core", this.#config); return this.#config; } getCoreConfigs() { const configs = []; if (this.configs.has("default")) { configs.push(this.configs.get("default")); } if (this.env === "development" && this.configs.has("local")) { configs.push(this.configs.get("local")); } else if (this.env === "production" && this.configs.has("prod")) { configs.push(this.configs.get("prod")); } else if (this.env && this.configs.has(this.env)) { configs.push(this.configs.get(this.env)); } return configs; } loadAllConfigs() { return all(this.fileGroups, async ([key, path]) => { const module = await this.importConfig(path); if (!isEmpty(module)) this.configs.set(key, module); return module; }); } loadPaths() { return fg.sync(this.getPattern(), { onlyFiles: true, ignore: this.ignore, absolute: true, }); } groupConfigs(paths) { const fileGroups = new Map(); for (const path of paths) { const ext = extname(path); const index = this.order.indexOf(ext); if (index === -1) continue; const fileName = basename(path, ext).slice(0, -7); if (!fileGroups.has(fileName)) fileGroups.set(fileName, path); else { const oldIndex = this.order.indexOf(extname(fileGroups.get(fileName))); if (index < oldIndex) fileGroups.set(fileName, path); } } return fileGroups; } async importConfig(path) { try { if (extname(path) === ".json") return importJson(path); const module = await importModule(path); const result = isFunction(module) ? module(ctx()) : module; return isEmpty(result) ? {} : result; } catch (error) { console.error("❌ Failed to load config:", error); throw error; } } async loadEnvConfig() { ENV_KEY_VALUES.forEach((item) => { if (process.env[item.value]) { if (item.type === "number") this.merge(item.key, parseInt(process.env[item.value])); else if (item.type === "boolean") this.merge(item.key, process.env[item.value] === "true"); else if (item.type === "resolve") this.merge(item.key, resolve(process.env[item.value])); else this.merge(item.key, process.env[item.value]); } }); } getPattern() { const ext = this.order.join(","); return join(this.path, `*.config{${ext}}`).replace(/\\/g, "/"); } merge(str, value) { this.#config = deepMerge(this.#config, set(str, value)); } async validate() { if (!this.#config.session?.client?.secret) { console.warn("⚠️ Session secret is not set."); } if (this.env === "production") { if (this.#config.session?.enable) { if (!this.#config.session?.client?.cookie?.secure) { console.warn("⚠️ Forcing secure cookies in production environment"); } } if (this.#config.db?.enable) { if (this.#config.db?.client?.synchronize) { console.warn("⚠️ Database synchronization is enabled in production environment"); } } } } resolveServerPaths() { const serverPaths = ["controllers", "middlewares", "interceptors"]; serverPaths.forEach((key) => { if (this.#config.server?.route?.[key]?.length === 1 && typeof this.#config.server?.route?.[key][0] === "string") { const path = this.#config.server.route[key][0]; this.merge(`server.route.${key}`, [getAbsolutePath(path)]); } }); } } export { Config }; //# sourceMappingURL=index.js.map