@fluojs/config 1.0.0-beta.6 → 1.0.0-beta.8
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/README.ko.md +17 -4
- package/README.md +15 -3
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +62 -7
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
package/README.ko.md
CHANGED
|
@@ -22,7 +22,7 @@ npm install @fluojs/config
|
|
|
22
22
|
|
|
23
23
|
## 사용 시점
|
|
24
24
|
|
|
25
|
-
- `.env
|
|
25
|
+
- `.env` 파일과 명시적인 `processEnv` 스냅샷을 하나의 설정 스냅샷으로 합쳐야 할 때
|
|
26
26
|
- 여러 소스의 우선순위를 명확하게 유지한 채 설정을 병합해야 할 때
|
|
27
27
|
- 애플리케이션 시작 전에 설정을 검증해서 잘못된 상태로 부팅되는 일을 막고 싶을 때
|
|
28
28
|
- `ConfigService`를 통해 설정 값을 타입 안전하게 읽고 싶을 때
|
|
@@ -54,11 +54,15 @@ const EnvSchema = z.object({
|
|
|
54
54
|
class AppModule {}
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
env file이 절대 경로나 미리 해석된 경로에 있다면 `envFilePath`를 사용하고, 기본 dotenv parser 대신 다른 flat-file parser가 필요하다면 `parse`를 전달하세요.
|
|
58
|
+
|
|
57
59
|
등록 후에는 `ConfigService`를 주입해서 값을 읽습니다.
|
|
58
60
|
|
|
59
61
|
```ts
|
|
62
|
+
import { Inject } from '@fluojs/core';
|
|
60
63
|
import { ConfigService } from '@fluojs/config';
|
|
61
64
|
|
|
65
|
+
@Inject(ConfigService)
|
|
62
66
|
class MyService {
|
|
63
67
|
constructor(private readonly config: ConfigService) {
|
|
64
68
|
const port = this.config.get('PORT');
|
|
@@ -75,6 +79,8 @@ class MyService {
|
|
|
75
79
|
|
|
76
80
|
`@fluojs/config`는 주변 환경 변수를 자동으로 스캔하지 않습니다. 환경 기반 값을 우선순위에 포함하려면 부트스트랩 경계에서 `processEnv` 스냅샷을 명시적으로 전달하세요.
|
|
77
81
|
|
|
82
|
+
`envFilePath`는 `envFile`보다 우선하며, `parse`를 사용하면 flat key/value 파일을 위한 custom parser로 dotenv parsing을 대체할 수 있습니다. 누락된 env file은 load 시 빈 입력처럼 처리됩니다. watch mode에서는 parent directory도 관찰하므로 나중에 파일을 생성해도 reload를 트리거할 수 있습니다.
|
|
83
|
+
|
|
78
84
|
### 객체 단위 딥 머지
|
|
79
85
|
|
|
80
86
|
일반 객체는 키 기준으로 깊게 병합되고, 배열과 원시값은 더 높은 우선순위 소스가 전체를 덮어씁니다.
|
|
@@ -89,9 +95,11 @@ class MyService {
|
|
|
89
95
|
|
|
90
96
|
`ConfigService.get('a.b.c')`는 dot-path 세그먼트를 순서대로 탐색하므로 조회 비용은 path 깊이에 비례합니다. `get()`, `getOrThrow()`, `snapshot()`이 객체 형태의 값을 반환할 때는 분리된 clone을 반환합니다. 따라서 clone 비용은 반환되는 subtree 크기에 비례하며, 호출자 mutation은 활성 config snapshot에 영향을 주지 않습니다.
|
|
91
97
|
|
|
92
|
-
`ConfigReloadManager.reload()`는 리로드 작업을 직렬화합니다. 현재 리로드가 listener 알림을 수행하는 동안 다른 리로드가 요청되면 후속 리로드는 큐에 들어가 활성 알림이 끝난 뒤 적용됩니다. 활성 알림이 실패하면
|
|
98
|
+
`ConfigReloadManager.reload()`는 리로드 작업을 직렬화합니다. 현재 리로드가 listener 알림을 수행하는 동안 다른 리로드가 요청되면 후속 리로드는 큐에 들어가 활성 알림이 끝난 뒤 적용됩니다. 활성 알림이 실패하면 직전 snapshot을 복구하고 큐에 있던 리로드는 폐기합니다. 동일한 직렬화와 rollback 계약은 `createConfigReloader(...).reload()`에도 적용되며, watch로 시작된 알림 중 큐에 들어간 manual reload도 이 계약을 따릅니다.
|
|
93
99
|
|
|
94
|
-
Module registration과 reloader 생성은 caller-owned options를 저장하기 전에 snapshot으로 분리합니다. `ConfigModule.forRoot(...)`, `ConfigReloadModule.forRoot(...)`, `createConfigReloader(...)`에 넘긴 객체를 나중에 변경해도 bootstrap, manual reload, watch reload 입력은 바뀌지 않습니다. Watch mode에서 시작 시점에 env file이 없으면 빈 file snapshot처럼 취급하고 parent directory를 watch하므로, 나중에 env file을 생성해도 reload가 트리거될 수 있습니다. Watch reload는 reload 전에 최종 env file content를 마지막으로 commit된 watch baseline과 비교하므로, 내용이 바뀌지 않은 저장이나 변경 후 debounce 안에서 원래 내용으로 되돌린 burst는 인프로세스 config snapshot을 교체하지 않습니다.
|
|
100
|
+
Module registration과 reloader 생성은 caller-owned options를 저장하기 전에 snapshot으로 분리합니다. `ConfigModule.forRoot(...)`, `ConfigReloadModule.forRoot(...)`, `createConfigReloader(...)`에 넘긴 객체를 나중에 변경해도 bootstrap, manual reload, watch reload 입력은 바뀌지 않습니다. `ConfigModule.forRoot({ watch: true, ... })`를 사용하면 module은 application bootstrap 중 env-file watcher를 시작하고, watch reload가 성공한 뒤 같은 injected `ConfigService` instance를 갱신합니다. Watch mode에서 시작 시점에 env file이 없으면 빈 file snapshot처럼 취급하고 parent directory를 watch하므로, 나중에 env file을 생성해도 reload가 트리거될 수 있습니다. Watch reload는 reload 전에 최종 env file content를 마지막으로 commit된 watch baseline과 비교하므로, 내용이 바뀌지 않은 저장이나 변경 후 debounce 안에서 원래 내용으로 되돌린 burst는 인프로세스 config snapshot을 교체하지 않습니다.
|
|
101
|
+
|
|
102
|
+
`ConfigReloadModule`은 명시적으로 주입 가능한 reload layer이며 standalone config source가 아닙니다. manual reload나 subscription을 위해 `CONFIG_RELOADER`가 필요한 caller는 `ConfigModule` 또는 다른 `ConfigService` provider와 함께 사용하세요. `ConfigModule` 또는 `ConfigReloadModule`이 만든 watcher는 `watch: true`일 때만 생성되며 module shutdown 중에 닫힙니다. 같은 env file에 대해서는 한 layer에서만 `watch: true`를 활성화하세요. 자동 `ConfigService` 갱신만 필요하면 `ConfigModule`을 사용하고, subscription/manual reload를 위한 injected reloader 계약이 필요하면 `ConfigReloadModule`을 사용합니다.
|
|
95
103
|
|
|
96
104
|
## 공개 API
|
|
97
105
|
|
|
@@ -105,7 +113,9 @@ Module registration과 reloader 생성은 caller-owned options를 저장하기
|
|
|
105
113
|
| `loadConfig(options)` | 설정을 수동으로 로드하기 위한 함수형 엔트리 포인트입니다. |
|
|
106
114
|
| `createConfigReloader(options)` | 동적 설정 업데이트를 위한 리로더를 생성합니다. |
|
|
107
115
|
|
|
108
|
-
|
|
116
|
+
이 패키지는 `ConfigModuleOptions`, `ConfigLoadOptions`, `ConfigReloadSubscription`, `ConfigReloadReason` 같은 option/subscription 타입도 export합니다.
|
|
117
|
+
|
|
118
|
+
`ConfigReloadManager.reload()`는 기존 `ConfigService` 인스턴스를 갱신하므로 소비자는 주입받은 서비스 identity를 유지하면서 새 스냅샷을 관찰합니다. 리로드 listener가 에러를 던지면 매니저는 직전 스냅샷을 복구하고 listener 에러를 다시 던집니다. `createConfigReloader(...).reload()`도 standalone reloader snapshot에 대해 동일한 listener 직렬화와 rollback 동작을 따릅니다.
|
|
109
119
|
|
|
110
120
|
## 관련 패키지
|
|
111
121
|
|
|
@@ -117,3 +127,6 @@ Module registration과 reloader 생성은 caller-owned options를 저장하기
|
|
|
117
127
|
- `packages/config/src/load.ts`
|
|
118
128
|
- `packages/config/src/service.ts`
|
|
119
129
|
- `packages/config/src/load.test.ts`
|
|
130
|
+
- `packages/config/src/reload-module.ts`
|
|
131
|
+
- `docs/architecture/config-and-environments.md`
|
|
132
|
+
- `docs/architecture/dev-reload-architecture.md`
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ npm install @fluojs/config
|
|
|
23
23
|
## When to Use
|
|
24
24
|
|
|
25
25
|
Use this package when you need to:
|
|
26
|
-
- Load configuration from `.env` files
|
|
26
|
+
- Load configuration from `.env` files plus an explicit `processEnv` snapshot.
|
|
27
27
|
- Merge multiple configuration sources with strict precedence rules.
|
|
28
28
|
- Validate your application configuration at startup.
|
|
29
29
|
- Access configuration values through a typed `ConfigService`.
|
|
@@ -57,14 +57,17 @@ const EnvSchema = z.object({
|
|
|
57
57
|
class AppModule {}
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
Use `envFilePath` when the env file lives at an absolute or pre-resolved path, or `parse` when you need a custom flat-file parser instead of the default dotenv parser.
|
|
61
|
+
|
|
60
62
|
Once registered, you can inject `ConfigService` to access your values:
|
|
61
63
|
|
|
62
64
|
```typescript
|
|
63
65
|
import { Inject } from '@fluojs/core';
|
|
64
66
|
import { ConfigService } from '@fluojs/config';
|
|
65
67
|
|
|
68
|
+
@Inject(ConfigService)
|
|
66
69
|
class MyService {
|
|
67
|
-
constructor(
|
|
70
|
+
constructor(private readonly config: ConfigService) {
|
|
68
71
|
const port = this.config.get('PORT');
|
|
69
72
|
const dbUrl = this.config.getOrThrow('DATABASE_URL');
|
|
70
73
|
}
|
|
@@ -82,6 +85,8 @@ Configuration is merged in the following order (highest precedence wins):
|
|
|
82
85
|
|
|
83
86
|
`@fluojs/config` does not scan ambient environment variables automatically. Pass an explicit `processEnv` snapshot at the bootstrap boundary when process-backed values should participate in precedence.
|
|
84
87
|
|
|
88
|
+
`envFilePath` overrides `envFile`, and `parse` lets callers replace dotenv parsing with a custom parser for flat key/value files. Missing env files are treated as empty input during load; watch mode also observes the parent directory so creating the file later can trigger a reload.
|
|
89
|
+
|
|
85
90
|
### Deep Merging
|
|
86
91
|
Plain objects are deep-merged by key. Arrays and primitive values from higher-precedence sources completely replace lower-precedence ones.
|
|
87
92
|
|
|
@@ -95,7 +100,9 @@ The `schema` option accepts a synchronous [Standard Schema](https://standardsche
|
|
|
95
100
|
|
|
96
101
|
`ConfigReloadManager.reload()` serializes reload work. If another reload is requested while the current reload is notifying listeners, the follow-up reload is queued and applied after the active notification finishes; if the active notification fails, the previous snapshot is restored and the queued reload is discarded. The same serialization and rollback contract applies to `createConfigReloader(...).reload()`, including manual reloads queued during watch-triggered notifications.
|
|
97
102
|
|
|
98
|
-
Module registration and reloader creation snapshot caller-owned options before storing them. Later mutations to objects passed to `ConfigModule.forRoot(...)`, `ConfigReloadModule.forRoot(...)`, or `createConfigReloader(...)` do not affect bootstrap, manual reloads, or watch reloads. In watch mode, a missing env file at startup is treated as an empty file snapshot while the parent directory is watched so creating the env file later can still trigger reload. Watch reloads compare the final env file content with the last committed watch baseline before reloading, so unchanged saves and change-then-revert bursts do not replace the in-process config snapshot.
|
|
103
|
+
Module registration and reloader creation snapshot caller-owned options before storing them. Later mutations to objects passed to `ConfigModule.forRoot(...)`, `ConfigReloadModule.forRoot(...)`, or `createConfigReloader(...)` do not affect bootstrap, manual reloads, or watch reloads. When `ConfigModule.forRoot({ watch: true, ... })` is used, the module starts an env-file watcher during application bootstrap and updates the same injected `ConfigService` instance after successful watch reloads. In watch mode, a missing env file at startup is treated as an empty file snapshot while the parent directory is watched so creating the env file later can still trigger reload. Watch reloads compare the final env file content with the last committed watch baseline before reloading, so unchanged saves and change-then-revert bursts do not replace the in-process config snapshot.
|
|
104
|
+
|
|
105
|
+
`ConfigReloadModule` is the explicit injectable reload layer, not a standalone config source. Pair it with `ConfigModule` or another `ConfigService` provider when callers need `CONFIG_RELOADER` for manual reloads or subscriptions. Watchers created by `ConfigModule` or `ConfigReloadModule` are created only when `watch: true`, and they are closed during module shutdown. Enable `watch: true` on one layer for a given env file: use `ConfigModule` for automatic `ConfigService` updates, or `ConfigReloadModule` when callers need the injected reloader contract for subscriptions/manual reloads.
|
|
99
106
|
|
|
100
107
|
## Public API
|
|
101
108
|
|
|
@@ -109,6 +116,8 @@ Module registration and reloader creation snapshot caller-owned options before s
|
|
|
109
116
|
| `loadConfig(options)` | Functional entry point for loading configuration manually. |
|
|
110
117
|
| `createConfigReloader(options)` | Creates a reloader for dynamic configuration updates. |
|
|
111
118
|
|
|
119
|
+
The package also exports option and subscription types such as `ConfigModuleOptions`, `ConfigLoadOptions`, `ConfigReloadSubscription`, and `ConfigReloadReason`.
|
|
120
|
+
|
|
112
121
|
`ConfigReloadManager.reload()` updates the existing `ConfigService` instance so consumers keep their injected service identity while observing the new snapshot. If a reload listener throws, the manager restores the previous snapshot and rethrows the listener error. `createConfigReloader(...).reload()` follows the same listener serialization and rollback behavior for its standalone reloader snapshot.
|
|
113
122
|
|
|
114
123
|
## Related Packages
|
|
@@ -121,3 +130,6 @@ Module registration and reloader creation snapshot caller-owned options before s
|
|
|
121
130
|
- `packages/config/src/load.ts`
|
|
122
131
|
- `packages/config/src/service.ts`
|
|
123
132
|
- `packages/config/src/load.test.ts`
|
|
133
|
+
- `packages/config/src/reload-module.ts`
|
|
134
|
+
- `docs/architecture/config-and-environments.md`
|
|
135
|
+
- `docs/architecture/dev-reload-architecture.md`
|
package/dist/module.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,mBAAmB,EAA4C,MAAM,YAAY,CAAC;AA4ChG;;GAEG;AACH,qBAAa,YAAY;IACvB;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,UAAU,YAAY;CA4BtE"}
|
package/dist/module.js
CHANGED
|
@@ -1,7 +1,55 @@
|
|
|
1
|
+
let _initClass;
|
|
2
|
+
function _applyDecs(e, t, n, r, o, i) { var a, c, u, s, f, l, p, d = Symbol.metadata || Symbol.for("Symbol.metadata"), m = Object.defineProperty, h = Object.create, y = [h(null), h(null)], v = t.length; function g(t, n, r) { return function (o, i) { n && (i = o, o = e); for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []); return r ? i : o; }; } function b(e, t, n, r) { if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined")); return e; } function applyDec(e, t, n, r, o, i, u, s, f, l, p) { function d(e) { if (!p(e)) throw new TypeError("Attempted to access private element on non-instance"); } var h = [].concat(t[0]), v = t[3], w = !u, D = 1 === o, S = 3 === o, j = 4 === o, E = 2 === o; function I(t, n, r) { return function (o, i) { return n && (i = o, o = e), r && r(o), P[t].call(o, i); }; } if (!w) { var P = {}, k = [], F = S ? "get" : j || D ? "set" : "value"; if (f ? (l || D ? P = { get: _setFunctionName(function () { return v(this); }, r, "get"), set: function (e) { t[4](this, e); } } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) { if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet"); y[+s][r] = o < 3 ? 1 : o; } } for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) { var T = b(h[O], "A decorator", "be", !0), z = n ? h[O - 1] : void 0, A = {}, H = { kind: ["field", "accessor", "method", "getter", "setter", "class"][o], name: r, metadata: a, addInitializer: function (e, t) { if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished"); b(t, "An initializer", "be", !0), i.push(t); }.bind(null, A) }; if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H.static = s, H.private = f, c = H.access = { has: f ? p.bind() : function (e) { return r in e; } }, j || (c.get = f ? E ? function (e) { return d(e), P.value; } : I("get", 0, d) : function (e) { return e[r]; }), E || S || (c.set = f ? I("set", 0, d) : function (e, t) { e[r] = t; }), N = T.call(z, D ? { get: P.get, set: P.set } : P[F], H), A.v = 1, D) { if ("object" == typeof N && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined"); } else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N); } return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N; } function w(e) { return m(e, d, { configurable: !0, enumerable: !0, value: a }); } return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function (e) { e && f.push(g(e)); }, p = function (t, r) { for (var i = 0; i < n.length; i++) { var a = n[i], c = a[1], l = 7 & c; if ((8 & c) == t && !l == r) { var p = a[2], d = !!a[3], m = 16 & c; applyDec(t ? e : e.prototype, a, m, d ? "#" + p : _toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function (t) { return _checkInRHS(t) === e; } : o); } } }, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), { e: c, get c() { var n = []; return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)]; } }; }
|
|
3
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
4
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
5
|
+
function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); try { Object.defineProperty(e, "name", { configurable: !0, value: n ? n + " " + t : t }); } catch (e) {} return e; }
|
|
6
|
+
function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
|
|
7
|
+
import { Inject } from '@fluojs/core';
|
|
1
8
|
import { defineModuleMetadata } from '@fluojs/core/internal';
|
|
2
|
-
import { loadConfig } from './load.js';
|
|
9
|
+
import { createConfigReloader, loadConfig } from './load.js';
|
|
3
10
|
import { snapshotConfigModuleOptions } from './options.js';
|
|
4
|
-
import { ConfigService, createConfigServiceFromSnapshot } from './service.js';
|
|
11
|
+
import { ConfigService, createConfigServiceFromSnapshot, replaceConfigServiceSnapshotUnchecked } from './service.js';
|
|
12
|
+
const CONFIG_MODULE_WATCH_OPTIONS = Symbol('fluo.config.module-watch-options');
|
|
13
|
+
let _ConfigModuleWatchMan;
|
|
14
|
+
class ConfigModuleWatchManager {
|
|
15
|
+
static {
|
|
16
|
+
[_ConfigModuleWatchMan, _initClass] = _applyDecs(this, [Inject(ConfigService, CONFIG_MODULE_WATCH_OPTIONS)], []).c;
|
|
17
|
+
}
|
|
18
|
+
reloader;
|
|
19
|
+
reloadForwarder;
|
|
20
|
+
constructor(config, options) {
|
|
21
|
+
this.config = config;
|
|
22
|
+
this.options = options;
|
|
23
|
+
}
|
|
24
|
+
onApplicationBootstrap() {
|
|
25
|
+
if (!this.options.watch) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (this.reloader) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this.reloader = createConfigReloader(this.options);
|
|
32
|
+
this.reloadForwarder = this.reloader.subscribe(snapshot => {
|
|
33
|
+
const previousConfig = this.config.snapshot();
|
|
34
|
+
try {
|
|
35
|
+
replaceConfigServiceSnapshotUnchecked(this.config, snapshot);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
replaceConfigServiceSnapshotUnchecked(this.config, previousConfig);
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
onModuleDestroy() {
|
|
43
|
+
this.reloadForwarder?.unsubscribe();
|
|
44
|
+
this.reloadForwarder = undefined;
|
|
45
|
+
this.reloader?.close();
|
|
46
|
+
this.reloader = undefined;
|
|
47
|
+
}
|
|
48
|
+
static {
|
|
49
|
+
_initClass();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
5
53
|
/**
|
|
6
54
|
* Module facade that wires normalized configuration into the application container.
|
|
7
55
|
*/
|
|
@@ -28,13 +76,20 @@ export class ConfigModule {
|
|
|
28
76
|
static forRoot(options) {
|
|
29
77
|
const loadOptions = snapshotConfigModuleOptions(options);
|
|
30
78
|
class ConfigModuleImpl extends ConfigModule {}
|
|
79
|
+
const providers = [{
|
|
80
|
+
provide: ConfigService,
|
|
81
|
+
useFactory: () => createConfigServiceFromSnapshot(loadConfig(loadOptions))
|
|
82
|
+
}];
|
|
83
|
+
if (loadOptions.watch) {
|
|
84
|
+
providers.push({
|
|
85
|
+
provide: CONFIG_MODULE_WATCH_OPTIONS,
|
|
86
|
+
useValue: loadOptions
|
|
87
|
+
}, _ConfigModuleWatchMan);
|
|
88
|
+
}
|
|
31
89
|
defineModuleMetadata(ConfigModuleImpl, {
|
|
32
|
-
global: loadOptions.
|
|
90
|
+
global: loadOptions.global ?? true,
|
|
33
91
|
exports: [ConfigService],
|
|
34
|
-
providers
|
|
35
|
-
provide: ConfigService,
|
|
36
|
-
useFactory: () => createConfigServiceFromSnapshot(loadConfig(loadOptions))
|
|
37
|
-
}]
|
|
92
|
+
providers
|
|
38
93
|
});
|
|
39
94
|
return ConfigModuleImpl;
|
|
40
95
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -34,7 +34,8 @@ export interface ConfigModuleOptions {
|
|
|
34
34
|
* returns a flat key-value record. Defaults to dotenv parsing. */
|
|
35
35
|
parse?: (content: string) => Record<string, string>;
|
|
36
36
|
watch?: boolean;
|
|
37
|
-
|
|
37
|
+
/** Whether the module should expose `ConfigService` globally. Defaults to `true`. */
|
|
38
|
+
global?: boolean;
|
|
38
39
|
}
|
|
39
40
|
/**
|
|
40
41
|
* Extended load options for one-off config loads and reloaders outside `ConfigModule.forRoot(...)`.
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,SAAS,gBAAgB,GAAG,gBAAgB,IAAI,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAEhI;;;GAGG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,MAAM,SAAS,MAAM,GAAG,EAAE,IAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnF;KACG,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,GAClB,GAAG,MAAM,GAAG,CAAC,EAAE,GACf,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC;CACrC,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GACnB,KAAK,CAAC;AAEV;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,CAAC,GACzD,CAAC,CAAC,CAAC,CAAC,GACJ,CAAC,SAAS,GAAG,MAAM,IAAI,IAAI,MAAM,IAAI,EAAE,GACrC,IAAI,SAAS,MAAM,CAAC,GAClB,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,GACvB,KAAK,GACP,KAAK,CAAC;AAEZ;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC/B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B;uEACmE;IACnE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,SAAS,gBAAgB,GAAG,gBAAgB,IAAI,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAEhI;;;GAGG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,MAAM,SAAS,MAAM,GAAG,EAAE,IAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnF;KACG,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,GAClB,GAAG,MAAM,GAAG,CAAC,EAAE,GACf,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC;CACrC,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GACnB,KAAK,CAAC;AAEV;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,CAAC,GACzD,CAAC,CAAC,CAAC,CAAC,GACJ,CAAC,SAAS,GAAG,MAAM,IAAI,IAAI,MAAM,IAAI,EAAE,GACrC,IAAI,SAAS,MAAM,CAAC,GAClB,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,GACvB,KAAK,GACP,KAAK,CAAC;AAEZ;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC/B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B;uEACmE;IACnE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,qFAAqF;IACrF,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEpD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAEpG;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAE7F;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,WAAW,IAAI,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,IAAI,gBAAgB,CAAC;IAC5B,MAAM,IAAI,gBAAgB,CAAC;IAC3B,SAAS,CAAC,QAAQ,EAAE,oBAAoB,GAAG,wBAAwB,CAAC;IACpE,cAAc,CAAC,QAAQ,EAAE,yBAAyB,GAAG,wBAAwB,CAAC;IAC9E,KAAK,IAAI,IAAI,CAAC;CACf"}
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"environment",
|
|
9
9
|
"typed-config"
|
|
10
10
|
],
|
|
11
|
-
"version": "1.0.0-beta.
|
|
11
|
+
"version": "1.0.0-beta.8",
|
|
12
12
|
"private": false,
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"repository": {
|
|
@@ -38,10 +38,11 @@
|
|
|
38
38
|
"@standard-schema/spec": "^1.1.0",
|
|
39
39
|
"dotenv": "^16.0.0",
|
|
40
40
|
"dotenv-expand": "^11.0.0",
|
|
41
|
-
"@fluojs/core": "^1.0.0-beta.
|
|
41
|
+
"@fluojs/core": "^1.0.0-beta.5"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"vitest": "^3.2.4"
|
|
44
|
+
"vitest": "^3.2.4",
|
|
45
|
+
"@fluojs/di": "^1.0.0-beta.7"
|
|
45
46
|
},
|
|
46
47
|
"scripts": {
|
|
47
48
|
"prebuild": "node ../../tooling/scripts/clean-dist.mjs",
|