@nexusts/config 0.9.6 → 0.9.7

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.
@@ -1,46 +1,16 @@
1
- /**
2
- * `ConfigService` — type-safe access to validated environment
3
- * variables and configuration values.
4
- *
5
- * Usage:
6
- * constructor(@Inject(ConfigService.TOKEN) private config: ConfigService<typeof schema>) {}
7
- *
8
- * const dbUrl = this.config.get('DATABASE_URL'); // string
9
- * const port = this.config.get('PORT', { default: 3000 }); // number
10
- *
11
- * For full type inference, parameterize the class with your schema:
12
- * class MyService {
13
- * constructor(@Inject(ConfigService.TOKEN) private config: ConfigService<typeof schema>) {}
14
- * }
15
- */
16
1
  import type { ConfigSchema, InferConfig, ConfigOptions } from "./types.js";
17
2
  export declare class ConfigService<S extends ConfigSchema = ConfigSchema> {
18
3
  #private;
19
- private readonly options;
20
- /** DI token — use with `@Inject(ConfigService.TOKEN)`. */
21
4
  static readonly TOKEN: unique symbol;
22
- /** The validated, fully-typed config. */
5
+ private _diOptions;
23
6
  readonly config: InferConfig<S>;
24
7
  constructor(options?: ConfigOptions<S>);
25
- /**
26
- * Look up a config value by key. Type-safe when the class is
27
- * parameterized with the schema (`ConfigService<typeof schema>`).
28
- */
29
8
  get<K extends keyof InferConfig<S>>(key: K): InferConfig<S>[K];
30
9
  get<K extends keyof InferConfig<S>>(key: K, options: {
31
10
  default: InferConfig<S>[K];
32
11
  }): InferConfig<S>[K];
33
12
  get(key: string): unknown;
34
- /**
35
- * Look up a config value by key, throwing if it's missing.
36
- * Convenience for required values.
37
- */
38
13
  require<K extends keyof InferConfig<S>>(key: K): InferConfig<S>[K];
39
- /**
40
- * Read the raw env value (string), regardless of the schema.
41
- * Useful for debugging.
42
- */
43
14
  env(key: string): string | undefined;
44
- /** Reload from env. Drops the cache. */
45
15
  reload(): void;
46
16
  }
package/dist/index.js CHANGED
@@ -9,7 +9,6 @@ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
9
9
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
10
10
  return c > 3 && r && Object.defineProperty(target, key, r), r;
11
11
  };
12
- var __legacyDecorateParamTS = (index, decorator) => (target, key) => decorator(target, key, index);
13
12
  var __legacyMetadataTS = (k, v) => {
14
13
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
15
14
  return Reflect.metadata(k, v);
@@ -18,23 +17,24 @@ var __require = import.meta.require;
18
17
  // packages/config/src/config.service.ts
19
18
  import { Inject, Injectable } from "@nexusts/core";
20
19
  class ConfigService {
21
- options;
22
20
  static TOKEN = Symbol.for("nexus:ConfigService");
23
21
  config;
24
22
  #raw;
25
23
  #cache = new Map;
26
24
  #strict;
27
- constructor(options = {}) {
28
- this.options = options;
29
- const loaded = loadConfig(options);
25
+ #options;
26
+ constructor(options) {
27
+ const opts = options ?? this._diOptions ?? {};
28
+ this.#options = opts;
29
+ const loaded = loadConfig(opts);
30
30
  this.config = loaded.value;
31
31
  this.#raw = loaded.raw;
32
- this.#strict = options.strict ?? false;
32
+ this.#strict = opts.strict ?? false;
33
33
  if (loaded.errors.length > 0) {
34
34
  const msg = `[nexus/config] Configuration validation failed:
35
35
  ` + loaded.errors.map((e) => ` - ${e}`).join(`
36
36
  `);
37
- if (options.exitOnError) {
37
+ if (opts.exitOnError) {
38
38
  console.error(msg);
39
39
  process.exit(1);
40
40
  }
@@ -42,28 +42,25 @@ class ConfigService {
42
42
  }
43
43
  }
44
44
  get(key, options) {
45
- if (this.options.cache !== false && this.#cache.has(key)) {
45
+ const opts = this.#options;
46
+ if (opts.cache !== false && this.#cache.has(key))
46
47
  return this.#cache.get(key);
47
- }
48
48
  const fromConfig = this.config[key];
49
49
  if (fromConfig !== undefined) {
50
- if (this.options.cache !== false)
50
+ if (opts.cache !== false)
51
51
  this.#cache.set(key, fromConfig);
52
52
  return fromConfig;
53
53
  }
54
- if (options && "default" in options) {
54
+ if (options && "default" in options)
55
55
  return options.default;
56
- }
57
- if (this.#strict) {
56
+ if (this.#strict)
58
57
  throw new Error(`[nexus/config] Unknown config key "${key}"`);
59
- }
60
58
  return;
61
59
  }
62
60
  require(key) {
63
61
  const v = this.get(key);
64
- if (v === undefined || v === null || v === "") {
62
+ if (v === undefined || v === null || v === "")
65
63
  throw new Error(`[nexus/config] Required config key "${String(key)}" is missing`);
66
- }
67
64
  return v;
68
65
  }
69
66
  env(key) {
@@ -71,23 +68,24 @@ class ConfigService {
71
68
  }
72
69
  reload() {
73
70
  this.#cache.clear();
74
- const loaded = loadConfig(this.options);
71
+ const loaded = loadConfig(this.#options);
75
72
  Object.assign(this.config, loaded.value);
76
73
  this.#raw = loaded.raw;
77
74
  }
78
75
  }
76
+ __legacyDecorateClassTS([
77
+ Inject("CONFIG_OPTIONS")
78
+ ], ConfigService.prototype, "_diOptions", undefined);
79
79
  ConfigService = __legacyDecorateClassTS([
80
80
  Injectable(),
81
- __legacyDecorateParamTS(0, Inject("CONFIG_OPTIONS")),
82
81
  __legacyMetadataTS("design:paramtypes", [
83
82
  typeof ConfigOptions === "undefined" ? Object : ConfigOptions
84
83
  ])
85
84
  ], ConfigService);
86
85
  function loadConfig(options) {
87
86
  const env = {};
88
- for (const [k, v] of Object.entries(process.env)) {
87
+ for (const [k, v] of Object.entries(process.env))
89
88
  env[k] = v;
90
- }
91
89
  const paths = options.envFilePaths ?? [];
92
90
  const useEnvFile = options.envFile !== false;
93
91
  if (useEnvFile) {
@@ -194,5 +192,5 @@ export {
194
192
  ConfigModule
195
193
  };
196
194
 
197
- //# debugId=D9E2E2947256DA4664756E2164756E21
195
+ //# debugId=7B6891E1ECBD6A5364756E2164756E21
198
196
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -2,10 +2,10 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/config.service.ts", "../src/config.module.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * `ConfigService` — type-safe access to validated environment\n * variables and configuration values.\n *\n * Usage:\n * constructor(@Inject(ConfigService.TOKEN) private config: ConfigService<typeof schema>) {}\n *\n * const dbUrl = this.config.get('DATABASE_URL'); // string\n * const port = this.config.get('PORT', { default: 3000 }); // number\n *\n * For full type inference, parameterize the class with your schema:\n * class MyService {\n * constructor(@Inject(ConfigService.TOKEN) private config: ConfigService<typeof schema>) {}\n * }\n */\n\nimport { Inject, Injectable } from \"@nexusts/core\";\nimport type {\n\tConfigSchema,\n\tInferConfig,\n\tConfigOptions,\n\tLoadedConfig,\n} from \"./types.js\";\n\n@Injectable()\nexport class ConfigService<S extends ConfigSchema = ConfigSchema> {\n\t/** DI token — use with `@Inject(ConfigService.TOKEN)`. */\n\tstatic readonly TOKEN = Symbol.for(\"nexus:ConfigService\");\n\n\t/** The validated, fully-typed config. */\n\treadonly config: InferConfig<S>;\n\n\t#raw: Record<string, string | undefined>;\n\t#cache = new Map<string, unknown>();\n\t#strict: boolean;\n\n\tconstructor(\n\t\t@Inject(\"CONFIG_OPTIONS\") private readonly options: ConfigOptions<S> = {},\n\t) {\n\t\tconst loaded = loadConfig(options);\n\t\tthis.config = loaded.value as InferConfig<S>;\n\t\tthis.#raw = loaded.raw;\n\t\tthis.#strict = options.strict ?? false;\n\n\t\tif (loaded.errors.length > 0) {\n\t\t\tconst msg =\n\t\t\t\t`[nexus/config] Configuration validation failed:\\n` +\n\t\t\t\tloaded.errors.map((e) => ` - ${e}`).join(\"\\n\");\n\t\t\tif (options.exitOnError) {\n\t\t\t\tconsole.error(msg);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\tthrow new Error(msg);\n\t\t}\n\t}\n\n\t/**\n\t * Look up a config value by key. Type-safe when the class is\n\t * parameterized with the schema (`ConfigService<typeof schema>`).\n\t */\n\tget<K extends keyof InferConfig<S>>(key: K): InferConfig<S>[K];\n\tget<K extends keyof InferConfig<S>>(\n\t\tkey: K,\n\t\toptions: { default: InferConfig<S>[K] },\n\t): InferConfig<S>[K];\n\tget(key: string): unknown;\n\tget(key: string, options?: { default?: unknown }): unknown {\n\t\tif (this.options.cache !== false && this.#cache.has(key)) {\n\t\t\treturn this.#cache.get(key);\n\t\t}\n\t\tconst fromConfig = (this.config as Record<string, unknown>)[key];\n\t\tif (fromConfig !== undefined) {\n\t\t\tif (this.options.cache !== false) this.#cache.set(key, fromConfig);\n\t\t\treturn fromConfig;\n\t\t}\n\t\tif (options && \"default\" in options) {\n\t\t\treturn options.default;\n\t\t}\n\t\tif (this.#strict) {\n\t\t\tthrow new Error(`[nexus/config] Unknown config key \"${key}\"`);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Look up a config value by key, throwing if it's missing.\n\t * Convenience for required values.\n\t */\n\trequire<K extends keyof InferConfig<S>>(key: K): InferConfig<S>[K] {\n\t\tconst v = this.get(key);\n\t\tif (v === undefined || v === null || v === \"\") {\n\t\t\tthrow new Error(`[nexus/config] Required config key \"${String(key)}\" is missing`);\n\t\t}\n\t\treturn v as InferConfig<S>[K];\n\t}\n\n\t/**\n\t * Read the raw env value (string), regardless of the schema.\n\t * Useful for debugging.\n\t */\n\tenv(key: string): string | undefined {\n\t\treturn this.#raw[key];\n\t}\n\n\t/** Reload from env. Drops the cache. */\n\treload(): void {\n\t\tthis.#cache.clear();\n\t\tconst loaded = loadConfig(this.options);\n\t\tObject.assign(this.config as object, loaded.value);\n\t\tthis.#raw = loaded.raw;\n\t}\n}\n\n/**\n * Internal: load + validate config.\n *\n * Order: static `load` overrides `.env` files → `process.env`.\n * Env wins on conflict (most recent takes precedence).\n */\nfunction loadConfig<S extends ConfigSchema>(\n\toptions: ConfigOptions<S>,\n): LoadedConfig<S> {\n\t// 1) process.env as the base layer\n\tconst env: Record<string, string | undefined> = {};\n\tfor (const [k, v] of Object.entries(process.env)) {\n\t\tenv[k] = v;\n\t}\n\n\t// 2) .env files (overrides env defaults but env still wins)\n\tconst paths = options.envFilePaths ?? [];\n\n\t// When envFile is enabled (default), auto-load environment-specific files.\n\tconst useEnvFile = options.envFile !== false;\n\tif (useEnvFile) {\n\t\tconst nodeEnv = options.nodeEnv ?? process.env[\"NODE_ENV\"] ?? \"development\";\n\t\t// Base .env is always loaded first.\n\t\tif (!paths.includes(\".env\")) paths.unshift(\".env\");\n\t\t// .env.local — local overrides (should be .gitignored).\n\t\tif (!paths.includes(\".env.local\")) paths.push(\".env.local\");\n\t\t// .env.{NODE_ENV} — environment-specific (e.g. .env.production).\n\t\tconst envSpecific = `.env.${nodeEnv}`;\n\t\tif (!paths.includes(envSpecific)) paths.push(envSpecific);\n\t}\n\n\tfor (const p of paths) {\n\t\tconst file = readDotEnv(p);\n\t\tfor (const [k, v] of Object.entries(file)) {\n\t\t\tif (env[k] === undefined) env[k] = v;\n\t\t}\n\t}\n\n\t// 3) Static load() overrides\n\tconst merged: Record<string, unknown> = { ...env };\n\tif (options.load) {\n\t\tfor (const layer of options.load) {\n\t\t\tfor (const [k, v] of Object.entries(layer)) {\n\t\t\t\tif (!(k in env)) merged[k] = v;\n\t\t\t}\n\t\t}\n\t}\n\n\t// 4) Validate through Zod\n\tconst schema = options.schema;\n\tif (!schema) {\n\t\treturn { value: merged as InferConfig<S>, raw: env, errors: [] };\n\t}\n\tconst result = schema.safeParse(merged);\n\tif (result.success) {\n\t\treturn { value: result.data as InferConfig<S>, raw: env, errors: [] };\n\t}\n\tconst errors = result.error.issues.map(\n\t\t(i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`,\n\t);\n\treturn { value: merged as InferConfig<S>, raw: env, errors };\n}\n\n/**\n * Minimal .env reader. Avoids a runtime dep on `dotenv`.\n * Supports `KEY=value` lines, comments, and quoted values.\n */\nfunction readDotEnv(path: string): Record<string, string> {\n\ttry {\n\t\t// Bun has Bun.file(); Node has node:fs. Use whichever is available.\n\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\tconst fs = require(\"node:fs\") as typeof import(\"node:fs\");\n\t\tif (!fs.existsSync(path)) return {};\n\t\tconst text = fs.readFileSync(path, \"utf8\");\n\t\tconst out: Record<string, string> = {};\n\t\tfor (const rawLine of text.split(/\\r?\\n/)) {\n\t\t\tconst line = rawLine.trim();\n\t\t\tif (!line || line.startsWith(\"#\")) continue;\n\t\t\tconst eq = line.indexOf(\"=\");\n\t\t\tif (eq < 0) continue;\n\t\t\tconst key = line.slice(0, eq).trim();\n\t\t\tlet value = line.slice(eq + 1).trim();\n\t\t\t// Strip inline comments after unquoted values.\n\t\t\tif (!value.startsWith('\"') && !value.startsWith(\"'\")) {\n\t\t\t\tconst hash = value.indexOf(\" #\");\n\t\t\t\tif (hash >= 0) value = value.slice(0, hash).trim();\n\t\t\t}\n\t\t\t// Strip surrounding quotes.\n\t\t\tif (\n\t\t\t\t(value.startsWith('\"') && value.endsWith('\"')) ||\n\t\t\t\t(value.startsWith(\"'\") && value.endsWith(\"'\"))\n\t\t\t) {\n\t\t\t\tvalue = value.slice(1, -1);\n\t\t\t}\n\t\t\tout[key] = value;\n\t\t}\n\t\treturn out;\n\t} catch {\n\t\treturn {};\n\t}\n}",
6
- "/**\n * `ConfigModule` — drop-in module for typed, validated configuration.\n *\n * Usage:\n * // src/config/schema.ts\n * import { z } from 'zod';\n * export const configSchema = z.object({\n * DATABASE_URL: z.string().url(),\n * PORT: z.coerce.number().default(3000),\n * LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),\n * });\n *\n * // src/app/app.module.ts\n * @Module({\n * imports: [\n * ConfigModule.forRoot({\n * schema: configSchema,\n * envFilePaths: ['.env.local', '.env'],\n * }),\n * ],\n * })\n * export class AppModule {}\n *\n * // any service\n * class MyService {\n * constructor(@Inject(ConfigService.TOKEN) private config: ConfigService<typeof configSchema>) {}\n * connect() {\n * return this.config.require('DATABASE_URL');\n * }\n * }\n */\n\nimport { Module } from \"@nexusts/core\";\nimport { ConfigService } from \"./config.service.js\";\nimport type { ConfigOptions } from \"./types.js\";\nimport { safeGetMeta, safeDefineMeta, safeHasMeta } from \"@nexusts/core/di/safe-reflect\";\n\n@Module({\n\tproviders: [\n\t\tConfigService,\n\t\t{ provide: ConfigService.TOKEN, useExisting: ConfigService },\n\t],\n\texports: [ConfigService, ConfigService.TOKEN],\n})\nexport class ConfigModule {\n\tstatic forRoot(options: ConfigOptions = {}) {\n\t\t@Module({\n\t\t\tproviders: [\n\t\t\t\tConfigService,\n\t\t\t\t{ provide: ConfigService.TOKEN, useExisting: ConfigService },\n\t\t\t\t{ provide: \"CONFIG_OPTIONS\", useValue: options },\n\t\t\t],\n\t\t\texports: [ConfigService, ConfigService.TOKEN],\n\t\t})\n\t\tclass ConfiguredConfigModule {}\n\n\t\tObject.defineProperty(ConfiguredConfigModule, \"name\", {\n\t\t\tvalue: \"ConfiguredConfigModule\",\n\t\t});\n\n\t\treturn ConfiguredConfigModule;\n\t}\n}\n"
5
+ "/**\n * `ConfigService` — type-safe access to validated environment\n * variables and configuration values.\n */\nimport { Inject, Injectable } from \"@nexusts/core\";\nimport type {\n\tConfigSchema,\n\tInferConfig,\n\tConfigOptions,\n} from \"./types.js\";\n\n@Injectable()\nexport class ConfigService<S extends ConfigSchema = ConfigSchema> {\n\tstatic readonly TOKEN = Symbol.for(\"nexus:ConfigService\");\n\n\t@Inject(\"CONFIG_OPTIONS\") declare private _diOptions: ConfigOptions<S>;\n\n\treadonly config: InferConfig<S>;\n\t#raw: Record<string, string | undefined>;\n\t#cache = new Map<string, unknown>();\n\t#strict: boolean;\n\t#options: ConfigOptions<S>;\n\n\tconstructor(options?: ConfigOptions<S>) {\n\t\tconst opts = options ?? this._diOptions ?? ({} as ConfigOptions<S>);\n\t\tthis.#options = opts;\n\t\tconst loaded = loadConfig(opts);\n\t\tthis.config = loaded.value as InferConfig<S>;\n\t\tthis.#raw = loaded.raw;\n\t\tthis.#strict = opts.strict ?? false;\n\t\tif (loaded.errors.length > 0) {\n\t\t\tconst msg = `[nexus/config] Configuration validation failed:\\n` +\n\t\t\t\tloaded.errors.map((e) => ` - ${e}`).join(\"\\n\");\n\t\t\tif (opts.exitOnError) { console.error(msg); process.exit(1); }\n\t\t\tthrow new Error(msg);\n\t\t}\n\t}\n\n\tget<K extends keyof InferConfig<S>>(key: K): InferConfig<S>[K];\n\tget<K extends keyof InferConfig<S>>(key: K, options: { default: InferConfig<S>[K] }): InferConfig<S>[K];\n\tget(key: string): unknown;\n\tget(key: string, options?: { default?: unknown }): unknown {\n\t\tconst opts = this.#options;\n\t\tif (opts.cache !== false && this.#cache.has(key)) return this.#cache.get(key);\n\t\tconst fromConfig = (this.config as Record<string, unknown>)[key];\n\t\tif (fromConfig !== undefined) {\n\t\t\tif (opts.cache !== false) this.#cache.set(key, fromConfig);\n\t\t\treturn fromConfig;\n\t\t}\n\t\tif (options && \"default\" in options) return options.default;\n\t\tif (this.#strict) throw new Error(`[nexus/config] Unknown config key \"${key}\"`);\n\t\treturn undefined;\n\t}\n\n\trequire<K extends keyof InferConfig<S>>(key: K): InferConfig<S>[K] {\n\t\tconst v = this.get(key);\n\t\tif (v === undefined || v === null || v === \"\") throw new Error(`[nexus/config] Required config key \"${String(key)}\" is missing`);\n\t\treturn v as InferConfig<S>[K];\n\t}\n\n\tenv(key: string): string | undefined {\n\t\treturn this.#raw[key];\n\t}\n\n\treload(): void {\n\t\tthis.#cache.clear();\n\t\tconst loaded = loadConfig(this.#options);\n\t\tObject.assign(this.config as object, loaded.value);\n\t\tthis.#raw = loaded.raw;\n\t}\n}\n\n// ===========================================================================\n// Internal helpers\n// ===========================================================================\n\ninterface LoadedConfigResult<S extends ConfigSchema = ConfigSchema> {\n\tvalue: InferConfig<S>;\n\traw: Record<string, string | undefined>;\n\terrors: string[];\n}\n\nfunction loadConfig<S extends ConfigSchema>(options: ConfigOptions<S>): LoadedConfigResult<S> {\n\tconst env: Record<string, string | undefined> = {};\n\tfor (const [k, v] of Object.entries(process.env)) env[k] = v;\n\n\tconst paths = options.envFilePaths ?? [];\n\tconst useEnvFile = options.envFile !== false;\n\tif (useEnvFile) {\n\t\tconst nodeEnv = options.nodeEnv ?? process.env[\"NODE_ENV\"] ?? \"development\";\n\t\tif (!paths.includes(\".env\")) paths.unshift(\".env\");\n\t\tif (!paths.includes(\".env.local\")) paths.push(\".env.local\");\n\t\tconst envSpecific = `.env.${nodeEnv}`;\n\t\tif (!paths.includes(envSpecific)) paths.push(envSpecific);\n\t}\n\tfor (const p of paths) {\n\t\tconst file = readDotEnv(p);\n\t\tfor (const [k, v] of Object.entries(file)) {\n\t\t\tif (env[k] === undefined) env[k] = v;\n\t\t}\n\t}\n\n\tconst merged: Record<string, unknown> = { ...env };\n\tif (options.load) {\n\t\tfor (const layer of options.load) {\n\t\t\tfor (const [k, v] of Object.entries(layer)) {\n\t\t\t\tif (!(k in env)) merged[k] = v;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst schema = options.schema;\n\tif (!schema) {\n\t\treturn { value: merged as InferConfig<S>, raw: env, errors: [] };\n\t}\n\tconst result = schema.safeParse(merged);\n\tif (result.success) {\n\t\treturn { value: result.data as InferConfig<S>, raw: env, errors: [] };\n\t}\n\tconst errors = result.error.issues.map(\n\t\t(i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`,\n\t);\n\treturn { value: merged as InferConfig<S>, raw: env, errors };\n}\n\nfunction readDotEnv(path: string): Record<string, string> {\n\ttry {\n\t\tconst fs = require(\"node:fs\") as typeof import(\"node:fs\");\n\t\tif (!fs.existsSync(path)) return {};\n\t\tconst text = fs.readFileSync(path, \"utf8\");\n\t\tconst out: Record<string, string> = {};\n\t\tfor (const rawLine of text.split(/\\r?\\n/)) {\n\t\t\tconst line = rawLine.trim();\n\t\t\tif (!line || line.startsWith(\"#\")) continue;\n\t\t\tconst eq = line.indexOf(\"=\");\n\t\t\tif (eq < 0) continue;\n\t\t\tconst key = line.slice(0, eq).trim();\n\t\t\tlet value = line.slice(eq + 1).trim();\n\t\t\tif (!value.startsWith('\"') && !value.startsWith(\"'\")) {\n\t\t\t\tconst hash = value.indexOf(\" #\");\n\t\t\t\tif (hash >= 0) value = value.slice(0, hash).trim();\n\t\t\t}\n\t\t\tif ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n\t\t\t\tvalue = value.slice(1, -1);\n\t\t\t}\n\t\t\tout[key] = value;\n\t\t}\n\t\treturn out;\n\t} catch {\n\t\treturn {};\n\t}\n}\n",
6
+ "/**\n * `ConfigModule` — drop-in module for typed, validated configuration.\n *\n * Usage:\n * // src/config/schema.ts\n * import { z } from 'zod';\n * export const configSchema = z.object({\n * DATABASE_URL: z.string().url(),\n * PORT: z.coerce.number().default(3000),\n * LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),\n * });\n *\n * // src/app/app.module.ts\n * @Module({\n * imports: [\n * ConfigModule.forRoot({\n * schema: configSchema,\n * envFilePaths: ['.env.local', '.env'],\n * }),\n * ],\n * })\n * export class AppModule {}\n *\n * // any service\n * class MyService {\n * constructor(@Inject(ConfigService.TOKEN) private config: ConfigService<typeof configSchema>) {}\n * connect() {\n * return this.config.require('DATABASE_URL');\n * }\n * }\n */\n\nimport { Module } from \"@nexusts/core\";\nimport { ConfigService } from \"./config.service.js\";\nimport type { ConfigOptions } from \"./types.js\";\n\n@Module({\n\tproviders: [\n\t\tConfigService,\n\t\t{ provide: ConfigService.TOKEN, useExisting: ConfigService },\n\t],\n\texports: [ConfigService, ConfigService.TOKEN],\n})\nexport class ConfigModule {\n\tstatic forRoot(options: ConfigOptions = {}) {\n\t\t@Module({\n\t\t\tproviders: [\n\t\t\t\tConfigService,\n\t\t\t\t{ provide: ConfigService.TOKEN, useExisting: ConfigService },\n\t\t\t\t{ provide: \"CONFIG_OPTIONS\", useValue: options },\n\t\t\t],\n\t\t\texports: [ConfigService, ConfigService.TOKEN],\n\t\t})\n\t\tclass ConfiguredConfigModule {}\n\n\t\tObject.defineProperty(ConfiguredConfigModule, \"name\", {\n\t\t\tvalue: \"ConfiguredConfigModule\",\n\t\t});\n\n\t\treturn ConfiguredConfigModule;\n\t}\n}\n"
7
7
  ],
8
- "mappings": ";;;;;;;;;;;;;;;;;;AAgBA;AASO,MAAM,cAAqD;AAAA,EAYrB;AAAA,SAV5B,QAAQ,OAAO,IAAI,qBAAqB;AAAA,EAG/C;AAAA,EAET;AAAA,EACA,SAAS,IAAI;AAAA,EACb;AAAA,EAEA,WAAW,CACiC,UAA4B,CAAC,GACvE;AAAA,IAD0C;AAAA,IAE3C,MAAM,SAAS,WAAW,OAAO;AAAA,IACjC,KAAK,SAAS,OAAO;AAAA,IACrB,KAAK,OAAO,OAAO;AAAA,IACnB,KAAK,UAAU,QAAQ,UAAU;AAAA,IAEjC,IAAI,OAAO,OAAO,SAAS,GAAG;AAAA,MAC7B,MAAM,MACL;AAAA,IACA,OAAO,OAAO,IAAI,CAAC,MAAM,OAAO,GAAG,EAAE,KAAK;AAAA,CAAI;AAAA,MAC/C,IAAI,QAAQ,aAAa;AAAA,QACxB,QAAQ,MAAM,GAAG;AAAA,QACjB,QAAQ,KAAK,CAAC;AAAA,MACf;AAAA,MACA,MAAM,IAAI,MAAM,GAAG;AAAA,IACpB;AAAA;AAAA,EAaD,GAAG,CAAC,KAAa,SAA0C;AAAA,IAC1D,IAAI,KAAK,QAAQ,UAAU,SAAS,KAAK,OAAO,IAAI,GAAG,GAAG;AAAA,MACzD,OAAO,KAAK,OAAO,IAAI,GAAG;AAAA,IAC3B;AAAA,IACA,MAAM,aAAc,KAAK,OAAmC;AAAA,IAC5D,IAAI,eAAe,WAAW;AAAA,MAC7B,IAAI,KAAK,QAAQ,UAAU;AAAA,QAAO,KAAK,OAAO,IAAI,KAAK,UAAU;AAAA,MACjE,OAAO;AAAA,IACR;AAAA,IACA,IAAI,WAAW,aAAa,SAAS;AAAA,MACpC,OAAO,QAAQ;AAAA,IAChB;AAAA,IACA,IAAI,KAAK,SAAS;AAAA,MACjB,MAAM,IAAI,MAAM,sCAAsC,MAAM;AAAA,IAC7D;AAAA,IACA;AAAA;AAAA,EAOD,OAAuC,CAAC,KAA2B;AAAA,IAClE,MAAM,IAAI,KAAK,IAAI,GAAG;AAAA,IACtB,IAAI,MAAM,aAAa,MAAM,QAAQ,MAAM,IAAI;AAAA,MAC9C,MAAM,IAAI,MAAM,uCAAuC,OAAO,GAAG,eAAe;AAAA,IACjF;AAAA,IACA,OAAO;AAAA;AAAA,EAOR,GAAG,CAAC,KAAiC;AAAA,IACpC,OAAO,KAAK,KAAK;AAAA;AAAA,EAIlB,MAAM,GAAS;AAAA,IACd,KAAK,OAAO,MAAM;AAAA,IAClB,MAAM,SAAS,WAAW,KAAK,OAAO;AAAA,IACtC,OAAO,OAAO,KAAK,QAAkB,OAAO,KAAK;AAAA,IACjD,KAAK,OAAO,OAAO;AAAA;AAErB;AAtFa,gBAAN;AAAA,EADN,WAAW;AAAA,EAaT,kCAAO,gBAAgB;AAAA,EAZnB;AAAA;AAAA;AAAA,GAAM;AA8Fb,SAAS,UAAkC,CAC1C,SACkB;AAAA,EAElB,MAAM,MAA0C,CAAC;AAAA,EACjD,YAAY,GAAG,MAAM,OAAO,QAAQ,QAAQ,GAAG,GAAG;AAAA,IACjD,IAAI,KAAK;AAAA,EACV;AAAA,EAGA,MAAM,QAAQ,QAAQ,gBAAgB,CAAC;AAAA,EAGvC,MAAM,aAAa,QAAQ,YAAY;AAAA,EACvC,IAAI,YAAY;AAAA,IACf,MAAM,UAAU,QAAQ,WAAW,QAAQ,IAAI,eAAe;AAAA,IAE9D,IAAI,CAAC,MAAM,SAAS,MAAM;AAAA,MAAG,MAAM,QAAQ,MAAM;AAAA,IAEjD,IAAI,CAAC,MAAM,SAAS,YAAY;AAAA,MAAG,MAAM,KAAK,YAAY;AAAA,IAE1D,MAAM,cAAc,QAAQ;AAAA,IAC5B,IAAI,CAAC,MAAM,SAAS,WAAW;AAAA,MAAG,MAAM,KAAK,WAAW;AAAA,EACzD;AAAA,EAEA,WAAW,KAAK,OAAO;AAAA,IACtB,MAAM,OAAO,WAAW,CAAC;AAAA,IACzB,YAAY,GAAG,MAAM,OAAO,QAAQ,IAAI,GAAG;AAAA,MAC1C,IAAI,IAAI,OAAO;AAAA,QAAW,IAAI,KAAK;AAAA,IACpC;AAAA,EACD;AAAA,EAGA,MAAM,SAAkC,KAAK,IAAI;AAAA,EACjD,IAAI,QAAQ,MAAM;AAAA,IACjB,WAAW,SAAS,QAAQ,MAAM;AAAA,MACjC,YAAY,GAAG,MAAM,OAAO,QAAQ,KAAK,GAAG;AAAA,QAC3C,IAAI,EAAE,KAAK;AAAA,UAAM,OAAO,KAAK;AAAA,MAC9B;AAAA,IACD;AAAA,EACD;AAAA,EAGA,MAAM,SAAS,QAAQ;AAAA,EACvB,IAAI,CAAC,QAAQ;AAAA,IACZ,OAAO,EAAE,OAAO,QAA0B,KAAK,KAAK,QAAQ,CAAC,EAAE;AAAA,EAChE;AAAA,EACA,MAAM,SAAS,OAAO,UAAU,MAAM;AAAA,EACtC,IAAI,OAAO,SAAS;AAAA,IACnB,OAAO,EAAE,OAAO,OAAO,MAAwB,KAAK,KAAK,QAAQ,CAAC,EAAE;AAAA,EACrE;AAAA,EACA,MAAM,SAAS,OAAO,MAAM,OAAO,IAClC,CAAC,MAAM,GAAG,EAAE,KAAK,KAAK,GAAG,KAAK,aAAa,EAAE,SAC9C;AAAA,EACA,OAAO,EAAE,OAAO,QAA0B,KAAK,KAAK,OAAO;AAAA;AAO5D,SAAS,UAAU,CAAC,MAAsC;AAAA,EACzD,IAAI;AAAA,IAGH,MAAM;AAAA,IACN,IAAI,CAAC,GAAG,WAAW,IAAI;AAAA,MAAG,OAAO,CAAC;AAAA,IAClC,MAAM,OAAO,GAAG,aAAa,MAAM,MAAM;AAAA,IACzC,MAAM,MAA8B,CAAC;AAAA,IACrC,WAAW,WAAW,KAAK,MAAM,OAAO,GAAG;AAAA,MAC1C,MAAM,OAAO,QAAQ,KAAK;AAAA,MAC1B,IAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAAA,QAAG;AAAA,MACnC,MAAM,KAAK,KAAK,QAAQ,GAAG;AAAA,MAC3B,IAAI,KAAK;AAAA,QAAG;AAAA,MACZ,MAAM,MAAM,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK;AAAA,MACnC,IAAI,QAAQ,KAAK,MAAM,KAAK,CAAC,EAAE,KAAK;AAAA,MAEpC,IAAI,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,WAAW,GAAG,GAAG;AAAA,QACrD,MAAM,OAAO,MAAM,QAAQ,IAAI;AAAA,QAC/B,IAAI,QAAQ;AAAA,UAAG,QAAQ,MAAM,MAAM,GAAG,IAAI,EAAE,KAAK;AAAA,MAClD;AAAA,MAEA,IACE,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAC3C,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAC3C;AAAA,QACD,QAAQ,MAAM,MAAM,GAAG,EAAE;AAAA,MAC1B;AAAA,MACA,IAAI,OAAO;AAAA,IACZ;AAAA,IACA,OAAO;AAAA,IACN,MAAM;AAAA,IACP,OAAO,CAAC;AAAA;AAAA;;ACnLV;AAYO,MAAM,aAAa;AAAA,SAClB,OAAO,CAAC,UAAyB,CAAC,GAAG;AAAA,IAS3C,MAAM,uBAAuB;AAAA,IAAC;AAAA,IAAxB,yBAAN;AAAA,MARC,OAAO;AAAA,QACP,WAAW;AAAA,UACV;AAAA,UACA,EAAE,SAAS,cAAc,OAAO,aAAa,cAAc;AAAA,UAC3D,EAAE,SAAS,kBAAkB,UAAU,QAAQ;AAAA,QAChD;AAAA,QACA,SAAS,CAAC,eAAe,cAAc,KAAK;AAAA,MAC7C,CAAC;AAAA,OACK;AAAA,IAEN,OAAO,eAAe,wBAAwB,QAAQ;AAAA,MACrD,OAAO;AAAA,IACR,CAAC;AAAA,IAED,OAAO;AAAA;AAET;AAlBa,eAAN;AAAA,EAPN,OAAO;AAAA,IACP,WAAW;AAAA,MACV;AAAA,MACA,EAAE,SAAS,cAAc,OAAO,aAAa,cAAc;AAAA,IAC5D;AAAA,IACA,SAAS,CAAC,eAAe,cAAc,KAAK;AAAA,EAC7C,CAAC;AAAA,GACY;",
9
- "debugId": "D9E2E2947256DA4664756E2164756E21",
8
+ "mappings": "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",
9
+ "debugId": "7B6891E1ECBD6A5364756E2164756E21",
10
10
  "names": []
11
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexusts/config",
3
- "version": "0.9.6",
3
+ "version": "0.9.7",
4
4
  "description": "Zod-validated configuration with layered loading",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,7 +26,7 @@
26
26
  ],
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
- "@nexusts/core": "^0.9.6"
29
+ "@nexusts/core": "^0.9.7"
30
30
  },
31
31
  "repository": {
32
32
  "type": "git",