11import 'dotenv/config' ;
22
3+ import http from 'node:http' ;
34import os from 'node:os' ;
45import path from 'node:path' ;
56
@@ -13,6 +14,7 @@ import {
1314 initServices ,
1415 runMigrations ,
1516} from './app' ;
17+ import { log } from './middleware/logger' ;
1618import {
1719 buildBackendRouteRegistrations ,
1820 loadModulesFromDisk ,
@@ -28,10 +30,7 @@ applyConfigToEnv();
2830// ── 환경변수 검증 (누락·오류 시 즉시 종료) ────────────────────
2931const env = validateEnv ( process . env ) ;
3032
31- const BOOTSTRAP_MESSAGE = 'Fieldstack API bootstrap initialized' ;
32-
33- console . log ( BOOTSTRAP_MESSAGE ) ;
34- console . log ( `[fieldstack][api] env: ${ env . NODE_ENV } ` ) ;
33+ log . info ( 'api' , `bootstrap initialized — env: ${ env . NODE_ENV } ` ) ;
3534// modules/ 디렉터리는 프로젝트 루트 기준 (apps/api/src → ../../../modules)
3635const MODULES_DIR = path . join ( __dirname , '..' , '..' , '..' , 'modules' ) ;
3736
@@ -84,29 +83,36 @@ function printSetupBanner(apiPort: number, isDev: boolean) {
8483// ── Setup 모드 ─────────────────────────────────────────────────
8584// installed.lock 없을 때 → Setup 마법사만 서빙
8685async function startSetup ( ) {
87- console . log ( '[fieldstack][ api] *** SETUP MODE — installation wizard active ***' ) ;
86+ log . warn ( ' api' , ` SETUP MODE — installation wizard active` ) ;
8887 const app = createSetupApp ( ) ;
8988 finalizeApp ( app ) ;
90- app . listen ( env . PORT , ( ) => {
89+ const server = http . createServer ( app ) ;
90+ server . listen ( env . PORT , ( ) => {
9191 printSetupBanner ( env . PORT , env . NODE_ENV !== 'production' ) ;
9292 } ) ;
93+ process . once ( 'SIGINT' , ( ) => { server . close ( ( ) => process . exit ( 0 ) ) ; } ) ;
94+ process . once ( 'SIGTERM' , ( ) => { server . close ( ( ) => process . exit ( 0 ) ) ; } ) ;
9395}
9496
9597// ── 앱 모드 ────────────────────────────────────────────────────
9698// DB 초기화 → 마이그레이션 → 서비스 초기화 → 모듈 로드 → 서버 시작
9799async function startApp ( ) {
98- let services ;
100+ let services : Awaited < ReturnType < typeof initServices > > | undefined ;
99101
100102 if ( env . DB_PROVIDER === 'postgres' && env . DATABASE_URL ) {
103+ log . info ( 'db' , `connecting (postgres)…` ) ;
101104 const db = await initDb ( ) ;
105+ log . info ( 'db' , `running migrations…` ) ;
102106 await runMigrations ( db ) ;
103107 services = await initServices ( db ) ;
104- console . log ( '[fieldstack][api] DB initialized and migrations applied' ) ;
108+ log . success ( 'db' , `postgres ready` ) ;
105109 } else if ( env . DB_PROVIDER === 'sqlite' ) {
110+ log . info ( 'db' , `connecting (sqlite)…` ) ;
106111 const db = await initDb ( ) ;
112+ log . info ( 'db' , `running migrations…` ) ;
107113 await runMigrations ( db ) ;
108114 services = await initServices ( db ) ;
109- console . log ( '[fieldstack][api] SQLite DB initialized and migrations applied' ) ;
115+ log . success ( 'db' , `sqlite ready` ) ;
110116 }
111117
112118 let app ;
@@ -125,24 +131,42 @@ async function startApp() {
125131
126132 const depIssues = validateModuleDependencies ( manifests ) ;
127133 if ( depIssues . length > 0 ) {
128- console . warn ( '[fieldstack][ loader] dependency issues detected:' ) ;
134+ log . warn ( 'loader' , ` dependency issues detected` ) ;
129135 for ( const issue of depIssues ) {
130- console . warn (
131- ` - "${ issue . moduleName } " missing: ${ issue . missingDependencies . join ( ', ' ) } ` ,
132- ) ;
136+ log . warn ( 'loader' , ` "${ issue . moduleName } " missing: ${ issue . missingDependencies . join ( ', ' ) } ` ) ;
133137 }
134138 }
135139
136140 const registrations = buildBackendRouteRegistrations ( manifests ) ;
141+ const enabledCount = manifests . filter ( ( m ) => m . enabled ) . length ;
142+ log . info ( 'loader' , `loading ${ enabledCount } module(s)…` ) ;
137143 await loadModulesIntoRegistry ( registrations , manifests , MODULES_DIR , services ) ;
144+ log . success ( 'loader' , `${ enabledCount } module(s) mounted` ) ;
138145 }
139146
140147 // ── Error handler (반드시 모든 라우트 등록 후 마지막) ────────
141148 finalizeApp ( app ) ;
142149
143- app . listen ( env . PORT , ( ) => {
144- console . log ( `[fieldstack][api] server listening on http://localhost:${ env . PORT } ` ) ;
150+ const server = http . createServer ( app ) ;
151+
152+ server . listen ( env . PORT , ( ) => {
153+ log . success ( 'api' , `server ready → http://localhost:${ env . PORT } ` ) ;
145154 } ) ;
155+
156+ // ── Graceful shutdown ─────────────────────────────────────────
157+ const shutdown = ( ) => {
158+ log . info ( 'api' , `shutting down…` ) ;
159+ server . close ( ( ) => {
160+ if ( services ) {
161+ services . db . disconnect ( ) . finally ( ( ) => process . exit ( 0 ) ) ;
162+ } else {
163+ process . exit ( 0 ) ;
164+ }
165+ } ) ;
166+ } ;
167+
168+ process . once ( 'SIGINT' , shutdown ) ;
169+ process . once ( 'SIGTERM' , shutdown ) ;
146170}
147171
148172// ── 진입점 ──────────────────────────────────────────────────────
@@ -151,6 +175,6 @@ const shouldSetup = !isInstalled();
151175const boot = shouldSetup ? startSetup : startApp ;
152176
153177boot ( ) . catch ( ( err ) => {
154- console . error ( '[fieldstack][ api] startup failed:' , err ) ;
178+ log . error ( 'api' , ` startup failed` , err ) ;
155179 process . exit ( 1 ) ;
156180} ) ;
0 commit comments