import Nconf from 'nconf'; import path from 'node:path'; import {bindAll as bindUrlHelpers, type BoundHelpers} from '@tryghost/config-url-helpers'; import * as localUtils from './utils'; import {bindAll as bindHelpers, type ConfigHelpers} from './helpers'; const _debug = require('@tryghost/debug')._base; const debug = _debug('ghost:config'); interface LoadNconfOptions { baseConfigPath?: string; customConfigPath?: string; } export type ConfigInstance = Nconf.Provider & BoundHelpers & ConfigHelpers; function loadNconf(options?: LoadNconfOptions): ConfigInstance { debug('config start'); const env = localUtils.getNodeEnv(); options = options || {}; const baseConfigPath = options.baseConfigPath || __dirname; const customConfigPath = options.customConfigPath || process.cwd(); const nconf = new Nconf.Provider(); // ## Load Config // no channel can override the overrides nconf.file('overrides', path.join(baseConfigPath, 'overrides.json')); // command line arguments take precedence, then environment variables nconf.argv(); nconf.env({separator: '__', parseValues: true}); // Now load various config json files nconf.file('custom-env', path.join(customConfigPath, 'config.' + env + '.json')); if (!env.startsWith('testing')) { if (process.env.GHOST_DEV_IS_DOCKER === 'true') { nconf.file('docker-env', path.join(baseConfigPath, 'env', 'config.development.docker.json')); } nconf.file('local-env', path.join(customConfigPath, 'config.local.json')); nconf.file('local-env-jsonc', { file: path.join(customConfigPath, 'config.local.jsonc'), format: localUtils.jsoncFormat }); } nconf.file('default-env', path.join(baseConfigPath, 'env', 'config.' + env + '.json')); // Finally, we load defaults, if nothing else has a value this will nconf.file('defaults', path.join(baseConfigPath, 'defaults.json')); // ## Config Methods // Expose dynamic utility methods bindUrlHelpers(nconf); bindHelpers(nconf); // ## Sanitization // transform all relative paths to absolute paths localUtils.makePathsAbsolute(nconf, nconf.get('paths'), 'paths'); // transform sqlite filename path for Ghost-CLI localUtils.sanitizeDatabaseProperties(nconf); // Check if the URL in config has a protocol localUtils.checkUrlProtocol(nconf.get('url')); // Ensure that the content path exists localUtils.doesContentPathExist(nconf.get('paths:contentPath')); // ## Other Stuff! // Manually set values nconf.set('env', env); // Wrap this in a check, because else nconf.get() is executed unnecessarily // To output this, use DEBUG=ghost:*,ghost-config if (_debug.enabled('ghost-config')) { debug(nconf.get()); } debug('config end'); return nconf; } export {loadNconf};