@xfilecom/xframe 0.1.13 → 0.1.14
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/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Nest API (`@xfilecom/backend-core`) + Vite/React client·admin (`@xfilecom/front
|
|
|
16
16
|
|
|
17
17
|
## URLs
|
|
18
18
|
|
|
19
|
-
- API: `http://localhost:3000` — `GET /health` (`AppService`:
|
|
19
|
+
- API: `http://localhost:3000` — `GET /health` (`AppService`: DB 로드·연결 여부만; 쿼리 패턴은 `docs/DATABASE.md`)
|
|
20
20
|
- Client: `http://localhost:3001` — `CommonResponse` 형태로 `/health` 표시
|
|
21
21
|
- Admin: `http://localhost:3002`
|
|
22
22
|
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { Controller, Get } from '@nestjs/common';
|
|
2
|
-
import { Public } from '@xfilecom/backend-core';
|
|
2
|
+
import { ControllerHelpers, Public } from '@xfilecom/backend-core';
|
|
3
3
|
import { AppService } from './app.service';
|
|
4
4
|
|
|
5
5
|
@Controller()
|
|
6
6
|
export class AppController {
|
|
7
|
-
constructor(
|
|
7
|
+
constructor(
|
|
8
|
+
private readonly appService: AppService,
|
|
9
|
+
private readonly controllerHelpers: ControllerHelpers,
|
|
10
|
+
) {}
|
|
8
11
|
|
|
9
12
|
@Public()
|
|
10
13
|
@Get('health')
|
|
11
14
|
health() {
|
|
12
|
-
return this.appService.getHealth();
|
|
15
|
+
return this.controllerHelpers.success(this.appService.getHealth());
|
|
13
16
|
}
|
|
14
17
|
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { Injectable, Optional } from '@nestjs/common';
|
|
2
|
-
import { sql } from 'drizzle-orm';
|
|
3
2
|
import { DatabaseService } from '@xfilecom/backend-core';
|
|
4
|
-
import { appMeta } from '../../../shared/schema';
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* DB 사용은 backend-core 에서 두 가지가 있습니다.
|
|
8
6
|
*
|
|
9
|
-
* 1. **DatabaseService** — `this.database.db` 로 Drizzle API
|
|
10
|
-
* 2. **DatabaseQuery** — `findOne` / `count` / `select` 등 헬퍼.
|
|
7
|
+
* 1. **DatabaseService** — `this.database.db` 로 Drizzle API 직접.
|
|
8
|
+
* 2. **DatabaseQuery** — `findOne` / `count` / `select` 등 헬퍼.
|
|
11
9
|
*
|
|
12
|
-
* `
|
|
10
|
+
* `GET /health` 는 특정 테이블을 가정하지 않음 (`db:pull` 등으로 스키마가 바뀌어도 깨지지 않게).
|
|
11
|
+
* 도메인 쿼리는 별도 서비스에서 스키마 심볼·`DatabaseQuery` 로 작성하면 됨. → `docs/DATABASE.md` §3.
|
|
13
12
|
*/
|
|
14
13
|
@Injectable()
|
|
15
14
|
export class AppService {
|
|
@@ -20,48 +19,20 @@ export class AppService {
|
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
|
-
* `GET /health
|
|
22
|
+
* `GET /health`. `core.database.auto: false` 이면 DB 모듈 미로드 → optional 미주입.
|
|
24
23
|
*/
|
|
25
|
-
|
|
24
|
+
getHealth(): {
|
|
26
25
|
ok: true;
|
|
27
26
|
service: string;
|
|
28
|
-
database: {
|
|
29
|
-
|
|
30
|
-
connected: boolean;
|
|
31
|
-
/** Drizzle 직접 `count(*)` — 동일 결과: `DatabaseQuery.count('appMeta')` */
|
|
32
|
-
rowCount?: number;
|
|
33
|
-
sampleTable?: string;
|
|
34
|
-
};
|
|
35
|
-
}> {
|
|
36
|
-
const sampleTable = 'appMeta';
|
|
27
|
+
database: { moduleLoaded: boolean; connected: boolean };
|
|
28
|
+
} {
|
|
37
29
|
const service = this.serviceLabel();
|
|
38
30
|
const moduleLoaded = this.database !== undefined;
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
ok: true,
|
|
42
|
-
service,
|
|
43
|
-
database: { moduleLoaded, connected: false, sampleTable },
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
let rowCount: number | undefined;
|
|
47
|
-
try {
|
|
48
|
-
const db = this.database.db;
|
|
49
|
-
const [row] = await db
|
|
50
|
-
.select({ c: sql<number>`count(*)` })
|
|
51
|
-
.from(appMeta);
|
|
52
|
-
rowCount = Number(row?.c ?? 0);
|
|
53
|
-
} catch {
|
|
54
|
-
rowCount = undefined;
|
|
55
|
-
}
|
|
31
|
+
const connected = moduleLoaded && this.database.isConnected();
|
|
56
32
|
return {
|
|
57
33
|
ok: true,
|
|
58
34
|
service,
|
|
59
|
-
database: {
|
|
60
|
-
moduleLoaded,
|
|
61
|
-
connected: true,
|
|
62
|
-
rowCount,
|
|
63
|
-
sampleTable,
|
|
64
|
-
},
|
|
35
|
+
database: { moduleLoaded, connected },
|
|
65
36
|
};
|
|
66
37
|
}
|
|
67
38
|
}
|
|
@@ -32,7 +32,7 @@ xframe 프로젝트는 **`@xfilecom/backend-core`** 가 MySQL 풀과 Drizzle 인
|
|
|
32
32
|
| **타입** | 스키마 심볼 import (`appMeta` 등) — 권장 | 테이블 키는 문자열 (`'appMeta'`) |
|
|
33
33
|
| **언제** | 복잡한 조인·raw·Drizzle 문서 그대로 | 단순 CRUD·페이지네이션·object `where` |
|
|
34
34
|
|
|
35
|
-
스캐폴드 **`apps/api/src/app.service.ts`**
|
|
35
|
+
스캐폴드 **`apps/api/src/app.service.ts`** 의 `GET /health` 는 **DB 모듈 로드 여부·연결 여부**만 돌려주며, 어떤 테이블도 가정하지 않습니다. 실제 쿼리는 아래 패턴으로 별도 서비스를 두면 됩니다.
|
|
36
36
|
|
|
37
37
|
### A. Drizzle API 직접 (`DatabaseService.db`)
|
|
38
38
|
|
|
@@ -98,6 +98,11 @@ export class AppModule {}
|
|
|
98
98
|
|
|
99
99
|
`DatabaseModule` 을 다시 import 할 필요는 없습니다.
|
|
100
100
|
|
|
101
|
+
## 공통 응답 (`CommonResponseDto`)
|
|
102
|
+
|
|
103
|
+
`CoreModule.forHttpApi` 는 기본으로 **`ResponseTransformInterceptor`** 를 켜서, 컨트롤러가 객체만 반환해도 `{ code, data, meta?, error }` 형태로 감쌉니다.
|
|
104
|
+
그래도 **`ControllerHelpers.success(payload)`** 로 `CommonResponseDto` 를 직접 반환하는 편이 의도가 분명합니다. `CoreModule` 이 `@Global()` 이라 **`ControllerHelpers` 는 주입만 하면 됩니다** — `apps/api/src/app.controller.ts` 의 `GET /health` 가 그 패턴입니다.
|
|
105
|
+
|
|
101
106
|
## 5. Drizzle Kit (루트에서 실행)
|
|
102
107
|
|
|
103
108
|
프로젝트 **루트**에서 스크립트를 실행합니다 (`process.cwd()` 가 루트여야 `drizzle.env.ts` 가 YAML 을 찾습니다).
|
package/template/.env.example
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
# Nest API·Drizzle 부트스트랩은 루트 .env 를 읽지 않음. DB 등은 `shared/config/api/application*.yml` 기준.
|
|
2
|
-
# 기본 CONFIG_SOURCE=yaml → 셸에서 export 한 DB_* 로 YAML 이 바뀌지 않음. 덮어쓰기: CONFIG_SOURCE=yamlWithEnvOverrides
|
|
3
|
-
#
|
|
4
|
-
# (선택) 로컬 도구용으로만 .env 를 쓸 경우 — 앱/ drizzle-kit 은 자동 로드하지 않음.
|
|
5
|
-
#
|
|
6
|
-
# 접속 오류 시: GUI 와 동일한 host·user·password·database 이름을 YAML 에 맞출 것.
|