@spfn/core 0.1.0-alpha.82 → 0.1.0-alpha.84
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/cache/index.js +6 -136
- package/dist/cache/index.js.map +1 -1
- package/dist/codegen/generators/index.js +6 -134
- package/dist/codegen/generators/index.js.map +1 -1
- package/dist/codegen/index.d.ts +5 -0
- package/dist/codegen/index.js +21 -145
- package/dist/codegen/index.js.map +1 -1
- package/dist/db/index.d.ts +1 -0
- package/dist/db/index.js +41 -135
- package/dist/db/index.js.map +1 -1
- package/dist/env/index.js +6 -134
- package/dist/env/index.js.map +1 -1
- package/dist/events/index.d.ts +183 -0
- package/dist/events/index.js +77 -0
- package/dist/events/index.js.map +1 -0
- package/dist/index.js +174 -180
- package/dist/index.js.map +1 -1
- package/dist/logger/index.d.ts +90 -34
- package/dist/logger/index.js +7 -137
- package/dist/logger/index.js.map +1 -1
- package/dist/middleware/index.js +22 -138
- package/dist/middleware/index.js.map +1 -1
- package/dist/route/index.js +12 -152
- package/dist/route/index.js.map +1 -1
- package/dist/server/index.d.ts +110 -4
- package/dist/server/index.js +174 -180
- package/dist/server/index.js.map +1 -1
- package/package.json +7 -4
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import pino from 'pino';
|
|
2
1
|
import { readFileSync, existsSync, readdirSync, statSync, mkdirSync, accessSync, constants, writeFileSync, unlinkSync, createWriteStream, renameSync } from 'fs';
|
|
3
2
|
import { join, dirname, relative, basename } from 'path';
|
|
4
3
|
import { config } from 'dotenv';
|
|
@@ -24,76 +23,6 @@ var __export = (target, all) => {
|
|
|
24
23
|
for (var name in all)
|
|
25
24
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
26
25
|
};
|
|
27
|
-
var PinoAdapter;
|
|
28
|
-
var init_pino = __esm({
|
|
29
|
-
"src/logger/adapters/pino.ts"() {
|
|
30
|
-
PinoAdapter = class _PinoAdapter {
|
|
31
|
-
logger;
|
|
32
|
-
constructor(config) {
|
|
33
|
-
const isDevelopment = process.env.NODE_ENV === "development";
|
|
34
|
-
const transport = isDevelopment ? {
|
|
35
|
-
target: "pino-pretty",
|
|
36
|
-
options: {
|
|
37
|
-
colorize: true,
|
|
38
|
-
translateTime: "HH:MM:ss.l",
|
|
39
|
-
ignore: "pid,hostname",
|
|
40
|
-
singleLine: false,
|
|
41
|
-
messageFormat: "{module} {msg}",
|
|
42
|
-
errorLikeObjectKeys: ["err", "error"]
|
|
43
|
-
}
|
|
44
|
-
} : void 0;
|
|
45
|
-
try {
|
|
46
|
-
this.logger = pino({
|
|
47
|
-
level: config.level,
|
|
48
|
-
// 기본 필드
|
|
49
|
-
base: config.module ? { module: config.module } : void 0,
|
|
50
|
-
// Transport (pretty print in development if available)
|
|
51
|
-
transport
|
|
52
|
-
});
|
|
53
|
-
} catch (error) {
|
|
54
|
-
this.logger = pino({
|
|
55
|
-
level: config.level,
|
|
56
|
-
base: config.module ? { module: config.module } : void 0
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
child(module) {
|
|
61
|
-
const childLogger = new _PinoAdapter({ level: this.logger.level, module });
|
|
62
|
-
childLogger.logger = this.logger.child({ module });
|
|
63
|
-
return childLogger;
|
|
64
|
-
}
|
|
65
|
-
debug(message, context) {
|
|
66
|
-
this.logger.debug(context || {}, message);
|
|
67
|
-
}
|
|
68
|
-
info(message, context) {
|
|
69
|
-
this.logger.info(context || {}, message);
|
|
70
|
-
}
|
|
71
|
-
warn(message, errorOrContext, context) {
|
|
72
|
-
if (errorOrContext instanceof Error) {
|
|
73
|
-
this.logger.warn({ err: errorOrContext, ...context }, message);
|
|
74
|
-
} else {
|
|
75
|
-
this.logger.warn(errorOrContext || {}, message);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
error(message, errorOrContext, context) {
|
|
79
|
-
if (errorOrContext instanceof Error) {
|
|
80
|
-
this.logger.error({ err: errorOrContext, ...context }, message);
|
|
81
|
-
} else {
|
|
82
|
-
this.logger.error(errorOrContext || {}, message);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
fatal(message, errorOrContext, context) {
|
|
86
|
-
if (errorOrContext instanceof Error) {
|
|
87
|
-
this.logger.fatal({ err: errorOrContext, ...context }, message);
|
|
88
|
-
} else {
|
|
89
|
-
this.logger.fatal(errorOrContext || {}, message);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
async close() {
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
26
|
|
|
98
27
|
// src/logger/types.ts
|
|
99
28
|
var LOG_LEVEL_PRIORITY;
|
|
@@ -769,7 +698,7 @@ var init_config = __esm({
|
|
|
769
698
|
}
|
|
770
699
|
});
|
|
771
700
|
|
|
772
|
-
// src/logger/
|
|
701
|
+
// src/logger/factory.ts
|
|
773
702
|
function initializeTransports() {
|
|
774
703
|
const transports = [];
|
|
775
704
|
const consoleConfig = getConsoleConfig();
|
|
@@ -780,89 +709,19 @@ function initializeTransports() {
|
|
|
780
709
|
}
|
|
781
710
|
return transports;
|
|
782
711
|
}
|
|
783
|
-
var CustomAdapter;
|
|
784
|
-
var init_custom = __esm({
|
|
785
|
-
"src/logger/adapters/custom.ts"() {
|
|
786
|
-
init_logger();
|
|
787
|
-
init_console();
|
|
788
|
-
init_file();
|
|
789
|
-
init_config();
|
|
790
|
-
CustomAdapter = class _CustomAdapter {
|
|
791
|
-
logger;
|
|
792
|
-
constructor(config) {
|
|
793
|
-
this.logger = new Logger({
|
|
794
|
-
level: config.level,
|
|
795
|
-
module: config.module,
|
|
796
|
-
transports: initializeTransports()
|
|
797
|
-
});
|
|
798
|
-
}
|
|
799
|
-
child(module) {
|
|
800
|
-
const adapter = new _CustomAdapter({ level: this.logger.level, module });
|
|
801
|
-
adapter.logger = this.logger.child(module);
|
|
802
|
-
return adapter;
|
|
803
|
-
}
|
|
804
|
-
debug(message, context) {
|
|
805
|
-
this.logger.debug(message, context);
|
|
806
|
-
}
|
|
807
|
-
info(message, context) {
|
|
808
|
-
this.logger.info(message, context);
|
|
809
|
-
}
|
|
810
|
-
warn(message, errorOrContext, context) {
|
|
811
|
-
if (errorOrContext instanceof Error) {
|
|
812
|
-
this.logger.warn(message, errorOrContext, context);
|
|
813
|
-
} else {
|
|
814
|
-
this.logger.warn(message, errorOrContext);
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
error(message, errorOrContext, context) {
|
|
818
|
-
if (errorOrContext instanceof Error) {
|
|
819
|
-
this.logger.error(message, errorOrContext, context);
|
|
820
|
-
} else {
|
|
821
|
-
this.logger.error(message, errorOrContext);
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
fatal(message, errorOrContext, context) {
|
|
825
|
-
if (errorOrContext instanceof Error) {
|
|
826
|
-
this.logger.fatal(message, errorOrContext, context);
|
|
827
|
-
} else {
|
|
828
|
-
this.logger.fatal(message, errorOrContext);
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
async close() {
|
|
832
|
-
await this.logger.close();
|
|
833
|
-
}
|
|
834
|
-
};
|
|
835
|
-
}
|
|
836
|
-
});
|
|
837
|
-
|
|
838
|
-
// src/logger/adapter-factory.ts
|
|
839
|
-
function createAdapter(type) {
|
|
840
|
-
const level = getDefaultLogLevel();
|
|
841
|
-
switch (type) {
|
|
842
|
-
case "pino":
|
|
843
|
-
return new PinoAdapter({ level });
|
|
844
|
-
case "custom":
|
|
845
|
-
return new CustomAdapter({ level });
|
|
846
|
-
default:
|
|
847
|
-
return new PinoAdapter({ level });
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
function getAdapterType() {
|
|
851
|
-
const adapterEnv = process.env.LOGGER_ADAPTER;
|
|
852
|
-
if (adapterEnv === "custom" || adapterEnv === "pino") {
|
|
853
|
-
return adapterEnv;
|
|
854
|
-
}
|
|
855
|
-
return "pino";
|
|
856
|
-
}
|
|
857
712
|
function initializeLogger() {
|
|
858
713
|
validateConfig();
|
|
859
|
-
return
|
|
714
|
+
return new Logger({
|
|
715
|
+
level: getDefaultLogLevel(),
|
|
716
|
+
transports: initializeTransports()
|
|
717
|
+
});
|
|
860
718
|
}
|
|
861
719
|
var logger;
|
|
862
|
-
var
|
|
863
|
-
"src/logger/
|
|
864
|
-
|
|
865
|
-
|
|
720
|
+
var init_factory = __esm({
|
|
721
|
+
"src/logger/factory.ts"() {
|
|
722
|
+
init_logger();
|
|
723
|
+
init_console();
|
|
724
|
+
init_file();
|
|
866
725
|
init_config();
|
|
867
726
|
logger = initializeLogger();
|
|
868
727
|
}
|
|
@@ -871,7 +730,8 @@ var init_adapter_factory = __esm({
|
|
|
871
730
|
// src/logger/index.ts
|
|
872
731
|
var init_logger2 = __esm({
|
|
873
732
|
"src/logger/index.ts"() {
|
|
874
|
-
|
|
733
|
+
init_factory();
|
|
734
|
+
init_logger();
|
|
875
735
|
}
|
|
876
736
|
});
|
|
877
737
|
|
|
@@ -1592,7 +1452,7 @@ async function createDatabaseFromEnv(options) {
|
|
|
1592
1452
|
}
|
|
1593
1453
|
}
|
|
1594
1454
|
var dbLogger2;
|
|
1595
|
-
var
|
|
1455
|
+
var init_factory2 = __esm({
|
|
1596
1456
|
"src/db/manager/factory.ts"() {
|
|
1597
1457
|
init_logger2();
|
|
1598
1458
|
init_env();
|
|
@@ -1708,17 +1568,51 @@ var dbLogger3;
|
|
|
1708
1568
|
var init_health_check = __esm({
|
|
1709
1569
|
"src/db/manager/health-check.ts"() {
|
|
1710
1570
|
init_logger2();
|
|
1711
|
-
|
|
1571
|
+
init_factory2();
|
|
1712
1572
|
init_global_state();
|
|
1713
1573
|
dbLogger3 = logger.child("database");
|
|
1714
1574
|
}
|
|
1715
1575
|
});
|
|
1716
1576
|
|
|
1717
1577
|
// src/db/manager/manager.ts
|
|
1578
|
+
function getCallerInfo() {
|
|
1579
|
+
try {
|
|
1580
|
+
const stack = new Error().stack;
|
|
1581
|
+
if (!stack) return void 0;
|
|
1582
|
+
const lines = stack.split("\n");
|
|
1583
|
+
for (let i = 3; i < lines.length; i++) {
|
|
1584
|
+
const line = lines[i];
|
|
1585
|
+
if (!line.includes("node_modules") && !line.includes("/db/manager/")) {
|
|
1586
|
+
const match = line.match(/\((.+):(\d+):(\d+)\)/) || line.match(/at (.+):(\d+):(\d+)/);
|
|
1587
|
+
if (match) {
|
|
1588
|
+
const fullPath = match[1];
|
|
1589
|
+
const parts = fullPath.split("/");
|
|
1590
|
+
const srcIndex = parts.lastIndexOf("src");
|
|
1591
|
+
if (srcIndex !== -1) {
|
|
1592
|
+
const relativePath = parts.slice(srcIndex).join("/");
|
|
1593
|
+
return `${relativePath}:${match[2]}`;
|
|
1594
|
+
}
|
|
1595
|
+
return `${fullPath}:${match[2]}`;
|
|
1596
|
+
}
|
|
1597
|
+
break;
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
} catch {
|
|
1601
|
+
}
|
|
1602
|
+
return void 0;
|
|
1603
|
+
}
|
|
1718
1604
|
function getDatabase(type) {
|
|
1719
1605
|
const writeInst = getWriteInstance();
|
|
1720
1606
|
const readInst = getReadInstance();
|
|
1721
|
-
|
|
1607
|
+
if (process.env.DB_DEBUG_TRACE === "true") {
|
|
1608
|
+
const caller = getCallerInfo();
|
|
1609
|
+
dbLogger4.debug("getDatabase() called", {
|
|
1610
|
+
type: type || "write",
|
|
1611
|
+
hasWrite: !!writeInst,
|
|
1612
|
+
hasRead: !!readInst,
|
|
1613
|
+
caller
|
|
1614
|
+
});
|
|
1615
|
+
}
|
|
1722
1616
|
if (type === "read") {
|
|
1723
1617
|
return readInst ?? writeInst;
|
|
1724
1618
|
}
|
|
@@ -1823,7 +1717,7 @@ var dbLogger4;
|
|
|
1823
1717
|
var init_manager = __esm({
|
|
1824
1718
|
"src/db/manager/manager.ts"() {
|
|
1825
1719
|
init_logger2();
|
|
1826
|
-
|
|
1720
|
+
init_factory2();
|
|
1827
1721
|
init_config3();
|
|
1828
1722
|
init_global_state();
|
|
1829
1723
|
init_health_check();
|
|
@@ -1834,7 +1728,7 @@ var init_manager = __esm({
|
|
|
1834
1728
|
// src/db/manager/index.ts
|
|
1835
1729
|
var init_manager2 = __esm({
|
|
1836
1730
|
"src/db/manager/index.ts"() {
|
|
1837
|
-
|
|
1731
|
+
init_factory2();
|
|
1838
1732
|
init_manager();
|
|
1839
1733
|
init_connection();
|
|
1840
1734
|
}
|
|
@@ -3017,6 +2911,22 @@ function generateRequestId() {
|
|
|
3017
2911
|
const randomPart = randomBytes(6).toString("hex");
|
|
3018
2912
|
return `req_${timestamp2}_${randomPart}`;
|
|
3019
2913
|
}
|
|
2914
|
+
function maskSensitiveData2(obj, sensitiveFields, seen = /* @__PURE__ */ new WeakSet()) {
|
|
2915
|
+
if (!obj || typeof obj !== "object") return obj;
|
|
2916
|
+
if (seen.has(obj)) return "[Circular]";
|
|
2917
|
+
seen.add(obj);
|
|
2918
|
+
const lowerFields = sensitiveFields.map((f) => f.toLowerCase());
|
|
2919
|
+
const masked = Array.isArray(obj) ? [...obj] : { ...obj };
|
|
2920
|
+
for (const key in masked) {
|
|
2921
|
+
const lowerKey = key.toLowerCase();
|
|
2922
|
+
if (lowerFields.some((field) => lowerKey.includes(field))) {
|
|
2923
|
+
masked[key] = "***MASKED***";
|
|
2924
|
+
} else if (typeof masked[key] === "object" && masked[key] !== null) {
|
|
2925
|
+
masked[key] = maskSensitiveData2(masked[key], sensitiveFields, seen);
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
return masked;
|
|
2929
|
+
}
|
|
3020
2930
|
function RequestLogger(config) {
|
|
3021
2931
|
const cfg = { ...DEFAULT_CONFIG, ...config };
|
|
3022
2932
|
const apiLogger = logger.child("api");
|
|
@@ -3042,8 +2952,6 @@ function RequestLogger(config) {
|
|
|
3042
2952
|
await next();
|
|
3043
2953
|
const duration = Date.now() - startTime;
|
|
3044
2954
|
const status = c.res.status;
|
|
3045
|
-
const logLevel = status >= 400 ? "warn" : "info";
|
|
3046
|
-
const isSlowRequest = duration >= cfg.slowRequestThreshold;
|
|
3047
2955
|
const logData = {
|
|
3048
2956
|
requestId,
|
|
3049
2957
|
method,
|
|
@@ -3051,9 +2959,25 @@ function RequestLogger(config) {
|
|
|
3051
2959
|
status,
|
|
3052
2960
|
duration
|
|
3053
2961
|
};
|
|
2962
|
+
const isSlowRequest = duration >= cfg.slowRequestThreshold;
|
|
3054
2963
|
if (isSlowRequest) {
|
|
3055
2964
|
logData.slow = true;
|
|
3056
2965
|
}
|
|
2966
|
+
if (status >= 400) {
|
|
2967
|
+
try {
|
|
2968
|
+
const responseBody = await c.res.clone().json();
|
|
2969
|
+
logData.response = responseBody;
|
|
2970
|
+
} catch {
|
|
2971
|
+
}
|
|
2972
|
+
if (["POST", "PUT", "PATCH"].includes(method)) {
|
|
2973
|
+
try {
|
|
2974
|
+
const requestBody = await c.req.json();
|
|
2975
|
+
logData.request = maskSensitiveData2(requestBody, cfg.sensitiveFields);
|
|
2976
|
+
} catch {
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
const logLevel = status >= 500 ? "error" : status >= 400 ? "warn" : "info";
|
|
3057
2981
|
apiLogger[logLevel]("Request completed", logData);
|
|
3058
2982
|
} catch (error) {
|
|
3059
2983
|
const duration = Date.now() - startTime;
|
|
@@ -3256,11 +3180,11 @@ function registerHealthCheckEndpoint(app, config) {
|
|
|
3256
3180
|
}
|
|
3257
3181
|
}
|
|
3258
3182
|
async function executeBeforeRoutesHook(app, config) {
|
|
3259
|
-
if (!config?.beforeRoutes) {
|
|
3183
|
+
if (!config?.lifecycle?.beforeRoutes) {
|
|
3260
3184
|
return;
|
|
3261
3185
|
}
|
|
3262
3186
|
try {
|
|
3263
|
-
await config.beforeRoutes(app);
|
|
3187
|
+
await config.lifecycle.beforeRoutes(app);
|
|
3264
3188
|
} catch (error) {
|
|
3265
3189
|
serverLogger.error("beforeRoutes hook failed", error);
|
|
3266
3190
|
throw new Error("Server initialization failed in beforeRoutes hook");
|
|
@@ -3275,11 +3199,11 @@ async function loadAppRoutes(app, config) {
|
|
|
3275
3199
|
});
|
|
3276
3200
|
}
|
|
3277
3201
|
async function executeAfterRoutesHook(app, config) {
|
|
3278
|
-
if (!config?.afterRoutes) {
|
|
3202
|
+
if (!config?.lifecycle?.afterRoutes) {
|
|
3279
3203
|
return;
|
|
3280
3204
|
}
|
|
3281
3205
|
try {
|
|
3282
|
-
await config.afterRoutes(app);
|
|
3206
|
+
await config.lifecycle.afterRoutes(app);
|
|
3283
3207
|
} catch (error) {
|
|
3284
3208
|
serverLogger.error("afterRoutes hook failed", error);
|
|
3285
3209
|
throw new Error("Server initialization failed in afterRoutes hook");
|
|
@@ -3389,10 +3313,10 @@ async function startServer(config) {
|
|
|
3389
3313
|
port
|
|
3390
3314
|
});
|
|
3391
3315
|
logServerStarted(debug, host, port, finalConfig, timeouts);
|
|
3392
|
-
const shutdownServer = createShutdownHandler(server);
|
|
3316
|
+
const shutdownServer = createShutdownHandler(server, finalConfig);
|
|
3393
3317
|
const shutdown = createGracefulShutdown(shutdownServer, finalConfig);
|
|
3394
3318
|
registerShutdownHandlers(shutdown);
|
|
3395
|
-
|
|
3319
|
+
const serverInstance = {
|
|
3396
3320
|
server,
|
|
3397
3321
|
app,
|
|
3398
3322
|
config: finalConfig,
|
|
@@ -3401,10 +3325,19 @@ async function startServer(config) {
|
|
|
3401
3325
|
await shutdownServer();
|
|
3402
3326
|
}
|
|
3403
3327
|
};
|
|
3328
|
+
if (finalConfig.lifecycle?.afterStart) {
|
|
3329
|
+
serverLogger2.debug("Executing afterStart hook...");
|
|
3330
|
+
try {
|
|
3331
|
+
await finalConfig.lifecycle.afterStart(serverInstance);
|
|
3332
|
+
} catch (error) {
|
|
3333
|
+
serverLogger2.error("afterStart hook failed", error);
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
return serverInstance;
|
|
3404
3337
|
} catch (error) {
|
|
3405
3338
|
const err = error;
|
|
3406
3339
|
serverLogger2.error("Server initialization failed", err);
|
|
3407
|
-
await cleanupOnFailure();
|
|
3340
|
+
await cleanupOnFailure(finalConfig);
|
|
3408
3341
|
throw error;
|
|
3409
3342
|
}
|
|
3410
3343
|
}
|
|
@@ -3442,18 +3375,47 @@ function logMiddlewareOrder(config) {
|
|
|
3442
3375
|
});
|
|
3443
3376
|
}
|
|
3444
3377
|
async function initializeInfrastructure(config) {
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3378
|
+
if (config.lifecycle?.beforeInfrastructure) {
|
|
3379
|
+
serverLogger2.debug("Executing beforeInfrastructure hook...");
|
|
3380
|
+
try {
|
|
3381
|
+
await config.lifecycle.beforeInfrastructure(config);
|
|
3382
|
+
} catch (error) {
|
|
3383
|
+
serverLogger2.error("beforeInfrastructure hook failed", error);
|
|
3384
|
+
throw new Error("Server initialization failed in beforeInfrastructure hook");
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
const shouldInitDatabase = config.infrastructure?.database !== false;
|
|
3388
|
+
if (shouldInitDatabase) {
|
|
3389
|
+
serverLogger2.debug("Initializing database...");
|
|
3390
|
+
await initDatabase(config.database);
|
|
3391
|
+
} else {
|
|
3392
|
+
serverLogger2.debug("Database initialization disabled");
|
|
3393
|
+
}
|
|
3394
|
+
const shouldInitRedis = config.infrastructure?.redis !== false;
|
|
3395
|
+
if (shouldInitRedis) {
|
|
3396
|
+
serverLogger2.debug("Initializing Redis...");
|
|
3397
|
+
await initRedis();
|
|
3398
|
+
} else {
|
|
3399
|
+
serverLogger2.debug("Redis initialization disabled");
|
|
3400
|
+
}
|
|
3401
|
+
if (config.lifecycle?.afterInfrastructure) {
|
|
3402
|
+
serverLogger2.debug("Executing afterInfrastructure hook...");
|
|
3403
|
+
try {
|
|
3404
|
+
await config.lifecycle.afterInfrastructure();
|
|
3405
|
+
} catch (error) {
|
|
3406
|
+
serverLogger2.error("afterInfrastructure hook failed", error);
|
|
3407
|
+
throw new Error("Server initialization failed in afterInfrastructure hook");
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3449
3410
|
}
|
|
3450
3411
|
function startHttpServer(app, host, port) {
|
|
3451
3412
|
serverLogger2.debug(`Starting server on ${host}:${port}...`);
|
|
3452
|
-
|
|
3413
|
+
const server = serve({
|
|
3453
3414
|
fetch: app.fetch,
|
|
3454
3415
|
port,
|
|
3455
3416
|
hostname: host
|
|
3456
3417
|
});
|
|
3418
|
+
return server;
|
|
3457
3419
|
}
|
|
3458
3420
|
function logServerTimeouts(timeouts) {
|
|
3459
3421
|
serverLogger2.info("Server timeouts configured", {
|
|
@@ -3471,7 +3433,7 @@ function logServerStarted(debug, host, port, config, timeouts) {
|
|
|
3471
3433
|
config: startupConfig
|
|
3472
3434
|
});
|
|
3473
3435
|
}
|
|
3474
|
-
function createShutdownHandler(server) {
|
|
3436
|
+
function createShutdownHandler(server, config) {
|
|
3475
3437
|
return async () => {
|
|
3476
3438
|
serverLogger2.debug("Closing HTTP server...");
|
|
3477
3439
|
await new Promise((resolve) => {
|
|
@@ -3480,10 +3442,24 @@ function createShutdownHandler(server) {
|
|
|
3480
3442
|
resolve();
|
|
3481
3443
|
});
|
|
3482
3444
|
});
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3445
|
+
if (config.lifecycle?.beforeShutdown) {
|
|
3446
|
+
serverLogger2.debug("Executing beforeShutdown hook...");
|
|
3447
|
+
try {
|
|
3448
|
+
await config.lifecycle.beforeShutdown();
|
|
3449
|
+
} catch (error) {
|
|
3450
|
+
serverLogger2.error("beforeShutdown hook failed", error);
|
|
3451
|
+
}
|
|
3452
|
+
}
|
|
3453
|
+
const shouldCloseDatabase = config.infrastructure?.database !== false;
|
|
3454
|
+
const shouldCloseRedis = config.infrastructure?.redis !== false;
|
|
3455
|
+
if (shouldCloseDatabase) {
|
|
3456
|
+
serverLogger2.debug("Closing database connections...");
|
|
3457
|
+
await closeDatabase();
|
|
3458
|
+
}
|
|
3459
|
+
if (shouldCloseRedis) {
|
|
3460
|
+
serverLogger2.debug("Closing Redis connections...");
|
|
3461
|
+
await closeRedis();
|
|
3462
|
+
}
|
|
3487
3463
|
serverLogger2.info("Server shutdown completed");
|
|
3488
3464
|
};
|
|
3489
3465
|
}
|
|
@@ -3515,10 +3491,22 @@ function createGracefulShutdown(shutdownServer, config) {
|
|
|
3515
3491
|
};
|
|
3516
3492
|
}
|
|
3517
3493
|
function registerShutdownHandlers(shutdown) {
|
|
3494
|
+
process.setMaxListeners(15);
|
|
3518
3495
|
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
3519
3496
|
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
3520
3497
|
process.on("uncaughtException", (error) => {
|
|
3521
|
-
|
|
3498
|
+
if (error.message?.includes("EADDRINUSE")) {
|
|
3499
|
+
serverLogger2.error("Port conflict detected - detailed trace:", {
|
|
3500
|
+
error: error.message,
|
|
3501
|
+
stack: error.stack,
|
|
3502
|
+
code: error.code,
|
|
3503
|
+
port: error.port,
|
|
3504
|
+
address: error.address,
|
|
3505
|
+
syscall: error.syscall
|
|
3506
|
+
});
|
|
3507
|
+
} else {
|
|
3508
|
+
serverLogger2.error("Uncaught exception", error);
|
|
3509
|
+
}
|
|
3522
3510
|
shutdown("UNCAUGHT_EXCEPTION");
|
|
3523
3511
|
});
|
|
3524
3512
|
process.on("unhandledRejection", (reason, promise) => {
|
|
@@ -3529,11 +3517,17 @@ function registerShutdownHandlers(shutdown) {
|
|
|
3529
3517
|
shutdown("UNHANDLED_REJECTION");
|
|
3530
3518
|
});
|
|
3531
3519
|
}
|
|
3532
|
-
async function cleanupOnFailure() {
|
|
3520
|
+
async function cleanupOnFailure(config) {
|
|
3533
3521
|
try {
|
|
3534
3522
|
serverLogger2.debug("Cleaning up after initialization failure...");
|
|
3535
|
-
|
|
3536
|
-
|
|
3523
|
+
const shouldCleanupDatabase = config.infrastructure?.database !== false;
|
|
3524
|
+
const shouldCleanupRedis = config.infrastructure?.redis !== false;
|
|
3525
|
+
if (shouldCleanupDatabase) {
|
|
3526
|
+
await closeDatabase();
|
|
3527
|
+
}
|
|
3528
|
+
if (shouldCleanupRedis) {
|
|
3529
|
+
await closeRedis();
|
|
3530
|
+
}
|
|
3537
3531
|
serverLogger2.debug("Cleanup completed");
|
|
3538
3532
|
} catch (cleanupError) {
|
|
3539
3533
|
serverLogger2.error("Cleanup failed", cleanupError);
|