@superdangerous/app-framework 4.9.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.
Files changed (239) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +652 -0
  3. package/dist/api/logsRouter.d.ts +20 -0
  4. package/dist/api/logsRouter.d.ts.map +1 -0
  5. package/dist/api/logsRouter.js +515 -0
  6. package/dist/api/logsRouter.js.map +1 -0
  7. package/dist/cli/dev-server.d.ts +7 -0
  8. package/dist/cli/dev-server.d.ts.map +1 -0
  9. package/dist/cli/dev-server.js +640 -0
  10. package/dist/cli/dev-server.js.map +1 -0
  11. package/dist/cli/index.d.ts +7 -0
  12. package/dist/cli/index.d.ts.map +1 -0
  13. package/dist/cli/index.js +26 -0
  14. package/dist/cli/index.js.map +1 -0
  15. package/dist/core/StandardServer.d.ts +129 -0
  16. package/dist/core/StandardServer.d.ts.map +1 -0
  17. package/dist/core/StandardServer.js +453 -0
  18. package/dist/core/StandardServer.js.map +1 -0
  19. package/dist/core/apiResponse.d.ts +69 -0
  20. package/dist/core/apiResponse.d.ts.map +1 -0
  21. package/dist/core/apiResponse.js +127 -0
  22. package/dist/core/apiResponse.js.map +1 -0
  23. package/dist/core/healthCheck.d.ts +160 -0
  24. package/dist/core/healthCheck.d.ts.map +1 -0
  25. package/dist/core/healthCheck.js +398 -0
  26. package/dist/core/healthCheck.js.map +1 -0
  27. package/dist/core/index.d.ts +40 -0
  28. package/dist/core/index.d.ts.map +1 -0
  29. package/dist/core/index.js +40 -0
  30. package/dist/core/index.js.map +1 -0
  31. package/dist/core/logger.d.ts +117 -0
  32. package/dist/core/logger.d.ts.map +1 -0
  33. package/dist/core/logger.js +826 -0
  34. package/dist/core/logger.js.map +1 -0
  35. package/dist/core/portUtils.d.ts +71 -0
  36. package/dist/core/portUtils.d.ts.map +1 -0
  37. package/dist/core/portUtils.js +240 -0
  38. package/dist/core/portUtils.js.map +1 -0
  39. package/dist/core/storageService.d.ts +119 -0
  40. package/dist/core/storageService.d.ts.map +1 -0
  41. package/dist/core/storageService.js +405 -0
  42. package/dist/core/storageService.js.map +1 -0
  43. package/dist/desktop/bundler.d.ts +40 -0
  44. package/dist/desktop/bundler.d.ts.map +1 -0
  45. package/dist/desktop/bundler.js +176 -0
  46. package/dist/desktop/bundler.js.map +1 -0
  47. package/dist/desktop/index.d.ts +25 -0
  48. package/dist/desktop/index.d.ts.map +1 -0
  49. package/dist/desktop/index.js +15 -0
  50. package/dist/desktop/index.js.map +1 -0
  51. package/dist/desktop/native-modules.d.ts +66 -0
  52. package/dist/desktop/native-modules.d.ts.map +1 -0
  53. package/dist/desktop/native-modules.js +200 -0
  54. package/dist/desktop/native-modules.js.map +1 -0
  55. package/dist/index.d.ts +29 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +39 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/logging/LogCategories.d.ts +87 -0
  60. package/dist/logging/LogCategories.d.ts.map +1 -0
  61. package/dist/logging/LogCategories.js +205 -0
  62. package/dist/logging/LogCategories.js.map +1 -0
  63. package/dist/middleware/aiErrorHandler.d.ts +31 -0
  64. package/dist/middleware/aiErrorHandler.d.ts.map +1 -0
  65. package/dist/middleware/aiErrorHandler.js +181 -0
  66. package/dist/middleware/aiErrorHandler.js.map +1 -0
  67. package/dist/middleware/auth.d.ts +101 -0
  68. package/dist/middleware/auth.d.ts.map +1 -0
  69. package/dist/middleware/auth.js +230 -0
  70. package/dist/middleware/auth.js.map +1 -0
  71. package/dist/middleware/cors.d.ts +56 -0
  72. package/dist/middleware/cors.d.ts.map +1 -0
  73. package/dist/middleware/cors.js +123 -0
  74. package/dist/middleware/cors.js.map +1 -0
  75. package/dist/middleware/errorHandler.d.ts +13 -0
  76. package/dist/middleware/errorHandler.d.ts.map +1 -0
  77. package/dist/middleware/errorHandler.js +85 -0
  78. package/dist/middleware/errorHandler.js.map +1 -0
  79. package/dist/middleware/fileUpload.d.ts +62 -0
  80. package/dist/middleware/fileUpload.d.ts.map +1 -0
  81. package/dist/middleware/fileUpload.js +175 -0
  82. package/dist/middleware/fileUpload.js.map +1 -0
  83. package/dist/middleware/health.d.ts +48 -0
  84. package/dist/middleware/health.d.ts.map +1 -0
  85. package/dist/middleware/health.js +143 -0
  86. package/dist/middleware/health.js.map +1 -0
  87. package/dist/middleware/index.d.ts +20 -0
  88. package/dist/middleware/index.d.ts.map +1 -0
  89. package/dist/middleware/index.js +18 -0
  90. package/dist/middleware/index.js.map +1 -0
  91. package/dist/middleware/openapi.d.ts +64 -0
  92. package/dist/middleware/openapi.d.ts.map +1 -0
  93. package/dist/middleware/openapi.js +258 -0
  94. package/dist/middleware/openapi.js.map +1 -0
  95. package/dist/middleware/requestLogging.d.ts +22 -0
  96. package/dist/middleware/requestLogging.d.ts.map +1 -0
  97. package/dist/middleware/requestLogging.js +61 -0
  98. package/dist/middleware/requestLogging.js.map +1 -0
  99. package/dist/middleware/session.d.ts +84 -0
  100. package/dist/middleware/session.d.ts.map +1 -0
  101. package/dist/middleware/session.js +189 -0
  102. package/dist/middleware/session.js.map +1 -0
  103. package/dist/middleware/validation.d.ts +1337 -0
  104. package/dist/middleware/validation.d.ts.map +1 -0
  105. package/dist/middleware/validation.js +483 -0
  106. package/dist/middleware/validation.js.map +1 -0
  107. package/dist/services/aiService.d.ts +180 -0
  108. package/dist/services/aiService.d.ts.map +1 -0
  109. package/dist/services/aiService.js +547 -0
  110. package/dist/services/aiService.js.map +1 -0
  111. package/dist/services/conversationStorage.d.ts +38 -0
  112. package/dist/services/conversationStorage.d.ts.map +1 -0
  113. package/dist/services/conversationStorage.js +158 -0
  114. package/dist/services/conversationStorage.js.map +1 -0
  115. package/dist/services/crossPlatformBuffer.d.ts +84 -0
  116. package/dist/services/crossPlatformBuffer.d.ts.map +1 -0
  117. package/dist/services/crossPlatformBuffer.js +246 -0
  118. package/dist/services/crossPlatformBuffer.js.map +1 -0
  119. package/dist/services/index.d.ts +17 -0
  120. package/dist/services/index.d.ts.map +1 -0
  121. package/dist/services/index.js +18 -0
  122. package/dist/services/index.js.map +1 -0
  123. package/dist/services/networkService.d.ts +81 -0
  124. package/dist/services/networkService.d.ts.map +1 -0
  125. package/dist/services/networkService.js +268 -0
  126. package/dist/services/networkService.js.map +1 -0
  127. package/dist/services/queueService.d.ts +112 -0
  128. package/dist/services/queueService.d.ts.map +1 -0
  129. package/dist/services/queueService.js +338 -0
  130. package/dist/services/queueService.js.map +1 -0
  131. package/dist/services/settingsService.d.ts +135 -0
  132. package/dist/services/settingsService.d.ts.map +1 -0
  133. package/dist/services/settingsService.js +425 -0
  134. package/dist/services/settingsService.js.map +1 -0
  135. package/dist/services/systemMonitor.d.ts +208 -0
  136. package/dist/services/systemMonitor.d.ts.map +1 -0
  137. package/dist/services/systemMonitor.js +693 -0
  138. package/dist/services/systemMonitor.js.map +1 -0
  139. package/dist/services/updateService.d.ts +78 -0
  140. package/dist/services/updateService.d.ts.map +1 -0
  141. package/dist/services/updateService.js +252 -0
  142. package/dist/services/updateService.js.map +1 -0
  143. package/dist/services/websocketEvents.d.ts +372 -0
  144. package/dist/services/websocketEvents.d.ts.map +1 -0
  145. package/dist/services/websocketEvents.js +338 -0
  146. package/dist/services/websocketEvents.js.map +1 -0
  147. package/dist/services/websocketServer.d.ts +80 -0
  148. package/dist/services/websocketServer.d.ts.map +1 -0
  149. package/dist/services/websocketServer.js +299 -0
  150. package/dist/services/websocketServer.js.map +1 -0
  151. package/dist/settings/SettingsSchema.d.ts +151 -0
  152. package/dist/settings/SettingsSchema.d.ts.map +1 -0
  153. package/dist/settings/SettingsSchema.js +424 -0
  154. package/dist/settings/SettingsSchema.js.map +1 -0
  155. package/dist/testing/TestServer.d.ts +69 -0
  156. package/dist/testing/TestServer.d.ts.map +1 -0
  157. package/dist/testing/TestServer.js +250 -0
  158. package/dist/testing/TestServer.js.map +1 -0
  159. package/dist/types/index.d.ts +137 -0
  160. package/dist/types/index.d.ts.map +1 -0
  161. package/dist/types/index.js +5 -0
  162. package/dist/types/index.js.map +1 -0
  163. package/dist/utils/appPaths.d.ts +74 -0
  164. package/dist/utils/appPaths.d.ts.map +1 -0
  165. package/dist/utils/appPaths.js +162 -0
  166. package/dist/utils/appPaths.js.map +1 -0
  167. package/dist/utils/fs-utils.d.ts +50 -0
  168. package/dist/utils/fs-utils.d.ts.map +1 -0
  169. package/dist/utils/fs-utils.js +114 -0
  170. package/dist/utils/fs-utils.js.map +1 -0
  171. package/dist/utils/index.d.ts +12 -0
  172. package/dist/utils/index.d.ts.map +1 -0
  173. package/dist/utils/index.js +10 -0
  174. package/dist/utils/index.js.map +1 -0
  175. package/dist/utils/standardConfig.d.ts +61 -0
  176. package/dist/utils/standardConfig.d.ts.map +1 -0
  177. package/dist/utils/standardConfig.js +109 -0
  178. package/dist/utils/standardConfig.js.map +1 -0
  179. package/dist/utils/startupBanner.d.ts +34 -0
  180. package/dist/utils/startupBanner.d.ts.map +1 -0
  181. package/dist/utils/startupBanner.js +169 -0
  182. package/dist/utils/startupBanner.js.map +1 -0
  183. package/dist/utils/startupLogger.d.ts +45 -0
  184. package/dist/utils/startupLogger.d.ts.map +1 -0
  185. package/dist/utils/startupLogger.js +200 -0
  186. package/dist/utils/startupLogger.js.map +1 -0
  187. package/package.json +151 -0
  188. package/src/api/logsRouter.ts +600 -0
  189. package/src/cli/dev-server.ts +803 -0
  190. package/src/cli/index.ts +31 -0
  191. package/src/core/StandardServer.ts +587 -0
  192. package/src/core/apiResponse.ts +202 -0
  193. package/src/core/healthCheck.ts +565 -0
  194. package/src/core/index.ts +80 -0
  195. package/src/core/logger.ts +1092 -0
  196. package/src/core/portUtils.ts +319 -0
  197. package/src/core/storageService.ts +595 -0
  198. package/src/desktop/bundler.ts +271 -0
  199. package/src/desktop/index.ts +18 -0
  200. package/src/desktop/native-modules.ts +289 -0
  201. package/src/index.ts +142 -0
  202. package/src/logging/LogCategories.ts +302 -0
  203. package/src/middleware/aiErrorHandler.ts +278 -0
  204. package/src/middleware/auth.ts +329 -0
  205. package/src/middleware/cors.ts +187 -0
  206. package/src/middleware/errorHandler.ts +103 -0
  207. package/src/middleware/fileUpload.ts +252 -0
  208. package/src/middleware/health.ts +206 -0
  209. package/src/middleware/index.ts +71 -0
  210. package/src/middleware/openapi.ts +305 -0
  211. package/src/middleware/requestLogging.ts +92 -0
  212. package/src/middleware/session.ts +238 -0
  213. package/src/middleware/validation.ts +603 -0
  214. package/src/services/aiService.ts +789 -0
  215. package/src/services/conversationStorage.ts +232 -0
  216. package/src/services/crossPlatformBuffer.ts +341 -0
  217. package/src/services/index.ts +47 -0
  218. package/src/services/networkService.ts +351 -0
  219. package/src/services/queueService.ts +446 -0
  220. package/src/services/settingsService.ts +549 -0
  221. package/src/services/systemMonitor.ts +936 -0
  222. package/src/services/updateService.ts +334 -0
  223. package/src/services/websocketEvents.ts +409 -0
  224. package/src/services/websocketServer.ts +394 -0
  225. package/src/settings/SettingsSchema.ts +664 -0
  226. package/src/testing/TestServer.ts +312 -0
  227. package/src/types/index.ts +154 -0
  228. package/src/utils/appPaths.ts +196 -0
  229. package/src/utils/fs-utils.ts +130 -0
  230. package/src/utils/index.ts +15 -0
  231. package/src/utils/standardConfig.ts +178 -0
  232. package/src/utils/startupBanner.ts +287 -0
  233. package/src/utils/startupLogger.ts +268 -0
  234. package/ui/dist/index.d.mts +1221 -0
  235. package/ui/dist/index.d.ts +1221 -0
  236. package/ui/dist/index.js +73 -0
  237. package/ui/dist/index.js.map +1 -0
  238. package/ui/dist/index.mjs +73 -0
  239. package/ui/dist/index.mjs.map +1 -0
@@ -0,0 +1,565 @@
1
+ /**
2
+ * Health Check Service
3
+ * Provides real-time system health monitoring without intervention
4
+ * Data is informational only - no automatic service stops based on metrics
5
+ */
6
+
7
+ import os from "os";
8
+ import { exec } from "child_process";
9
+ import { promisify } from "util";
10
+ import { Request, Response, Router } from "express";
11
+
12
+ const execAsync = promisify(exec);
13
+
14
+ export interface SystemHealth {
15
+ status: "healthy" | "degraded" | "unhealthy";
16
+ timestamp: string;
17
+ uptime: number;
18
+ environment: string;
19
+ version: string;
20
+ pid: number;
21
+ platform: string;
22
+ nodeVersion: string;
23
+ }
24
+
25
+ export interface SystemMetrics {
26
+ cpu: {
27
+ usage: number;
28
+ count: number;
29
+ model: string;
30
+ speed: number;
31
+ loadAverage: number[];
32
+ };
33
+ memory: {
34
+ total: number;
35
+ used: number;
36
+ free: number;
37
+ percentage: number;
38
+ };
39
+ disk: {
40
+ total: number;
41
+ used: number;
42
+ free: number;
43
+ percentage: number;
44
+ path: string;
45
+ };
46
+ network: {
47
+ interfaces: NetworkInterface[];
48
+ };
49
+ process: {
50
+ pid: number;
51
+ memory: NodeJS.MemoryUsage;
52
+ cpuUsage: NodeJS.CpuUsage;
53
+ uptime: number;
54
+ };
55
+ }
56
+
57
+ export interface NetworkInterface {
58
+ name: string;
59
+ address: string;
60
+ family: string;
61
+ internal: boolean;
62
+ }
63
+
64
+ export interface HealthCheckOptions {
65
+ includeCpu?: boolean;
66
+ includeMemory?: boolean;
67
+ includeDisk?: boolean;
68
+ includeNetwork?: boolean;
69
+ includeProcess?: boolean;
70
+ diskPath?: string;
71
+ customChecks?: CustomHealthCheck[];
72
+ }
73
+
74
+ export interface CustomHealthCheck {
75
+ name: string;
76
+ check: () => Promise<HealthCheckResult>;
77
+ }
78
+
79
+ export interface HealthCheckResult {
80
+ name: string;
81
+ status: "healthy" | "degraded" | "unhealthy";
82
+ message?: string;
83
+ data?: any;
84
+ }
85
+
86
+ export interface DependencyHealth {
87
+ name: string;
88
+ status: "connected" | "disconnected" | "error";
89
+ responseTime?: number;
90
+ error?: string;
91
+ }
92
+
93
+ class HealthCheckService {
94
+ private static instance: HealthCheckService;
95
+ private cpuUsageHistory: number[] = [];
96
+ private memoryUsageHistory: number[] = [];
97
+ private lastCpuInfo: any;
98
+ private metricsInterval?: NodeJS.Timeout;
99
+ private historySize: number = 60; // Keep last 60 data points
100
+
101
+ private constructor() {
102
+ this.startMetricsCollection();
103
+ }
104
+
105
+ static getInstance(): HealthCheckService {
106
+ if (!HealthCheckService.instance) {
107
+ HealthCheckService.instance = new HealthCheckService();
108
+ }
109
+ return HealthCheckService.instance;
110
+ }
111
+
112
+ /**
113
+ * Get basic system health status
114
+ */
115
+ async getHealth(appVersion?: string): Promise<SystemHealth> {
116
+ // Health status is 'healthy' by default - system metrics are informational only
117
+ // Actual health is determined by custom checks (database, websocket, etc.)
118
+ const status: SystemHealth["status"] = "healthy";
119
+
120
+ return {
121
+ status,
122
+ timestamp: new Date().toISOString(),
123
+ uptime: process.uptime(),
124
+ environment: process.env.NODE_ENV || "development",
125
+ version: appVersion || process.env.npm_package_version || "unknown",
126
+ pid: process.pid,
127
+ platform: process.platform,
128
+ nodeVersion: process.version,
129
+ };
130
+ }
131
+
132
+ /**
133
+ * Get detailed system metrics
134
+ */
135
+ async getMetrics(options: HealthCheckOptions = {}): Promise<SystemMetrics> {
136
+ const {
137
+ includeCpu = true,
138
+ includeMemory = true,
139
+ includeDisk = true,
140
+ includeNetwork = true,
141
+ includeProcess = true,
142
+ diskPath = process.cwd(),
143
+ } = options;
144
+
145
+ const metrics: SystemMetrics = {} as SystemMetrics;
146
+
147
+ if (includeCpu) {
148
+ metrics.cpu = await this.getCpuMetrics();
149
+ }
150
+
151
+ if (includeMemory) {
152
+ metrics.memory = this.getMemoryMetrics();
153
+ }
154
+
155
+ if (includeDisk) {
156
+ metrics.disk = await this.getDiskMetrics(diskPath);
157
+ }
158
+
159
+ if (includeNetwork) {
160
+ metrics.network = this.getNetworkMetrics();
161
+ }
162
+
163
+ if (includeProcess) {
164
+ metrics.process = this.getProcessMetrics();
165
+ }
166
+
167
+ return metrics;
168
+ }
169
+
170
+ /**
171
+ * Get CPU metrics with real usage calculation
172
+ */
173
+ private async getCpuMetrics(): Promise<SystemMetrics["cpu"]> {
174
+ const cpus = os.cpus();
175
+ const cpuModel = cpus[0]?.model || "Unknown";
176
+ const cpuSpeed = cpus[0]?.speed || 0;
177
+ const cpuCount = cpus.length;
178
+ const loadAverage = os.loadavg();
179
+
180
+ // Calculate CPU usage percentage
181
+ const cpuUsage = await this.calculateCpuUsage();
182
+
183
+ return {
184
+ usage: cpuUsage,
185
+ count: cpuCount,
186
+ model: cpuModel,
187
+ speed: cpuSpeed,
188
+ loadAverage,
189
+ };
190
+ }
191
+
192
+ /**
193
+ * Calculate real CPU usage percentage
194
+ */
195
+ private async calculateCpuUsage(): Promise<number> {
196
+ const cpus = os.cpus();
197
+
198
+ // Calculate total and idle times
199
+ let totalIdle = 0;
200
+ let totalTick = 0;
201
+
202
+ cpus.forEach((cpu) => {
203
+ for (const type in cpu.times) {
204
+ totalTick += cpu.times[type as keyof typeof cpu.times];
205
+ }
206
+ totalIdle += cpu.times.idle;
207
+ });
208
+
209
+ const idle = totalIdle / cpus.length;
210
+ const total = totalTick / cpus.length;
211
+
212
+ // If we have previous measurements, calculate the difference
213
+ if (this.lastCpuInfo) {
214
+ const idleDiff = idle - this.lastCpuInfo.idle;
215
+ const totalDiff = total - this.lastCpuInfo.total;
216
+ const usage = 100 - (100 * idleDiff) / totalDiff;
217
+
218
+ this.lastCpuInfo = { idle, total };
219
+ return Math.min(100, Math.max(0, usage));
220
+ }
221
+
222
+ // First measurement - store for next time
223
+ this.lastCpuInfo = { idle, total };
224
+
225
+ // Fallback: use load average as approximation
226
+ const loadAvg = os.loadavg()[0]; // 1-minute load average
227
+ const approximateUsage = (loadAvg / cpus.length) * 100;
228
+ return Math.min(100, Math.max(0, approximateUsage));
229
+ }
230
+
231
+ /**
232
+ * Get memory metrics
233
+ */
234
+ private getMemoryMetrics(): SystemMetrics["memory"] {
235
+ const totalMemory = os.totalmem();
236
+ const freeMemory = os.freemem();
237
+ const usedMemory = totalMemory - freeMemory;
238
+ const memoryPercentage = (usedMemory / totalMemory) * 100;
239
+
240
+ return {
241
+ total: totalMemory,
242
+ used: usedMemory,
243
+ free: freeMemory,
244
+ percentage: parseFloat(memoryPercentage.toFixed(2)),
245
+ };
246
+ }
247
+
248
+ /**
249
+ * Get disk metrics for specified path
250
+ */
251
+ private async getDiskMetrics(
252
+ diskPath: string,
253
+ ): Promise<SystemMetrics["disk"]> {
254
+ try {
255
+ // Platform-specific disk usage check
256
+ if (process.platform === "win32") {
257
+ // Windows: use wmic command
258
+ const { stdout } = await execAsync(
259
+ "wmic logicaldisk get size,freespace,caption",
260
+ );
261
+ const lines = stdout.split("\n").filter((line) => line.trim());
262
+
263
+ // Parse the output (this is simplified - may need adjustment)
264
+ const total = parseInt(lines[1]?.split(/\s+/)[2] || "0");
265
+ const free = parseInt(lines[1]?.split(/\s+/)[1] || "0");
266
+ const used = total - free;
267
+
268
+ return {
269
+ total,
270
+ used,
271
+ free,
272
+ percentage:
273
+ total > 0 ? parseFloat(((used / total) * 100).toFixed(2)) : 0,
274
+ path: diskPath,
275
+ };
276
+ } else {
277
+ // Unix-like systems: use df command
278
+ const { stdout } = await execAsync(`df -k "${diskPath}" | tail -1`);
279
+ const parts = stdout.trim().split(/\s+/);
280
+
281
+ // df output: filesystem 1K-blocks used available use% mounted
282
+ const total = parseInt(parts[1] || "0") * 1024;
283
+ const used = parseInt(parts[2] || "0") * 1024;
284
+ const available = parseInt(parts[3] || "0") * 1024;
285
+ const percentage = parseInt(parts[4]?.replace("%", "") || "0");
286
+
287
+ return {
288
+ total,
289
+ used,
290
+ free: available,
291
+ percentage,
292
+ path: diskPath,
293
+ };
294
+ }
295
+ } catch (_error) {
296
+ console.error("Failed to get disk metrics:", _error);
297
+ // Return zeros if we can't get disk stats
298
+ return {
299
+ total: 0,
300
+ used: 0,
301
+ free: 0,
302
+ percentage: 0,
303
+ path: diskPath,
304
+ };
305
+ }
306
+ }
307
+
308
+ /**
309
+ * Get network interface information
310
+ */
311
+ private getNetworkMetrics(): SystemMetrics["network"] {
312
+ const networkInterfaces = os.networkInterfaces();
313
+ const interfaces: NetworkInterface[] = [];
314
+
315
+ for (const [name, nets] of Object.entries(networkInterfaces)) {
316
+ if (nets) {
317
+ for (const net of nets) {
318
+ interfaces.push({
319
+ name,
320
+ address: net.address,
321
+ family: net.family,
322
+ internal: net.internal,
323
+ });
324
+ }
325
+ }
326
+ }
327
+
328
+ return { interfaces };
329
+ }
330
+
331
+ /**
332
+ * Get current process metrics
333
+ */
334
+ private getProcessMetrics(): SystemMetrics["process"] {
335
+ return {
336
+ pid: process.pid,
337
+ memory: process.memoryUsage(),
338
+ cpuUsage: process.cpuUsage(),
339
+ uptime: process.uptime(),
340
+ };
341
+ }
342
+
343
+ /**
344
+ * Check dependency health (database, Redis, external APIs, etc.)
345
+ */
346
+ async checkDependencies(
347
+ dependencies: {
348
+ name: string;
349
+ check: () => Promise<boolean>;
350
+ }[],
351
+ ): Promise<DependencyHealth[]> {
352
+ const results: DependencyHealth[] = [];
353
+
354
+ for (const dep of dependencies) {
355
+ const startTime = Date.now();
356
+ try {
357
+ const isHealthy = await dep.check();
358
+ results.push({
359
+ name: dep.name,
360
+ status: isHealthy ? "connected" : "disconnected",
361
+ responseTime: Date.now() - startTime,
362
+ });
363
+ } catch (_error) {
364
+ results.push({
365
+ name: dep.name,
366
+ status: "error",
367
+ responseTime: Date.now() - startTime,
368
+ error: _error instanceof Error ? _error.message : "Unknown error",
369
+ });
370
+ }
371
+ }
372
+
373
+ return results;
374
+ }
375
+
376
+ /**
377
+ * Run custom health checks
378
+ */
379
+ async runCustomChecks(
380
+ checks: CustomHealthCheck[],
381
+ ): Promise<HealthCheckResult[]> {
382
+ const results: HealthCheckResult[] = [];
383
+
384
+ for (const check of checks) {
385
+ try {
386
+ const result = await check.check();
387
+ results.push(result);
388
+ } catch (_error) {
389
+ results.push({
390
+ name: check.name,
391
+ status: "unhealthy",
392
+ message: _error instanceof Error ? _error.message : "Check failed",
393
+ });
394
+ }
395
+ }
396
+
397
+ return results;
398
+ }
399
+
400
+ /**
401
+ * Get metrics history for graphs
402
+ */
403
+ getMetricsHistory(): {
404
+ cpu: number[];
405
+ memory: number[];
406
+ } {
407
+ return {
408
+ cpu: [...this.cpuUsageHistory],
409
+ memory: [...this.memoryUsageHistory],
410
+ };
411
+ }
412
+
413
+ /**
414
+ * Start collecting metrics periodically for history
415
+ */
416
+ private startMetricsCollection(): void {
417
+ // Collect metrics every 5 seconds
418
+ this.metricsInterval = setInterval(async () => {
419
+ try {
420
+ const metrics = await this.getMetrics();
421
+
422
+ // Add to history
423
+ this.cpuUsageHistory.push(metrics.cpu.usage);
424
+ this.memoryUsageHistory.push(metrics.memory.percentage);
425
+
426
+ // Keep only last N data points
427
+ if (this.cpuUsageHistory.length > this.historySize) {
428
+ this.cpuUsageHistory.shift();
429
+ }
430
+ if (this.memoryUsageHistory.length > this.historySize) {
431
+ this.memoryUsageHistory.shift();
432
+ }
433
+ } catch (_error) {
434
+ console.error("Failed to collect metrics:", _error);
435
+ }
436
+ }, 5000);
437
+ }
438
+
439
+ /**
440
+ * Stop metrics collection (for cleanup)
441
+ */
442
+ stopMetricsCollection(): void {
443
+ if (this.metricsInterval) {
444
+ clearInterval(this.metricsInterval);
445
+ this.metricsInterval = undefined;
446
+ }
447
+ }
448
+ }
449
+
450
+ /**
451
+ * Create health check router for Express apps
452
+ */
453
+ export function createHealthCheckRouter(options?: {
454
+ version?: string;
455
+ customChecks?: CustomHealthCheck[];
456
+ dependencies?: Array<{ name: string; check: () => Promise<boolean> }>;
457
+ }): Router {
458
+ const router = Router();
459
+ const healthService = HealthCheckService.getInstance();
460
+
461
+ // Basic health endpoint
462
+ router.get("/health", async (_req: Request, res: Response) => {
463
+ try {
464
+ const health = await healthService.getHealth(options?.version);
465
+
466
+ // Run custom checks if provided
467
+ if (options?.customChecks && options.customChecks.length > 0) {
468
+ const customResults = await Promise.all(
469
+ options.customChecks.map((check) => check.check()),
470
+ );
471
+
472
+ // Add custom check results to health object
473
+ (health as any).checks = customResults;
474
+
475
+ // Update overall status based ONLY on custom checks
476
+ const hasUnhealthy = customResults.some(
477
+ (r) => r.status === "unhealthy",
478
+ );
479
+ const hasDegraded = customResults.some((r) => r.status === "degraded");
480
+
481
+ if (hasUnhealthy) {
482
+ health.status = "unhealthy";
483
+ } else if (hasDegraded) {
484
+ health.status = "degraded";
485
+ }
486
+ // Otherwise keep default 'healthy' status
487
+ }
488
+
489
+ const statusCode =
490
+ health.status === "healthy"
491
+ ? 200
492
+ : health.status === "degraded"
493
+ ? 200
494
+ : 503;
495
+ res.status(statusCode).json(health);
496
+ } catch (_error) {
497
+ res.status(503).json({
498
+ status: "unhealthy",
499
+ error: "Failed to get health status",
500
+ });
501
+ }
502
+ });
503
+
504
+ // Detailed metrics endpoint
505
+ router.get("/metrics", async (_req: Request, res: Response) => {
506
+ try {
507
+ const metrics = await healthService.getMetrics();
508
+ res.json(metrics);
509
+ } catch (_error) {
510
+ res.status(500).json({
511
+ error: "Failed to get metrics",
512
+ });
513
+ }
514
+ });
515
+
516
+ // Metrics history for graphs
517
+ router.get("/metrics/history", (_req: Request, res: Response) => {
518
+ const history = healthService.getMetricsHistory();
519
+ res.json(history);
520
+ });
521
+
522
+ // Dependency health checks
523
+ if (options?.dependencies) {
524
+ router.get("/health/dependencies", async (_req: Request, res: Response) => {
525
+ try {
526
+ const results = await healthService.checkDependencies(
527
+ options.dependencies!,
528
+ );
529
+ const allHealthy = results.every((r) => r.status === "connected");
530
+ res.status(allHealthy ? 200 : 503).json(results);
531
+ } catch (_error) {
532
+ res.status(500).json({
533
+ error: "Failed to check dependencies",
534
+ });
535
+ }
536
+ });
537
+ }
538
+
539
+ // Custom health checks
540
+ if (options?.customChecks) {
541
+ router.get("/health/custom", async (_req: Request, res: Response) => {
542
+ try {
543
+ const results = await healthService.runCustomChecks(
544
+ options.customChecks!,
545
+ );
546
+ const allHealthy = results.every((r) => r.status === "healthy");
547
+ res.status(allHealthy ? 200 : 503).json(results);
548
+ } catch (_error) {
549
+ res.status(500).json({
550
+ error: "Failed to run custom checks",
551
+ });
552
+ }
553
+ });
554
+ }
555
+
556
+ return router;
557
+ }
558
+
559
+ // Export singleton instance getter
560
+ export function getHealthCheckService(): HealthCheckService {
561
+ return HealthCheckService.getInstance();
562
+ }
563
+
564
+ // Export types
565
+ export type { HealthCheckService };
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Core Framework Components
3
+ *
4
+ * These are generic, reusable components that could be extracted
5
+ * into a separate npm package for use in other applications.
6
+ */
7
+
8
+ // Framework version
9
+ export const FRAMEWORK_VERSION = "4.4.0";
10
+
11
+ // Process Management
12
+ export { StandardServer, createStandardServer } from "./StandardServer.js";
13
+ export type { StandardServerConfig } from "./StandardServer.js";
14
+ export {
15
+ clearPort,
16
+ isPortAvailable,
17
+ getPortInfo,
18
+ getProcessOnPort,
19
+ findAvailablePort,
20
+ checkRequiredPorts,
21
+ formatPortStatus,
22
+ waitForPort,
23
+ getPortsInUse,
24
+ type ProcessInfo,
25
+ type PortStatus,
26
+ type PortClearResult,
27
+ type PortStatusResult,
28
+ } from "./portUtils.js";
29
+
30
+ // Logging - Consolidated logger implementation
31
+ export {
32
+ getLogger,
33
+ default as Logger,
34
+ createLogger as createLoggerBase,
35
+ } from "./logger.js";
36
+
37
+ import { createLogger as createLoggerImport } from "./logger.js";
38
+
39
+ /**
40
+ * Create a logger instance with automatic file output
41
+ * @param name - The name/category for this logger
42
+ * @returns A logger instance that writes to console and files
43
+ */
44
+ export function createLogger(name: string) {
45
+ // Use the createLogger function from logger
46
+ return createLoggerImport(name);
47
+ }
48
+
49
+ // Export types for backward compatibility
50
+ export interface Logger {
51
+ info: (...args: any[]) => void;
52
+ error: (...args: any[]) => void;
53
+ warn: (...args: any[]) => void;
54
+ debug: (...args: any[]) => void;
55
+ }
56
+
57
+ export type LogLevel = "debug" | "info" | "warn" | "error";
58
+
59
+ // Security
60
+ export {
61
+ getStorageService,
62
+ StorageService,
63
+ getSecureFileHandler,
64
+ SecureFileHandler,
65
+ } from "./storageService.js";
66
+
67
+ /**
68
+ * Usage Example:
69
+ *
70
+ * import { StandardServer, createLogger } from '@/core';
71
+ *
72
+ * const logger = createLogger('MyApp');
73
+ * const server = new StandardServer({
74
+ * appName: 'MyApp',
75
+ * appVersion: '1.0.0',
76
+ * port: 8080
77
+ * });
78
+ * await server.initialize();
79
+ * await server.start();
80
+ */