@gaonjs/config 0.23.0 → 0.25.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/testkit.d.ts CHANGED
@@ -1,7 +1,18 @@
1
+ import { type MongoConnectionConfig } from '@gaonjs/data';
1
2
  export interface TestDbHandle {
2
3
  /** 등록한 모든 커넥션을 종료하고 배터리를 리셋한다(afterAll 에서 호출). */
3
4
  close(): Promise<void>;
4
5
  }
6
+ /**
7
+ * 문서형(mongodb) 커넥션을 테스트용으로 파생한다 — SQL 의 `<db>_test`(결정 111)와 대칭.
8
+ * 몽고는 CREATE DATABASE 가 없어(첫 쓰기에 생성) 미리 만들 것이 없고, 이름만 갈라도
9
+ * 개발 DB 를 테스트가 건드리지 않는다. `database` 를 채워 돌려주면 adapter-mongo 가
10
+ * dbName 으로 우선 적용한다(결정 364 — url 경로보다 database 가 이긴다).
11
+ *
12
+ * url·database 가 둘 다 없으면 그대로 돌려준다 — openMongoConnection 이 무신호
13
+ * 오배선(기본 DB `test`)을 fail-loud 로 막는 자기 안내를 그대로 내게 둔다(결정 335).
14
+ */
15
+ export declare function deriveMongoTestConfig(cfg: MongoConnectionConfig): MongoConnectionConfig;
5
16
  /**
6
17
  * 테스트용 DB 커넥션 + DB 외 배터리(mail·storage·i18n)를 배선한다(결정 111·136).
7
18
  * 각 커넥션을 `<db>_test` 로 파생해 poolMax:1 로 붙이고, 스토리지·메일을 테스트
package/dist/testkit.js CHANGED
@@ -4,6 +4,10 @@
4
4
  // 만들어 마이그레이션한 그 DB 다. 스캐폴드 `test/setup.ts` 가 부트스트랩으로 쓰고,
5
5
  // 매 테스트 뒤 `truncateAll()` 로 격리한다(§9 실 인프라 · 근거는 결정 111).
6
6
  //
7
+ // 문서형(mongodb) 커넥션도 **등록한다**(`<db>_test` · deriveMongoTestConfig) — 다만
8
+ // SQL 전용 프로비저닝(CREATE DATABASE + 마이그레이션)과 트랜잭션 롤백/truncate 격리는
9
+ // 타지 않는다(§7.3 · 결정 279 — 문서형은 각 테스트가 deleteMany 로 자기 정리).
10
+ //
7
11
  // Redis·NATS 는 배선하지 않는다(웹 전용). mail·storage·i18n 은 serve·work 와 같은
8
12
  // 경로(configureNonDbBatteries)로 배선한다 — 스토리지·메일을 쓰는 잡·서비스가
9
13
  // 테스트에서도 운영과 같은 코드로 돌아야 한다(결정 136 · "wireDomain 안 태워 테스트만
@@ -15,6 +19,30 @@ import { resetStorage } from '@gaonjs/storage';
15
19
  import { resetI18n } from '@gaonjs/i18n';
16
20
  import { connectNats, configureJobs, configureEvents, configureBroadcast, resetJobs, resetEvents, resetBroadcast, outboxServiceTxWrapper, ensureOutboxTable, relayOutboxBatch, setOutboxDrainer, setLockBackend, memoryLockBackend, } from '@gaonjs/async';
17
21
  import { createDb, registerConnection, deriveTestDatabaseConfig, destroyAllConnections, setServiceTxWrapper, setCacheBackend, memoryCacheBackend, getConnection, hasConnection, } from '@gaonjs/data';
22
+ /**
23
+ * 문서형 커넥션의 url 에서 DB 경로를 뽑는다. `new URL` 은 멀티 호스트
24
+ * (`mongodb://h1:1,h2:2/db`)에서 포트 파싱이 깨지므로 스킴·호스트를 문자열로 벗긴다
25
+ * (adapter-mongo 의 urlHasDbPath 와 같은 이유 · 결정 364).
26
+ */
27
+ function mongoDbNameFromUrl(url) {
28
+ const noScheme = url.replace(/^mongodb(\+srv)?:\/\//, '');
29
+ return (noScheme.split('/').slice(1).join('/').split('?')[0] ?? '').trim();
30
+ }
31
+ /**
32
+ * 문서형(mongodb) 커넥션을 테스트용으로 파생한다 — SQL 의 `<db>_test`(결정 111)와 대칭.
33
+ * 몽고는 CREATE DATABASE 가 없어(첫 쓰기에 생성) 미리 만들 것이 없고, 이름만 갈라도
34
+ * 개발 DB 를 테스트가 건드리지 않는다. `database` 를 채워 돌려주면 adapter-mongo 가
35
+ * dbName 으로 우선 적용한다(결정 364 — url 경로보다 database 가 이긴다).
36
+ *
37
+ * url·database 가 둘 다 없으면 그대로 돌려준다 — openMongoConnection 이 무신호
38
+ * 오배선(기본 DB `test`)을 fail-loud 로 막는 자기 안내를 그대로 내게 둔다(결정 335).
39
+ */
40
+ export function deriveMongoTestConfig(cfg) {
41
+ const base = cfg.database ?? (cfg.url ? mongoDbNameFromUrl(cfg.url) : '');
42
+ if (!base)
43
+ return cfg;
44
+ return { ...cfg, database: base.endsWith('_test') ? base : `${base}_test` };
45
+ }
18
46
  /**
19
47
  * 테스트용 DB 커넥션 + DB 외 배터리(mail·storage·i18n)를 배선한다(결정 111·136).
20
48
  * 각 커넥션을 `<db>_test` 로 파생해 poolMax:1 로 붙이고, 스토리지·메일을 테스트
@@ -22,13 +50,24 @@ import { createDb, registerConnection, deriveTestDatabaseConfig, destroyAllConne
22
50
  */
23
51
  export async function connectTestDatabase(cwd = process.cwd()) {
24
52
  const config = await loadGaonConfig(cwd);
53
+ // 문서형(mongodb) 커넥션을 하나라도 열었는지 — close() 에서 몽고 레지스트리를 닫을지 결정한다
54
+ // (wireDomain 의 mongoOpened 와 대칭 · 결정 280).
55
+ let mongoOpened = false;
25
56
  if (config.db) {
26
57
  for (const [key, cfg] of Object.entries(config.db)) {
27
58
  const base = cfg;
28
- // 결정 279(§7.3): 문서형(mongodb)은 SQL 테스트 프로비저닝(<db>_test + CREATE DATABASE)을
29
- // 타지 않는다 — 몽고 테스트 격리는 전용 DB + deleteMany 통합 테스트가 직접 수행한다.
30
- if (base.adapter === 'mongodb')
59
+ // 결정 279(§7.3): 문서형(mongodb)은 SQL 테스트 프로비저닝(CREATE DATABASE + 마이그레이션)을
60
+ // 타지 않는다 — 몽고는 쓰기에 DB 생기고 격리는테스트의 deleteMany 한다.
61
+ // 다만 **등록은 한다** — 이전엔 통째로 continue 라 테스트 안 collection() 호출이
62
+ // "Mongo 커넥션 '<키>' 이(가) 등록되지 않았습니다" 로 깨졌다(serve·work 는 wireDomain 이
63
+ // 여는데 테스트 레인만 빠진 비대칭 · 결정 136 의 "테스트에서만 깨지던" 사각과 동형).
64
+ // 이름은 `<db>_test` 로 갈라 개발 DB 를 테스트가 건드리지 않게 한다(SQL 대칭).
65
+ if (base.adapter === 'mongodb') {
66
+ const { openMongoConnection } = await import('@gaonjs/adapter-mongo');
67
+ await openMongoConnection(key, deriveMongoTestConfig(base));
68
+ mongoOpened = true;
31
69
  continue;
70
+ }
32
71
  const testCfg = deriveTestDatabaseConfig({ ...base, poolMax: 1 });
33
72
  registerConnection(key, createDb(testCfg), base.adapter);
34
73
  }
@@ -74,6 +113,12 @@ export async function connectTestDatabase(cwd = process.cwd()) {
74
113
  return {
75
114
  close: async () => {
76
115
  await destroyAllConnections();
116
+ if (mongoOpened) {
117
+ // 결정 280: 문서형 커넥션이 열렸으면 몽고 레지스트리도 닫는다(SQL 과 대칭 · 배선 역순).
118
+ // 안 닫으면 열린 소켓이 이벤트 루프를 붙잡아 vitest 프로세스가 종료하지 못한다.
119
+ const { closeMongoConnections } = await import('@gaonjs/adapter-mongo');
120
+ await closeMongoConnections();
121
+ }
77
122
  resetStorage();
78
123
  resetI18n();
79
124
  // 결정 249: 락·캐시 백엔드 해제(다음 테스트 파일로 상태 누출 방지 · wireDomain.closeDomain 대칭).
package/dist/wire.js CHANGED
@@ -401,6 +401,11 @@ async function assembleApp(config, root, domain, redis, nats) {
401
401
  apps: specs,
402
402
  version: config.web?.assetsVersion,
403
403
  cookieSecret: config.web?.cookieSecret,
404
+ // 결정 431: 프로세스 공용 redis(gaon.config 의 redis)를 web 에 넘긴다 — seal 의 replay
405
+ // nonce store 가 **세션 없는 앱**에서도 공유 store 를 타게 하는 폴백이다. 이전엔 seal 이
406
+ // spec.session?.redis 만 봐서, REDIS_URL 을 구성해도 세션을 안 쓰는 seal 앱(JWT API)은
407
+ // in-memory nonce(프로세스별 격리)로 조용히 떨어졌다. 세션 저장소 배선은 그대로다.
408
+ redis,
404
409
  // 결정 159(W1): i18n 설정이 있으면 매 요청 로케일을 협상해 ALS 에 심는다(자동 배선).
405
410
  // createApp 의 onRequest 슬롯이 이 통로다(web↔i18n 결합 회피). 이게 없으면
406
411
  // detectLanguage·enterLanguage 가 죽은 코드라 t() 가 항상 fallback 이었다(반쪽 배선).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gaonjs/config",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
4
4
  "description": "Gaon 루트 설정 로더·자동 배선 (gaon.config.ts)",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,14 +30,14 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "ioredis": "^5.4.1",
33
- "@gaonjs/adapter-mongo": "0.4.0",
34
- "@gaonjs/async": "0.18.0",
35
- "@gaonjs/core": "0.2.4",
33
+ "@gaonjs/adapter-mongo": "0.4.2",
36
34
  "@gaonjs/i18n": "0.3.0",
35
+ "@gaonjs/data": "0.25.2",
36
+ "@gaonjs/async": "0.18.1",
37
+ "@gaonjs/core": "0.2.4",
37
38
  "@gaonjs/mail": "0.5.0",
38
- "@gaonjs/data": "0.25.0",
39
39
  "@gaonjs/storage": "0.1.5",
40
- "@gaonjs/web": "0.29.0"
40
+ "@gaonjs/web": "0.30.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "fastify": "^5.0.0"