@fluojs/config 1.0.0-beta.5 → 1.0.0-beta.6

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 CHANGED
@@ -91,7 +91,7 @@ class MyService {
91
91
 
92
92
  `ConfigReloadManager.reload()`는 리로드 작업을 직렬화합니다. 현재 리로드가 listener 알림을 수행하는 동안 다른 리로드가 요청되면 후속 리로드는 큐에 들어가 활성 알림이 끝난 뒤 적용됩니다. 활성 알림이 실패하면 이전 snapshot을 복구하고 큐에 있던 리로드는 폐기합니다. 동일한 직렬화와 rollback 계약은 `createConfigReloader(...).reload()`에도 적용되며, watch로 시작된 알림 중 큐에 들어간 manual reload도 이 계약을 따릅니다.
93
93
 
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가 트리거될 수 있습니다.
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을 교체하지 않습니다.
95
95
 
96
96
  ## 공개 API
97
97
 
package/README.md CHANGED
@@ -95,7 +95,7 @@ The `schema` option accepts a synchronous [Standard Schema](https://standardsche
95
95
 
96
96
  `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
97
 
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.
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.
99
99
 
100
100
  ## Public API
101
101
 
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EAEjB,cAAc,EAKf,MAAM,YAAY,CAAC;AAqYpB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CA+B/E;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CAEvE"}
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EAEjB,cAAc,EAKf,MAAM,YAAY,CAAC;AAwZpB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAgC/E;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CAEvE"}
package/dist/load.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createHash } from 'node:crypto';
1
2
  import { existsSync, readFileSync, watch } from 'node:fs';
2
3
  import { basename, dirname, join } from 'node:path';
3
4
  import { FluoError } from '@fluojs/core';
@@ -180,6 +181,16 @@ function createSubscription(listeners, listener) {
180
181
  }
181
182
  };
182
183
  }
184
+ function hashEnvFileContent(envFile) {
185
+ try {
186
+ return createHash('sha256').update(readFileSync(envFile)).digest('hex');
187
+ } catch (error) {
188
+ if (typeof error === 'object' && error !== null && 'code' in error && error.code === 'ENOENT') {
189
+ return undefined;
190
+ }
191
+ throw error;
192
+ }
193
+ }
183
194
  function notifyReloadListeners(listeners, snapshot, reason) {
184
195
  for (const listener of listeners) {
185
196
  listener(cloneConfigDictionary(snapshot), reason);
@@ -242,7 +253,12 @@ function startReloaderWatcher(normalized, options, state, listeners, errorListen
242
253
  return;
243
254
  }
244
255
  try {
256
+ const nextEnvFileHash = hashEnvFileContent(normalized.envFile);
257
+ if (nextEnvFileHash === state.watchedEnvFileHash) {
258
+ return;
259
+ }
245
260
  applyReload(normalized, state, listeners, 'watch');
261
+ state.watchedEnvFileHash = nextEnvFileHash;
246
262
  } catch (error) {
247
263
  notifyReloadErrorListeners(errorListeners, error, getReloadFailureReason(error) ?? 'watch');
248
264
  }
@@ -284,6 +300,7 @@ export function createConfigReloader(options) {
284
300
  current: resolveConfig(normalized),
285
301
  pendingReloadReason: undefined,
286
302
  reloading: false,
303
+ watchedEnvFileHash: hashEnvFileContent(normalized.envFile),
287
304
  watcher: undefined
288
305
  };
289
306
  const listeners = new Set();
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "environment",
9
9
  "typed-config"
10
10
  ],
11
- "version": "1.0.0-beta.5",
11
+ "version": "1.0.0-beta.6",
12
12
  "private": false,
13
13
  "license": "MIT",
14
14
  "repository": {