@rawnodes/config-loader 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,30 @@
1
- import { existsSync, readFileSync, readdirSync } from 'fs';
2
- import * as yaml from 'js-yaml';
3
- import * as dotenv from 'dotenv';
4
- import { join } from 'path';
1
+ 'use strict';
2
+
3
+ var fs = require('fs');
4
+ var yaml = require('js-yaml');
5
+ var dotenv = require('dotenv');
6
+ var path = require('path');
7
+
8
+ function _interopNamespace(e) {
9
+ if (e && e.__esModule) return e;
10
+ var n = Object.create(null);
11
+ if (e) {
12
+ Object.keys(e).forEach(function (k) {
13
+ if (k !== 'default') {
14
+ var d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: function () { return e[k]; }
18
+ });
19
+ }
20
+ });
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+
26
+ var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
27
+ var dotenv__namespace = /*#__PURE__*/_interopNamespace(dotenv);
5
28
 
6
29
  // src/loader.ts
7
30
 
@@ -169,18 +192,18 @@ function loadDotenv(dotenvOption, environment) {
169
192
  } else {
170
193
  envPath = environment === "production" ? ".env" : `.env.${environment}`;
171
194
  }
172
- dotenv.config({ path: envPath });
195
+ dotenv__namespace.config({ path: envPath });
173
196
  }
174
197
  function resolveConfigDir(configDir) {
175
198
  const possiblePaths = [
176
- join(configDir, "src", "config"),
177
- join(configDir, "dist", "config"),
178
- join(configDir, "config"),
199
+ path.join(configDir, "src", "config"),
200
+ path.join(configDir, "dist", "config"),
201
+ path.join(configDir, "config"),
179
202
  configDir
180
203
  ];
181
- for (const path of possiblePaths) {
182
- if (existsSync(join(path, "base.yml")) || existsSync(join(path, "base.yaml"))) {
183
- return path;
204
+ for (const path$1 of possiblePaths) {
205
+ if (fs.existsSync(path.join(path$1, "base.yml")) || fs.existsSync(path.join(path$1, "base.yaml"))) {
206
+ return path$1;
184
207
  }
185
208
  }
186
209
  throw new Error(
@@ -189,21 +212,24 @@ ${possiblePaths.map((p) => ` - ${p}`).join("\n")}`
189
212
  );
190
213
  }
191
214
  function loadYamlFile(dir, filename) {
192
- const filePath = join(dir, filename);
193
- if (!existsSync(filePath)) {
215
+ const filePath = path.join(dir, filename);
216
+ if (!fs.existsSync(filePath)) {
194
217
  return {};
195
218
  }
196
- const content = readFileSync(filePath, "utf8");
197
- return yaml.load(content) || {};
219
+ const content = fs.readFileSync(filePath, "utf8");
220
+ return yaml__namespace.load(content) || {};
198
221
  }
199
222
  function loadOverrideDir(dir) {
200
- if (!existsSync(dir)) {
223
+ if (!fs.existsSync(dir)) {
201
224
  return [];
202
225
  }
203
- const files = readdirSync(dir).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml")).sort();
226
+ const files = fs.readdirSync(dir).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml")).sort();
204
227
  return files.map((file) => loadYamlFile(dir, file));
205
228
  }
206
229
 
207
- export { deepMerge, loadConfig, maskSecrets, replacePlaceholders };
230
+ exports.deepMerge = deepMerge;
231
+ exports.loadConfig = loadConfig;
232
+ exports.maskSecrets = maskSecrets;
233
+ exports.replacePlaceholders = replacePlaceholders;
208
234
  //# sourceMappingURL=index.js.map
209
235
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/deep-merge.ts","../src/utils/env-replacer.ts","../src/utils/mask-secrets.ts","../src/loader.ts"],"names":["isPlainObject","config"],"mappings":"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","file":"index.js","sourcesContent":["type DeepObject = Record<string, unknown>;\n\nexport function deepMerge(base: DeepObject, override: DeepObject): DeepObject {\n const merged = { ...base };\n\n for (const key in override) {\n const overrideValue = override[key];\n const baseValue = base[key];\n\n if (isPlainObject(overrideValue) && isPlainObject(baseValue)) {\n merged[key] = deepMerge(baseValue as DeepObject, overrideValue as DeepObject);\n } else {\n merged[key] = overrideValue;\n }\n }\n\n return merged;\n}\n\nfunction isPlainObject(value: unknown): value is DeepObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const ENV_PLACEHOLDER_REGEX = /\\${(.*?)}/g;\n\nexport function replacePlaceholders(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return replaceStringPlaceholders(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => replacePlaceholders(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = replacePlaceholders(obj[key]);\n }\n return result;\n }\n\n return obj;\n}\n\nfunction replaceStringPlaceholders(str: string): string {\n return str.replace(ENV_PLACEHOLDER_REGEX, (match, key) => {\n const [envKey, ...rest] = key.split(':');\n const defaultValue = rest.length > 0 ? rest.join(':') : undefined;\n const envValue = process.env[envKey];\n\n let value: string;\n if (envValue !== undefined) {\n value = envValue;\n } else if (defaultValue !== undefined) {\n value = defaultValue;\n } else {\n throw new Error(`Environment variable \"${envKey}\" is not defined and no default value provided`);\n }\n\n if (value.includes('${')) {\n return replacePlaceholders(value) as string;\n }\n\n return value;\n });\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const SECRET_PATTERNS = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'credential'];\n\nconst URL_WITH_CREDENTIALS_REGEX = /^([a-z]+:\\/\\/)([^:]+):([^@]+)@(.+)$/i;\n\nexport function maskSecrets(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return maskUrlCredentials(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => maskSecrets(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n if (isSecretKey(key)) {\n result[key] = maskValue(value);\n } else {\n result[key] = maskSecrets(value);\n }\n }\n return result;\n }\n\n return obj;\n}\n\nfunction isSecretKey(key: string): boolean {\n const lowerKey = key.toLowerCase();\n return SECRET_PATTERNS.some((pattern) => lowerKey.includes(pattern));\n}\n\nfunction maskValue(value: unknown): string {\n if (typeof value !== 'string') {\n return '***';\n }\n if (value.length <= 4) {\n return '***';\n }\n return value.slice(0, 2) + '***' + value.slice(-2);\n}\n\nfunction maskUrlCredentials(url: string): string {\n const match = url.match(URL_WITH_CREDENTIALS_REGEX);\n if (match) {\n const [, protocol, user, , host] = match;\n return `${protocol}${user}:***@${host}`;\n }\n return url;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { readFileSync, existsSync, readdirSync } from 'fs';\nimport * as yaml from 'js-yaml';\nimport * as dotenv from 'dotenv';\nimport { join } from 'path';\nimport type { ConfigLoaderOptions, ConfigLoaderResult } from './types.js';\nimport { deepMerge, replacePlaceholders, maskSecrets } from './utils/index.js';\n\nconst DEFAULT_OPTIONS = {\n configDir: process.cwd(),\n baseFileName: 'base',\n environment: process.env.NODE_ENV || 'local',\n extension: 'yml' as const,\n overrideDir: '/etc/app/config',\n};\n\nexport function loadConfig<T>(options: ConfigLoaderOptions<T> = {}): ConfigLoaderResult<T> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n let config = replacePlaceholders(mergedConfig) as T;\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nfunction loadDotenv(\n dotenvOption: boolean | { path?: string },\n environment: string,\n): void {\n let envPath: string;\n\n if (typeof dotenvOption === 'object' && dotenvOption.path) {\n envPath = dotenvOption.path;\n } else {\n envPath = environment === 'production' ? '.env' : `.env.${environment}`;\n }\n\n dotenv.config({ path: envPath });\n}\n\nfunction resolveConfigDir(configDir: string): string {\n const possiblePaths = [\n join(configDir, 'src', 'config'),\n join(configDir, 'dist', 'config'),\n join(configDir, 'config'),\n configDir,\n ];\n\n for (const path of possiblePaths) {\n if (existsSync(join(path, 'base.yml')) || existsSync(join(path, 'base.yaml'))) {\n return path;\n }\n }\n\n throw new Error(\n `Config files not found. Searched in:\\n${possiblePaths.map((p) => ` - ${p}`).join('\\n')}`,\n );\n}\n\nfunction loadYamlFile(dir: string, filename: string): Record<string, unknown> {\n const filePath = join(dir, filename);\n\n if (!existsSync(filePath)) {\n return {};\n }\n\n const content = readFileSync(filePath, 'utf8');\n return (yaml.load(content) as Record<string, unknown>) || {};\n}\n\nfunction loadOverrideDir(dir: string): Record<string, unknown>[] {\n if (!existsSync(dir)) {\n return [];\n }\n\n const files = readdirSync(dir)\n .filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'))\n .sort();\n\n return files.map((file) => loadYamlFile(dir, file));\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/deep-merge.ts","../src/utils/env-replacer.ts","../src/utils/mask-secrets.ts","../src/loader.ts"],"names":["isPlainObject","config","dotenv","join","path","existsSync","readFileSync","yaml","readdirSync"],"mappings":"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","file":"index.js","sourcesContent":["type DeepObject = Record<string, unknown>;\n\nexport function deepMerge(base: DeepObject, override: DeepObject): DeepObject {\n const merged = { ...base };\n\n for (const key in override) {\n const overrideValue = override[key];\n const baseValue = base[key];\n\n if (isPlainObject(overrideValue) && isPlainObject(baseValue)) {\n merged[key] = deepMerge(baseValue as DeepObject, overrideValue as DeepObject);\n } else {\n merged[key] = overrideValue;\n }\n }\n\n return merged;\n}\n\nfunction isPlainObject(value: unknown): value is DeepObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const ENV_PLACEHOLDER_REGEX = /\\${(.*?)}/g;\n\nexport function replacePlaceholders(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return replaceStringPlaceholders(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => replacePlaceholders(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = replacePlaceholders(obj[key]);\n }\n return result;\n }\n\n return obj;\n}\n\nfunction replaceStringPlaceholders(str: string): string {\n return str.replace(ENV_PLACEHOLDER_REGEX, (match, key) => {\n const [envKey, ...rest] = key.split(':');\n const defaultValue = rest.length > 0 ? rest.join(':') : undefined;\n const envValue = process.env[envKey];\n\n let value: string;\n if (envValue !== undefined) {\n value = envValue;\n } else if (defaultValue !== undefined) {\n value = defaultValue;\n } else {\n throw new Error(`Environment variable \"${envKey}\" is not defined and no default value provided`);\n }\n\n if (value.includes('${')) {\n return replacePlaceholders(value) as string;\n }\n\n return value;\n });\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const SECRET_PATTERNS = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'credential'];\n\nconst URL_WITH_CREDENTIALS_REGEX = /^([a-z]+:\\/\\/)([^:]+):([^@]+)@(.+)$/i;\n\nexport function maskSecrets(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return maskUrlCredentials(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => maskSecrets(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n if (isSecretKey(key)) {\n result[key] = maskValue(value);\n } else {\n result[key] = maskSecrets(value);\n }\n }\n return result;\n }\n\n return obj;\n}\n\nfunction isSecretKey(key: string): boolean {\n const lowerKey = key.toLowerCase();\n return SECRET_PATTERNS.some((pattern) => lowerKey.includes(pattern));\n}\n\nfunction maskValue(value: unknown): string {\n if (typeof value !== 'string') {\n return '***';\n }\n if (value.length <= 4) {\n return '***';\n }\n return value.slice(0, 2) + '***' + value.slice(-2);\n}\n\nfunction maskUrlCredentials(url: string): string {\n const match = url.match(URL_WITH_CREDENTIALS_REGEX);\n if (match) {\n const [, protocol, user, , host] = match;\n return `${protocol}${user}:***@${host}`;\n }\n return url;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { readFileSync, existsSync, readdirSync } from 'fs';\nimport * as yaml from 'js-yaml';\nimport * as dotenv from 'dotenv';\nimport { join } from 'path';\nimport type { ConfigLoaderOptions, ConfigLoaderResult } from './types.js';\nimport { deepMerge, replacePlaceholders, maskSecrets } from './utils/index.js';\n\nconst DEFAULT_OPTIONS = {\n configDir: process.cwd(),\n baseFileName: 'base',\n environment: process.env.NODE_ENV || 'local',\n extension: 'yml' as const,\n overrideDir: '/etc/app/config',\n};\n\nexport function loadConfig<T>(options: ConfigLoaderOptions<T> = {}): ConfigLoaderResult<T> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n let config = replacePlaceholders(mergedConfig) as T;\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nfunction loadDotenv(\n dotenvOption: boolean | { path?: string },\n environment: string,\n): void {\n let envPath: string;\n\n if (typeof dotenvOption === 'object' && dotenvOption.path) {\n envPath = dotenvOption.path;\n } else {\n envPath = environment === 'production' ? '.env' : `.env.${environment}`;\n }\n\n dotenv.config({ path: envPath });\n}\n\nfunction resolveConfigDir(configDir: string): string {\n const possiblePaths = [\n join(configDir, 'src', 'config'),\n join(configDir, 'dist', 'config'),\n join(configDir, 'config'),\n configDir,\n ];\n\n for (const path of possiblePaths) {\n if (existsSync(join(path, 'base.yml')) || existsSync(join(path, 'base.yaml'))) {\n return path;\n }\n }\n\n throw new Error(\n `Config files not found. Searched in:\\n${possiblePaths.map((p) => ` - ${p}`).join('\\n')}`,\n );\n}\n\nfunction loadYamlFile(dir: string, filename: string): Record<string, unknown> {\n const filePath = join(dir, filename);\n\n if (!existsSync(filePath)) {\n return {};\n }\n\n const content = readFileSync(filePath, 'utf8');\n return (yaml.load(content) as Record<string, unknown>) || {};\n}\n\nfunction loadOverrideDir(dir: string): Record<string, unknown>[] {\n if (!existsSync(dir)) {\n return [];\n }\n\n const files = readdirSync(dir)\n .filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'))\n .sort();\n\n return files.map((file) => loadYamlFile(dir, file));\n}\n"]}
@@ -1,30 +1,7 @@
1
- 'use strict';
2
-
3
- var fs = require('fs');
4
- var yaml = require('js-yaml');
5
- var dotenv = require('dotenv');
6
- var path = require('path');
7
-
8
- function _interopNamespace(e) {
9
- if (e && e.__esModule) return e;
10
- var n = Object.create(null);
11
- if (e) {
12
- Object.keys(e).forEach(function (k) {
13
- if (k !== 'default') {
14
- var d = Object.getOwnPropertyDescriptor(e, k);
15
- Object.defineProperty(n, k, d.get ? d : {
16
- enumerable: true,
17
- get: function () { return e[k]; }
18
- });
19
- }
20
- });
21
- }
22
- n.default = e;
23
- return Object.freeze(n);
24
- }
25
-
26
- var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
27
- var dotenv__namespace = /*#__PURE__*/_interopNamespace(dotenv);
1
+ import { existsSync, readFileSync, readdirSync } from 'fs';
2
+ import * as yaml from 'js-yaml';
3
+ import * as dotenv from 'dotenv';
4
+ import { join } from 'path';
28
5
 
29
6
  // src/loader.ts
30
7
 
@@ -192,18 +169,18 @@ function loadDotenv(dotenvOption, environment) {
192
169
  } else {
193
170
  envPath = environment === "production" ? ".env" : `.env.${environment}`;
194
171
  }
195
- dotenv__namespace.config({ path: envPath });
172
+ dotenv.config({ path: envPath });
196
173
  }
197
174
  function resolveConfigDir(configDir) {
198
175
  const possiblePaths = [
199
- path.join(configDir, "src", "config"),
200
- path.join(configDir, "dist", "config"),
201
- path.join(configDir, "config"),
176
+ join(configDir, "src", "config"),
177
+ join(configDir, "dist", "config"),
178
+ join(configDir, "config"),
202
179
  configDir
203
180
  ];
204
- for (const path$1 of possiblePaths) {
205
- if (fs.existsSync(path.join(path$1, "base.yml")) || fs.existsSync(path.join(path$1, "base.yaml"))) {
206
- return path$1;
181
+ for (const path of possiblePaths) {
182
+ if (existsSync(join(path, "base.yml")) || existsSync(join(path, "base.yaml"))) {
183
+ return path;
207
184
  }
208
185
  }
209
186
  throw new Error(
@@ -212,24 +189,21 @@ ${possiblePaths.map((p) => ` - ${p}`).join("\n")}`
212
189
  );
213
190
  }
214
191
  function loadYamlFile(dir, filename) {
215
- const filePath = path.join(dir, filename);
216
- if (!fs.existsSync(filePath)) {
192
+ const filePath = join(dir, filename);
193
+ if (!existsSync(filePath)) {
217
194
  return {};
218
195
  }
219
- const content = fs.readFileSync(filePath, "utf8");
220
- return yaml__namespace.load(content) || {};
196
+ const content = readFileSync(filePath, "utf8");
197
+ return yaml.load(content) || {};
221
198
  }
222
199
  function loadOverrideDir(dir) {
223
- if (!fs.existsSync(dir)) {
200
+ if (!existsSync(dir)) {
224
201
  return [];
225
202
  }
226
- const files = fs.readdirSync(dir).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml")).sort();
203
+ const files = readdirSync(dir).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml")).sort();
227
204
  return files.map((file) => loadYamlFile(dir, file));
228
205
  }
229
206
 
230
- exports.deepMerge = deepMerge;
231
- exports.loadConfig = loadConfig;
232
- exports.maskSecrets = maskSecrets;
233
- exports.replacePlaceholders = replacePlaceholders;
234
- //# sourceMappingURL=index.cjs.map
235
- //# sourceMappingURL=index.cjs.map
207
+ export { deepMerge, loadConfig, maskSecrets, replacePlaceholders };
208
+ //# sourceMappingURL=index.mjs.map
209
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/deep-merge.ts","../src/utils/env-replacer.ts","../src/utils/mask-secrets.ts","../src/loader.ts"],"names":["isPlainObject","config"],"mappings":"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","file":"index.mjs","sourcesContent":["type DeepObject = Record<string, unknown>;\n\nexport function deepMerge(base: DeepObject, override: DeepObject): DeepObject {\n const merged = { ...base };\n\n for (const key in override) {\n const overrideValue = override[key];\n const baseValue = base[key];\n\n if (isPlainObject(overrideValue) && isPlainObject(baseValue)) {\n merged[key] = deepMerge(baseValue as DeepObject, overrideValue as DeepObject);\n } else {\n merged[key] = overrideValue;\n }\n }\n\n return merged;\n}\n\nfunction isPlainObject(value: unknown): value is DeepObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const ENV_PLACEHOLDER_REGEX = /\\${(.*?)}/g;\n\nexport function replacePlaceholders(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return replaceStringPlaceholders(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => replacePlaceholders(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = replacePlaceholders(obj[key]);\n }\n return result;\n }\n\n return obj;\n}\n\nfunction replaceStringPlaceholders(str: string): string {\n return str.replace(ENV_PLACEHOLDER_REGEX, (match, key) => {\n const [envKey, ...rest] = key.split(':');\n const defaultValue = rest.length > 0 ? rest.join(':') : undefined;\n const envValue = process.env[envKey];\n\n let value: string;\n if (envValue !== undefined) {\n value = envValue;\n } else if (defaultValue !== undefined) {\n value = defaultValue;\n } else {\n throw new Error(`Environment variable \"${envKey}\" is not defined and no default value provided`);\n }\n\n if (value.includes('${')) {\n return replacePlaceholders(value) as string;\n }\n\n return value;\n });\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const SECRET_PATTERNS = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'credential'];\n\nconst URL_WITH_CREDENTIALS_REGEX = /^([a-z]+:\\/\\/)([^:]+):([^@]+)@(.+)$/i;\n\nexport function maskSecrets(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return maskUrlCredentials(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => maskSecrets(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n if (isSecretKey(key)) {\n result[key] = maskValue(value);\n } else {\n result[key] = maskSecrets(value);\n }\n }\n return result;\n }\n\n return obj;\n}\n\nfunction isSecretKey(key: string): boolean {\n const lowerKey = key.toLowerCase();\n return SECRET_PATTERNS.some((pattern) => lowerKey.includes(pattern));\n}\n\nfunction maskValue(value: unknown): string {\n if (typeof value !== 'string') {\n return '***';\n }\n if (value.length <= 4) {\n return '***';\n }\n return value.slice(0, 2) + '***' + value.slice(-2);\n}\n\nfunction maskUrlCredentials(url: string): string {\n const match = url.match(URL_WITH_CREDENTIALS_REGEX);\n if (match) {\n const [, protocol, user, , host] = match;\n return `${protocol}${user}:***@${host}`;\n }\n return url;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { readFileSync, existsSync, readdirSync } from 'fs';\nimport * as yaml from 'js-yaml';\nimport * as dotenv from 'dotenv';\nimport { join } from 'path';\nimport type { ConfigLoaderOptions, ConfigLoaderResult } from './types.js';\nimport { deepMerge, replacePlaceholders, maskSecrets } from './utils/index.js';\n\nconst DEFAULT_OPTIONS = {\n configDir: process.cwd(),\n baseFileName: 'base',\n environment: process.env.NODE_ENV || 'local',\n extension: 'yml' as const,\n overrideDir: '/etc/app/config',\n};\n\nexport function loadConfig<T>(options: ConfigLoaderOptions<T> = {}): ConfigLoaderResult<T> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n let config = replacePlaceholders(mergedConfig) as T;\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nfunction loadDotenv(\n dotenvOption: boolean | { path?: string },\n environment: string,\n): void {\n let envPath: string;\n\n if (typeof dotenvOption === 'object' && dotenvOption.path) {\n envPath = dotenvOption.path;\n } else {\n envPath = environment === 'production' ? '.env' : `.env.${environment}`;\n }\n\n dotenv.config({ path: envPath });\n}\n\nfunction resolveConfigDir(configDir: string): string {\n const possiblePaths = [\n join(configDir, 'src', 'config'),\n join(configDir, 'dist', 'config'),\n join(configDir, 'config'),\n configDir,\n ];\n\n for (const path of possiblePaths) {\n if (existsSync(join(path, 'base.yml')) || existsSync(join(path, 'base.yaml'))) {\n return path;\n }\n }\n\n throw new Error(\n `Config files not found. Searched in:\\n${possiblePaths.map((p) => ` - ${p}`).join('\\n')}`,\n );\n}\n\nfunction loadYamlFile(dir: string, filename: string): Record<string, unknown> {\n const filePath = join(dir, filename);\n\n if (!existsSync(filePath)) {\n return {};\n }\n\n const content = readFileSync(filePath, 'utf8');\n return (yaml.load(content) as Record<string, unknown>) || {};\n}\n\nfunction loadOverrideDir(dir: string): Record<string, unknown>[] {\n if (!existsSync(dir)) {\n return [];\n }\n\n const files = readdirSync(dir)\n .filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'))\n .sort();\n\n return files.map((file) => loadYamlFile(dir, file));\n}\n"]}
package/package.json CHANGED
@@ -1,16 +1,20 @@
1
1
  {
2
2
  "name": "@rawnodes/config-loader",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Flexible YAML config loader with environment overrides, Zod validation, and Docker-friendly features",
5
- "type": "module",
6
- "main": "./dist/index.cjs",
7
- "module": "./dist/index.js",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
8
7
  "types": "./dist/index.d.ts",
9
8
  "exports": {
10
9
  ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js",
13
- "require": "./dist/index.cjs"
10
+ "import": {
11
+ "types": "./dist/index.d.mts",
12
+ "default": "./dist/index.mjs"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
14
18
  }
15
19
  },
16
20
  "files": [
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/deep-merge.ts","../src/utils/env-replacer.ts","../src/utils/mask-secrets.ts","../src/loader.ts"],"names":["isPlainObject","config","dotenv","join","path","existsSync","readFileSync","yaml","readdirSync"],"mappings":"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","file":"index.cjs","sourcesContent":["type DeepObject = Record<string, unknown>;\n\nexport function deepMerge(base: DeepObject, override: DeepObject): DeepObject {\n const merged = { ...base };\n\n for (const key in override) {\n const overrideValue = override[key];\n const baseValue = base[key];\n\n if (isPlainObject(overrideValue) && isPlainObject(baseValue)) {\n merged[key] = deepMerge(baseValue as DeepObject, overrideValue as DeepObject);\n } else {\n merged[key] = overrideValue;\n }\n }\n\n return merged;\n}\n\nfunction isPlainObject(value: unknown): value is DeepObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const ENV_PLACEHOLDER_REGEX = /\\${(.*?)}/g;\n\nexport function replacePlaceholders(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return replaceStringPlaceholders(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => replacePlaceholders(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = replacePlaceholders(obj[key]);\n }\n return result;\n }\n\n return obj;\n}\n\nfunction replaceStringPlaceholders(str: string): string {\n return str.replace(ENV_PLACEHOLDER_REGEX, (match, key) => {\n const [envKey, ...rest] = key.split(':');\n const defaultValue = rest.length > 0 ? rest.join(':') : undefined;\n const envValue = process.env[envKey];\n\n let value: string;\n if (envValue !== undefined) {\n value = envValue;\n } else if (defaultValue !== undefined) {\n value = defaultValue;\n } else {\n throw new Error(`Environment variable \"${envKey}\" is not defined and no default value provided`);\n }\n\n if (value.includes('${')) {\n return replacePlaceholders(value) as string;\n }\n\n return value;\n });\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","const SECRET_PATTERNS = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'credential'];\n\nconst URL_WITH_CREDENTIALS_REGEX = /^([a-z]+:\\/\\/)([^:]+):([^@]+)@(.+)$/i;\n\nexport function maskSecrets(obj: unknown): unknown {\n if (typeof obj === 'string') {\n return maskUrlCredentials(obj);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => maskSecrets(item));\n }\n\n if (isPlainObject(obj)) {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n if (isSecretKey(key)) {\n result[key] = maskValue(value);\n } else {\n result[key] = maskSecrets(value);\n }\n }\n return result;\n }\n\n return obj;\n}\n\nfunction isSecretKey(key: string): boolean {\n const lowerKey = key.toLowerCase();\n return SECRET_PATTERNS.some((pattern) => lowerKey.includes(pattern));\n}\n\nfunction maskValue(value: unknown): string {\n if (typeof value !== 'string') {\n return '***';\n }\n if (value.length <= 4) {\n return '***';\n }\n return value.slice(0, 2) + '***' + value.slice(-2);\n}\n\nfunction maskUrlCredentials(url: string): string {\n const match = url.match(URL_WITH_CREDENTIALS_REGEX);\n if (match) {\n const [, protocol, user, , host] = match;\n return `${protocol}${user}:***@${host}`;\n }\n return url;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { readFileSync, existsSync, readdirSync } from 'fs';\nimport * as yaml from 'js-yaml';\nimport * as dotenv from 'dotenv';\nimport { join } from 'path';\nimport type { ConfigLoaderOptions, ConfigLoaderResult } from './types.js';\nimport { deepMerge, replacePlaceholders, maskSecrets } from './utils/index.js';\n\nconst DEFAULT_OPTIONS = {\n configDir: process.cwd(),\n baseFileName: 'base',\n environment: process.env.NODE_ENV || 'local',\n extension: 'yml' as const,\n overrideDir: '/etc/app/config',\n};\n\nexport function loadConfig<T>(options: ConfigLoaderOptions<T> = {}): ConfigLoaderResult<T> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const { configDir, baseFileName, environment, extension } = opts;\n\n // Load .env if requested\n if (options.dotenv) {\n loadDotenv(options.dotenv, environment);\n }\n\n const resolvedConfigDir = resolveConfigDir(configDir);\n\n const baseConfig = loadYamlFile(resolvedConfigDir, `${baseFileName}.${extension}`);\n const envConfig = loadYamlFile(resolvedConfigDir, `${environment}.${extension}`);\n\n let mergedConfig = deepMerge(baseConfig, envConfig);\n\n // Load override files from directory\n const overrideDir = options.overrideDir !== false ? (options.overrideDir ?? DEFAULT_OPTIONS.overrideDir) : null;\n if (overrideDir) {\n const overrideConfigs = loadOverrideDir(overrideDir);\n for (const override of overrideConfigs) {\n mergedConfig = deepMerge(mergedConfig, override);\n }\n }\n\n let config = replacePlaceholders(mergedConfig) as T;\n\n // Post-process\n if (options.postProcess) {\n config = options.postProcess(config);\n }\n\n // Validate with Zod schema\n if (options.schema) {\n const result = options.schema.safeParse(config);\n if (!result.success) {\n const errors = result.error.issues\n .map((e) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n');\n throw new Error(`Config validation failed:\\n${errors}`);\n }\n config = result.data;\n }\n\n // Log config with masked secrets\n if (options.logger) {\n const maskedConfig = maskSecrets(config);\n options.logger(`Config loaded (${environment}):\\n${JSON.stringify(maskedConfig, null, 2)}`);\n }\n\n return {\n config,\n environment,\n configDir: resolvedConfigDir,\n };\n}\n\nfunction loadDotenv(\n dotenvOption: boolean | { path?: string },\n environment: string,\n): void {\n let envPath: string;\n\n if (typeof dotenvOption === 'object' && dotenvOption.path) {\n envPath = dotenvOption.path;\n } else {\n envPath = environment === 'production' ? '.env' : `.env.${environment}`;\n }\n\n dotenv.config({ path: envPath });\n}\n\nfunction resolveConfigDir(configDir: string): string {\n const possiblePaths = [\n join(configDir, 'src', 'config'),\n join(configDir, 'dist', 'config'),\n join(configDir, 'config'),\n configDir,\n ];\n\n for (const path of possiblePaths) {\n if (existsSync(join(path, 'base.yml')) || existsSync(join(path, 'base.yaml'))) {\n return path;\n }\n }\n\n throw new Error(\n `Config files not found. Searched in:\\n${possiblePaths.map((p) => ` - ${p}`).join('\\n')}`,\n );\n}\n\nfunction loadYamlFile(dir: string, filename: string): Record<string, unknown> {\n const filePath = join(dir, filename);\n\n if (!existsSync(filePath)) {\n return {};\n }\n\n const content = readFileSync(filePath, 'utf8');\n return (yaml.load(content) as Record<string, unknown>) || {};\n}\n\nfunction loadOverrideDir(dir: string): Record<string, unknown>[] {\n if (!existsSync(dir)) {\n return [];\n }\n\n const files = readdirSync(dir)\n .filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'))\n .sort();\n\n return files.map((file) => loadYamlFile(dir, file));\n}\n"]}
File without changes