@gaonjs/config 0.18.1 → 0.20.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @gaonjs/config
2
2
 
3
- Gaon 루트 설정 로더 · 자동 배선 (§3.3 · M9-A).
3
+ Gaon 루트 설정 로더 · 자동 배선 (§3.3).
4
4
 
5
5
  - `defineConfig()` — 사용자가 `gaon.config.ts` 에서 쓰는 타입 안전 헬퍼
6
6
  - `loadGaonConfig(cwd)` — `<cwd>/gaon.config.ts` 를 동적 import
package/dist/testkit.js CHANGED
@@ -25,6 +25,10 @@ export async function connectTestDatabase(cwd = process.cwd()) {
25
25
  if (config.db) {
26
26
  for (const [key, cfg] of Object.entries(config.db)) {
27
27
  const base = cfg;
28
+ // 결정 279(§7.3): 문서형(mongodb)은 SQL 테스트 프로비저닝(<db>_test + CREATE DATABASE)을
29
+ // 타지 않는다 — 몽고 테스트 격리는 전용 DB + deleteMany 로 각 통합 테스트가 직접 수행한다.
30
+ if (base.adapter === 'mongodb')
31
+ continue;
28
32
  const testCfg = deriveTestDatabaseConfig({ ...base, poolMax: 1 });
29
33
  registerConnection(key, createDb(testCfg), base.adapter);
30
34
  }
package/dist/types.d.ts CHANGED
@@ -140,6 +140,18 @@ export interface AppSessionConfig {
140
140
  * 쓴 defineAppConfig 리터럴이 excess-property 컴파일 에러였다).
141
141
  */
142
142
  readonly csrf?: boolean;
143
+ /**
144
+ * 쿠키 Secure 토글(결정 295). 생략 시 NODE_ENV==='production' 이면 켬. 운영인데
145
+ * 비-TLS(사내 내부망 http 등)로 서빙하면 Secure 쿠키가 안 실려 로그인이 조용히
146
+ * 실패한다 — 그 경우에만 `false` 로 명시한다(웹 레이어는 지원했는데 이 전달
147
+ * 통로가 없어 우회로가 없었다 · 결정 271 csrf 누락과 동형 표류).
148
+ */
149
+ readonly secure?: boolean;
150
+ /**
151
+ * 쿠키 SameSite(결정 295). 생략 시 'lax'. `'none'` 은 스펙상 Secure 필수라
152
+ * secure 가 꺼져 있으면 부팅 에러(웹 레이어 가드 · 브라우저 조용한 쿠키 거부 방지).
153
+ */
154
+ readonly sameSite?: 'lax' | 'strict' | 'none';
143
155
  }
144
156
  /**
145
157
  * 앱별 설정 — apps/<app>/app.config.ts (v0.16 §3.3).
package/dist/wire.js CHANGED
@@ -83,6 +83,9 @@ export async function wireDomain(config, cwd = process.cwd()) {
83
83
  // 0) 타임존 — 어떤 배터리보다 먼저 적용해 이후 Date·로깅·스케줄러가 선언 타임존을 본다(결정 230).
84
84
  applyTimezone(config);
85
85
  let redis;
86
+ // 결정 280: 문서형(mongodb) 커넥션을 하나라도 열었는지 — teardown 에서 몽고 레지스트리를
87
+ // 닫을지 결정한다(adapter-mongo 를 몽고 커넥션이 있을 때만 동적 로드해 SQL 전용 무비용).
88
+ let mongoOpened = false;
86
89
  // 배선 역순 정리 — 백엔드 해제(다음 인스턴스 누출 방지 · 결정 147·148) → redis 종료 → DB·기타.
87
90
  // 성공 시 closeDomain 이, 실패 시 아래 catch 가 같은 경로로 호출한다. 결정 252(결정 250 확장):
88
91
  // 부분 오픈된 핸들(Redis 소켓·DB 커넥션·전역 배터리)을 남긴 채 throw 하면 열린 소켓이 이벤트
@@ -94,6 +97,11 @@ export async function wireDomain(config, cwd = process.cwd()) {
94
97
  if (redis)
95
98
  redis.disconnect();
96
99
  await destroyAllConnections();
100
+ if (mongoOpened) {
101
+ // 결정 280: 문서형 커넥션이 열렸으면 몽고 레지스트리도 닫는다(SQL 과 대칭 · 배선 역순).
102
+ const { closeMongoConnections } = await import('@gaonjs/adapter-mongo');
103
+ await closeMongoConnections();
104
+ }
97
105
  resetStorage();
98
106
  resetI18n();
99
107
  };
@@ -101,6 +109,17 @@ export async function wireDomain(config, cwd = process.cwd()) {
101
109
  // 1) DB 커넥션 — 키별로 등록(main + 명명 커넥션 · §4.5). 실 연결은 첫 쿼리에서(pool lazy).
102
110
  if (config.db) {
103
111
  for (const [key, cfg] of Object.entries(config.db)) {
112
+ // 결정 279·280: 문서형(mongodb)은 Kysely(createDb) 경로를 타지 않고 @gaonjs/adapter-mongo
113
+ // 로 라우팅한다(별도 레지스트리 · Kysely 크로스커넥션 가드 미적용). adapter-mongo 는
114
+ // config·gaonjs 의 hard dep 이라 **항상 설치**되지만(작은 래퍼), 이 분기는 동적 import 라
115
+ // 몽고 커넥션이 있을 때만 모듈을 **로드**한다(SQL 전용은 미로드). 진짜 opt-in 은 mongoose
116
+ // 하나로, adapter-mongo 의 optional peer 라 SQL 전용 프로젝트엔 설치되지 않는다(호출 시 지연 로드).
117
+ if (cfg.adapter === 'mongodb') {
118
+ const { openMongoConnection } = await import('@gaonjs/adapter-mongo');
119
+ await openMongoConnection(key, cfg);
120
+ mongoOpened = true;
121
+ continue;
122
+ }
104
123
  const db = createDb(cfg);
105
124
  registerConnection(key, db, cfg.adapter);
106
125
  }
@@ -327,6 +346,12 @@ async function assembleApp(config, root, domain, redis, nats) {
327
346
  // app.config 의 CSRF 토글을 serve 로 전달한다(SessionOptions.csrf · 명시적으로만 끔).
328
347
  // 이전엔 wireGaon 이 이 필드를 떨궈 documented 토글이 gaon serve 에서 무시됐다.
329
348
  csrf: ac.session.csrf,
349
+ // 결정 295: 쿠키 secure·sameSite 도 전달한다 — 웹 레이어(AppSessionOptions)는
350
+ // 지원했는데 이 통로가 떨궈 운영 비-TLS(secure:false)·sameSite 조정의 우회로가
351
+ // 없었다(결정 271 csrf 누락과 동형). sameSite:'none'+secure 미충족은 웹 레이어가
352
+ // 부팅 에러로 막는다(assertSameSiteSecure).
353
+ secure: ac.session.secure,
354
+ sameSite: ac.session.sameSite,
330
355
  },
331
356
  };
332
357
  }
package/package.json CHANGED
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "name": "@gaonjs/config",
3
- "version": "0.18.1",
3
+ "version": "0.20.0",
4
4
  "description": "Gaon 루트 설정 로더·자동 배선 (gaon.config.ts)",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "homepage": "https://gaonjs.dev",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://git.nyx-zone.com/gaon/framework.git",
11
+ "directory": "packages/config"
12
+ },
8
13
  "engines": {
9
14
  "node": ">=22"
10
15
  },
@@ -25,13 +30,14 @@
25
30
  ],
26
31
  "dependencies": {
27
32
  "ioredis": "^5.4.1",
28
- "@gaonjs/async": "0.15.3",
33
+ "@gaonjs/async": "0.16.0",
34
+ "@gaonjs/adapter-mongo": "0.2.0",
29
35
  "@gaonjs/core": "0.2.4",
36
+ "@gaonjs/i18n": "0.2.4",
37
+ "@gaonjs/data": "0.22.0",
30
38
  "@gaonjs/mail": "0.3.3",
31
39
  "@gaonjs/storage": "0.1.5",
32
- "@gaonjs/data": "0.17.3",
33
- "@gaonjs/web": "0.20.5",
34
- "@gaonjs/i18n": "0.2.4"
40
+ "@gaonjs/web": "0.24.1"
35
41
  },
36
42
  "devDependencies": {
37
43
  "fastify": "^5.0.0"