@buenojs/bueno 0.8.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 (120) hide show
  1. package/.env.example +109 -0
  2. package/.github/workflows/ci.yml +31 -0
  3. package/LICENSE +21 -0
  4. package/README.md +892 -0
  5. package/architecture.md +652 -0
  6. package/bun.lock +70 -0
  7. package/dist/cli/index.js +3233 -0
  8. package/dist/index.js +9014 -0
  9. package/package.json +77 -0
  10. package/src/cache/index.ts +795 -0
  11. package/src/cli/ARCHITECTURE.md +837 -0
  12. package/src/cli/bin.ts +10 -0
  13. package/src/cli/commands/build.ts +425 -0
  14. package/src/cli/commands/dev.ts +248 -0
  15. package/src/cli/commands/generate.ts +541 -0
  16. package/src/cli/commands/help.ts +55 -0
  17. package/src/cli/commands/index.ts +112 -0
  18. package/src/cli/commands/migration.ts +355 -0
  19. package/src/cli/commands/new.ts +804 -0
  20. package/src/cli/commands/start.ts +208 -0
  21. package/src/cli/core/args.ts +283 -0
  22. package/src/cli/core/console.ts +349 -0
  23. package/src/cli/core/index.ts +60 -0
  24. package/src/cli/core/prompt.ts +424 -0
  25. package/src/cli/core/spinner.ts +265 -0
  26. package/src/cli/index.ts +135 -0
  27. package/src/cli/templates/deploy.ts +295 -0
  28. package/src/cli/templates/docker.ts +307 -0
  29. package/src/cli/templates/index.ts +24 -0
  30. package/src/cli/utils/fs.ts +428 -0
  31. package/src/cli/utils/index.ts +8 -0
  32. package/src/cli/utils/strings.ts +197 -0
  33. package/src/config/env.ts +408 -0
  34. package/src/config/index.ts +506 -0
  35. package/src/config/loader.ts +329 -0
  36. package/src/config/merge.ts +285 -0
  37. package/src/config/types.ts +320 -0
  38. package/src/config/validation.ts +441 -0
  39. package/src/container/forward-ref.ts +143 -0
  40. package/src/container/index.ts +386 -0
  41. package/src/context/index.ts +360 -0
  42. package/src/database/index.ts +1142 -0
  43. package/src/database/migrations/index.ts +371 -0
  44. package/src/database/schema/index.ts +619 -0
  45. package/src/frontend/api-routes.ts +640 -0
  46. package/src/frontend/bundler.ts +643 -0
  47. package/src/frontend/console-client.ts +419 -0
  48. package/src/frontend/console-stream.ts +587 -0
  49. package/src/frontend/dev-server.ts +846 -0
  50. package/src/frontend/file-router.ts +611 -0
  51. package/src/frontend/frameworks/index.ts +106 -0
  52. package/src/frontend/frameworks/react.ts +85 -0
  53. package/src/frontend/frameworks/solid.ts +104 -0
  54. package/src/frontend/frameworks/svelte.ts +110 -0
  55. package/src/frontend/frameworks/vue.ts +92 -0
  56. package/src/frontend/hmr-client.ts +663 -0
  57. package/src/frontend/hmr.ts +728 -0
  58. package/src/frontend/index.ts +342 -0
  59. package/src/frontend/islands.ts +552 -0
  60. package/src/frontend/isr.ts +555 -0
  61. package/src/frontend/layout.ts +475 -0
  62. package/src/frontend/ssr/react.ts +446 -0
  63. package/src/frontend/ssr/solid.ts +523 -0
  64. package/src/frontend/ssr/svelte.ts +546 -0
  65. package/src/frontend/ssr/vue.ts +504 -0
  66. package/src/frontend/ssr.ts +699 -0
  67. package/src/frontend/types.ts +2274 -0
  68. package/src/health/index.ts +604 -0
  69. package/src/index.ts +410 -0
  70. package/src/lock/index.ts +587 -0
  71. package/src/logger/index.ts +444 -0
  72. package/src/logger/transports/index.ts +969 -0
  73. package/src/metrics/index.ts +494 -0
  74. package/src/middleware/built-in.ts +360 -0
  75. package/src/middleware/index.ts +94 -0
  76. package/src/modules/filters.ts +458 -0
  77. package/src/modules/guards.ts +405 -0
  78. package/src/modules/index.ts +1256 -0
  79. package/src/modules/interceptors.ts +574 -0
  80. package/src/modules/lazy.ts +418 -0
  81. package/src/modules/lifecycle.ts +478 -0
  82. package/src/modules/metadata.ts +90 -0
  83. package/src/modules/pipes.ts +626 -0
  84. package/src/router/index.ts +339 -0
  85. package/src/router/linear.ts +371 -0
  86. package/src/router/regex.ts +292 -0
  87. package/src/router/tree.ts +562 -0
  88. package/src/rpc/index.ts +1263 -0
  89. package/src/security/index.ts +436 -0
  90. package/src/ssg/index.ts +631 -0
  91. package/src/storage/index.ts +456 -0
  92. package/src/telemetry/index.ts +1097 -0
  93. package/src/testing/index.ts +1586 -0
  94. package/src/types/index.ts +236 -0
  95. package/src/types/optional-deps.d.ts +219 -0
  96. package/src/validation/index.ts +276 -0
  97. package/src/websocket/index.ts +1004 -0
  98. package/tests/integration/cli.test.ts +1016 -0
  99. package/tests/integration/fullstack.test.ts +234 -0
  100. package/tests/unit/cache.test.ts +174 -0
  101. package/tests/unit/cli-commands.test.ts +892 -0
  102. package/tests/unit/cli.test.ts +1258 -0
  103. package/tests/unit/container.test.ts +279 -0
  104. package/tests/unit/context.test.ts +221 -0
  105. package/tests/unit/database.test.ts +183 -0
  106. package/tests/unit/linear-router.test.ts +280 -0
  107. package/tests/unit/lock.test.ts +336 -0
  108. package/tests/unit/middleware.test.ts +184 -0
  109. package/tests/unit/modules.test.ts +142 -0
  110. package/tests/unit/pubsub.test.ts +257 -0
  111. package/tests/unit/regex-router.test.ts +265 -0
  112. package/tests/unit/router.test.ts +373 -0
  113. package/tests/unit/rpc.test.ts +1248 -0
  114. package/tests/unit/security.test.ts +174 -0
  115. package/tests/unit/telemetry.test.ts +371 -0
  116. package/tests/unit/test-cache.test.ts +110 -0
  117. package/tests/unit/test-database.test.ts +282 -0
  118. package/tests/unit/tree-router.test.ts +325 -0
  119. package/tests/unit/validation.test.ts +794 -0
  120. package/tsconfig.json +27 -0
@@ -0,0 +1,604 @@
1
+ /**
2
+ * Health Check System
3
+ *
4
+ * Provides health check endpoints for production monitoring:
5
+ * - /health (liveness probe) - Returns 200 if server is running
6
+ * - /ready (readiness probe) - Returns 200 only if all checks pass
7
+ */
8
+
9
+ import type { Context } from "../context";
10
+ import type { Middleware } from "../middleware";
11
+
12
+ // ============= Types =============
13
+
14
+ /**
15
+ * Health check status
16
+ */
17
+ export type HealthStatus = "healthy" | "unhealthy" | "degraded";
18
+
19
+ /**
20
+ * Individual check result
21
+ */
22
+ export interface CheckResult {
23
+ status: HealthStatus;
24
+ latency?: number;
25
+ message?: string;
26
+ }
27
+
28
+ /**
29
+ * Overall health check result
30
+ */
31
+ export interface HealthCheckResult {
32
+ status: HealthStatus;
33
+ timestamp: string;
34
+ version?: string;
35
+ uptime?: number;
36
+ checks?: Record<string, CheckResult>;
37
+ }
38
+
39
+ /**
40
+ * Health check function type
41
+ */
42
+ export type HealthCheckFn = () => Promise<CheckResult> | CheckResult;
43
+
44
+ /**
45
+ * Options for individual health checks
46
+ */
47
+ export interface CheckOptions {
48
+ /** Whether this check is critical for readiness (default: true) */
49
+ critical?: boolean;
50
+ /** Timeout in milliseconds (default: 5000) */
51
+ timeout?: number;
52
+ /** Description of the check */
53
+ description?: string;
54
+ }
55
+
56
+ /**
57
+ * Registered health check entry
58
+ */
59
+ interface RegisteredCheck {
60
+ name: string;
61
+ fn: HealthCheckFn;
62
+ options: Required<CheckOptions>;
63
+ }
64
+
65
+ /**
66
+ * Options for health middleware
67
+ */
68
+ export interface HealthMiddlewareOptions {
69
+ /** Path for liveness probe (default: /health) */
70
+ healthPath?: string;
71
+ /** Path for readiness probe (default: /ready) */
72
+ readyPath?: string;
73
+ /** Whether to expose metrics in response (default: true) */
74
+ exposeMetrics?: boolean;
75
+ /** Initial health checks to register */
76
+ checks?: Record<string, HealthCheckFn | { fn: HealthCheckFn; options?: CheckOptions }>;
77
+ /** Custom version string (default: from package.json) */
78
+ version?: string;
79
+ }
80
+
81
+ /**
82
+ * Database interface for built-in checker
83
+ */
84
+ export interface DatabaseLike {
85
+ query?(sql: string): Promise<unknown>;
86
+ execute?(sql: string): Promise<unknown>;
87
+ healthCheck?(): Promise<boolean>;
88
+ }
89
+
90
+ /**
91
+ * Cache interface for built-in checker
92
+ */
93
+ export interface CacheLike {
94
+ get?(key: string): Promise<unknown>;
95
+ set?(key: string, value: unknown): Promise<unknown>;
96
+ ping?(): Promise<unknown>;
97
+ healthCheck?(): Promise<boolean>;
98
+ }
99
+
100
+ // ============= HealthCheckManager Class =============
101
+
102
+ /**
103
+ * Manages health checks for the application
104
+ */
105
+ export class HealthCheckManager {
106
+ private checks: Map<string, RegisteredCheck> = new Map();
107
+ private startTime = Date.now();
108
+ private version: string;
109
+
110
+ constructor(version?: string) {
111
+ this.version = version ?? "0.1.0";
112
+ }
113
+
114
+ /**
115
+ * Register a health check
116
+ */
117
+ registerCheck(
118
+ name: string,
119
+ checkFn: HealthCheckFn,
120
+ options: CheckOptions = {},
121
+ ): this {
122
+ this.checks.set(name, {
123
+ name,
124
+ fn: checkFn,
125
+ options: {
126
+ critical: options.critical ?? true,
127
+ timeout: options.timeout ?? 5000,
128
+ description: options.description ?? "",
129
+ },
130
+ });
131
+ return this;
132
+ }
133
+
134
+ /**
135
+ * Remove a health check
136
+ */
137
+ removeCheck(name: string): boolean {
138
+ return this.checks.delete(name);
139
+ }
140
+
141
+ /**
142
+ * Get all registered check names
143
+ */
144
+ getCheckNames(): string[] {
145
+ return Array.from(this.checks.keys());
146
+ }
147
+
148
+ /**
149
+ * Check if a check is registered
150
+ */
151
+ hasCheck(name: string): boolean {
152
+ return this.checks.has(name);
153
+ }
154
+
155
+ /**
156
+ * Run a single check with timeout
157
+ */
158
+ private async runSingleCheck(check: RegisteredCheck): Promise<CheckResult> {
159
+ const start = Date.now();
160
+
161
+ try {
162
+ // Run check with timeout
163
+ const result = await Promise.race([
164
+ check.fn(),
165
+ new Promise<never>((_, reject) =>
166
+ setTimeout(
167
+ () => reject(new Error(`Check timed out after ${check.options.timeout}ms`)),
168
+ check.options.timeout,
169
+ ),
170
+ ),
171
+ ]);
172
+
173
+ return {
174
+ ...result,
175
+ latency: Date.now() - start,
176
+ };
177
+ } catch (error) {
178
+ return {
179
+ status: "unhealthy",
180
+ latency: Date.now() - start,
181
+ message: error instanceof Error ? error.message : "Check failed",
182
+ };
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Execute all registered checks
188
+ */
189
+ async runChecks(): Promise<Record<string, CheckResult>> {
190
+ const results: Record<string, CheckResult> = {};
191
+
192
+ // Run all checks in parallel
193
+ const entries = Array.from(this.checks.values());
194
+ const outcomes = await Promise.all(
195
+ entries.map(async (check) => ({
196
+ name: check.name,
197
+ result: await this.runSingleCheck(check),
198
+ critical: check.options.critical,
199
+ })),
200
+ );
201
+
202
+ for (const { name, result } of outcomes) {
203
+ results[name] = result;
204
+ }
205
+
206
+ return results;
207
+ }
208
+
209
+ /**
210
+ * Get liveness status (lightweight - no dependency checks)
211
+ */
212
+ getHealth(): HealthCheckResult {
213
+ return {
214
+ status: "healthy",
215
+ timestamp: new Date().toISOString(),
216
+ version: this.version,
217
+ uptime: Math.floor((Date.now() - this.startTime) / 1000),
218
+ };
219
+ }
220
+
221
+ /**
222
+ * Get readiness status (runs all checks)
223
+ */
224
+ async getReadiness(): Promise<HealthCheckResult> {
225
+ const checks = await this.runChecks();
226
+
227
+ // Determine overall status
228
+ let status: HealthStatus = "healthy";
229
+ let hasUnhealthyCritical = false;
230
+ let hasUnhealthyNonCritical = false;
231
+ let hasDegraded = false;
232
+
233
+ const entries = Array.from(this.checks.values());
234
+
235
+ for (const entry of entries) {
236
+ const checkResult = checks[entry.name];
237
+ if (checkResult) {
238
+ // Critical checks affect overall status
239
+ if (entry.options.critical && checkResult.status === "unhealthy") {
240
+ hasUnhealthyCritical = true;
241
+ }
242
+ // Non-critical unhealthy checks degrade status
243
+ if (!entry.options.critical && checkResult.status === "unhealthy") {
244
+ hasUnhealthyNonCritical = true;
245
+ }
246
+ // Any degraded check degrades overall status
247
+ if (checkResult.status === "degraded") {
248
+ hasDegraded = true;
249
+ }
250
+ }
251
+ }
252
+
253
+ // Determine final status based on flags
254
+ if (hasUnhealthyCritical) {
255
+ status = "unhealthy";
256
+ } else if (hasUnhealthyNonCritical || hasDegraded) {
257
+ status = "degraded";
258
+ }
259
+
260
+ return {
261
+ status,
262
+ timestamp: new Date().toISOString(),
263
+ version: this.version,
264
+ uptime: Math.floor((Date.now() - this.startTime) / 1000),
265
+ checks,
266
+ };
267
+ }
268
+
269
+ /**
270
+ * Get uptime in seconds
271
+ */
272
+ getUptime(): number {
273
+ return Math.floor((Date.now() - this.startTime) / 1000);
274
+ }
275
+
276
+ /**
277
+ * Reset start time (useful for testing)
278
+ */
279
+ resetStartTime(): void {
280
+ this.startTime = Date.now();
281
+ }
282
+ }
283
+
284
+ // ============= Middleware Factory =============
285
+
286
+ /**
287
+ * Create health check middleware
288
+ */
289
+ export function createHealthMiddleware(
290
+ options: HealthMiddlewareOptions = {},
291
+ ): { middleware: Middleware; manager: HealthCheckManager } {
292
+ const {
293
+ healthPath = "/health",
294
+ readyPath = "/ready",
295
+ exposeMetrics = true,
296
+ checks = {},
297
+ version,
298
+ } = options;
299
+
300
+ const manager = new HealthCheckManager(version);
301
+
302
+ // Register initial checks
303
+ for (const [name, check] of Object.entries(checks)) {
304
+ if (typeof check === "function") {
305
+ manager.registerCheck(name, check);
306
+ } else {
307
+ manager.registerCheck(name, check.fn, check.options);
308
+ }
309
+ }
310
+
311
+ const middleware: Middleware = async (
312
+ context: Context,
313
+ next: () => Promise<Response>,
314
+ ): Promise<Response> => {
315
+ const path = context.path;
316
+
317
+ // Handle liveness probe
318
+ if (path === healthPath && context.method === "GET") {
319
+ const health = manager.getHealth();
320
+ return context.json(health);
321
+ }
322
+
323
+ // Handle readiness probe
324
+ if (path === readyPath && context.method === "GET") {
325
+ const readiness = await manager.getReadiness();
326
+
327
+ // Set appropriate status code
328
+ if (readiness.status === "unhealthy") {
329
+ context.status(503);
330
+ } else if (readiness.status === "degraded") {
331
+ context.status(200); // Still serve traffic but with warning
332
+ }
333
+
334
+ // Optionally strip metrics
335
+ const response = exposeMetrics
336
+ ? readiness
337
+ : { status: readiness.status, timestamp: readiness.timestamp };
338
+
339
+ return context.json(response);
340
+ }
341
+
342
+ // Continue to next middleware/handler
343
+ return next();
344
+ };
345
+
346
+ return { middleware, manager };
347
+ }
348
+
349
+ // ============= Built-in Checkers =============
350
+
351
+ /**
352
+ * Create a database connectivity check
353
+ */
354
+ export function createDatabaseCheck(
355
+ db: DatabaseLike,
356
+ options: { query?: string; timeout?: number } = {},
357
+ ): HealthCheckFn {
358
+ const { query = "SELECT 1" } = options;
359
+
360
+ return async (): Promise<CheckResult> => {
361
+ const start = Date.now();
362
+
363
+ try {
364
+ // Use custom healthCheck method if available
365
+ if (typeof db.healthCheck === "function") {
366
+ const isHealthy = await db.healthCheck();
367
+ return {
368
+ status: isHealthy ? "healthy" : "unhealthy",
369
+ latency: Date.now() - start,
370
+ message: isHealthy ? "Database connection OK" : "Database health check failed",
371
+ };
372
+ }
373
+
374
+ // Try to execute a simple query
375
+ if (typeof db.query === "function") {
376
+ await db.query(query);
377
+ return {
378
+ status: "healthy",
379
+ latency: Date.now() - start,
380
+ message: "Database connection OK",
381
+ };
382
+ }
383
+
384
+ if (typeof db.execute === "function") {
385
+ await db.execute(query);
386
+ return {
387
+ status: "healthy",
388
+ latency: Date.now() - start,
389
+ message: "Database connection OK",
390
+ };
391
+ }
392
+
393
+ return {
394
+ status: "degraded",
395
+ latency: Date.now() - start,
396
+ message: "No compatible database method found",
397
+ };
398
+ } catch (error) {
399
+ return {
400
+ status: "unhealthy",
401
+ latency: Date.now() - start,
402
+ message: error instanceof Error ? error.message : "Database check failed",
403
+ };
404
+ }
405
+ };
406
+ }
407
+
408
+ /**
409
+ * Create a cache connectivity check
410
+ */
411
+ export function createCacheCheck(
412
+ cache: CacheLike,
413
+ options: { testKey?: string; timeout?: number } = {},
414
+ ): HealthCheckFn {
415
+ const { testKey = "__health_check__" } = options;
416
+
417
+ return async (): Promise<CheckResult> => {
418
+ const start = Date.now();
419
+
420
+ try {
421
+ // Use custom healthCheck method if available
422
+ if (typeof cache.healthCheck === "function") {
423
+ const isHealthy = await cache.healthCheck();
424
+ return {
425
+ status: isHealthy ? "healthy" : "unhealthy",
426
+ latency: Date.now() - start,
427
+ message: isHealthy ? "Cache connection OK" : "Cache health check failed",
428
+ };
429
+ }
430
+
431
+ // Use ping method if available (Redis-like)
432
+ if (typeof cache.ping === "function") {
433
+ await cache.ping();
434
+ return {
435
+ status: "healthy",
436
+ latency: Date.now() - start,
437
+ message: "Cache ping OK",
438
+ };
439
+ }
440
+
441
+ // Try set and get operations
442
+ if (typeof cache.set === "function" && typeof cache.get === "function") {
443
+ const testValue = Date.now().toString();
444
+ await cache.set(testKey, testValue);
445
+ const retrieved = await cache.get(testKey);
446
+
447
+ if (retrieved === testValue || retrieved?.toString() === testValue) {
448
+ return {
449
+ status: "healthy",
450
+ latency: Date.now() - start,
451
+ message: "Cache read/write OK",
452
+ };
453
+ }
454
+
455
+ return {
456
+ status: "degraded",
457
+ latency: Date.now() - start,
458
+ message: "Cache read/write mismatch",
459
+ };
460
+ }
461
+
462
+ return {
463
+ status: "degraded",
464
+ latency: Date.now() - start,
465
+ message: "No compatible cache method found",
466
+ };
467
+ } catch (error) {
468
+ return {
469
+ status: "unhealthy",
470
+ latency: Date.now() - start,
471
+ message: error instanceof Error ? error.message : "Cache check failed",
472
+ };
473
+ }
474
+ };
475
+ }
476
+
477
+ /**
478
+ * Create a custom health check with timeout
479
+ */
480
+ export function createCustomCheck(
481
+ checkFn: () => Promise<boolean> | boolean,
482
+ options: { message?: string; timeout?: number } = {},
483
+ ): HealthCheckFn {
484
+ const { message = "Custom check" } = options;
485
+
486
+ return async (): Promise<CheckResult> => {
487
+ const start = Date.now();
488
+
489
+ try {
490
+ const result = await checkFn();
491
+ return {
492
+ status: result ? "healthy" : "unhealthy",
493
+ latency: Date.now() - start,
494
+ message: result ? `${message} OK` : `${message} failed`,
495
+ };
496
+ } catch (error) {
497
+ return {
498
+ status: "unhealthy",
499
+ latency: Date.now() - start,
500
+ message: error instanceof Error ? error.message : `${message} failed`,
501
+ };
502
+ }
503
+ };
504
+ }
505
+
506
+ /**
507
+ * Create a TCP port check
508
+ */
509
+ export function createTCPCheck(
510
+ host: string,
511
+ port: number,
512
+ options: { timeout?: number } = {},
513
+ ): HealthCheckFn {
514
+ const { timeout = 5000 } = options;
515
+
516
+ return async (): Promise<CheckResult> => {
517
+ const start = Date.now();
518
+
519
+ try {
520
+ // Use Bun's connect API
521
+ const socket = await Bun.connect({
522
+ hostname: host,
523
+ port,
524
+ socket: {
525
+ data() {},
526
+ error() {},
527
+ },
528
+ });
529
+ socket.end();
530
+
531
+ return {
532
+ status: "healthy",
533
+ latency: Date.now() - start,
534
+ message: `TCP ${host}:${port} reachable`,
535
+ };
536
+ } catch (error) {
537
+ return {
538
+ status: "unhealthy",
539
+ latency: Date.now() - start,
540
+ message: `TCP ${host}:${port} unreachable: ${error instanceof Error ? error.message : "unknown error"}`,
541
+ };
542
+ }
543
+ };
544
+ }
545
+
546
+ /**
547
+ * Create an HTTP endpoint check
548
+ */
549
+ export function createHTTPCheck(
550
+ url: string,
551
+ options: {
552
+ expectedStatus?: number;
553
+ timeout?: number;
554
+ headers?: Record<string, string>;
555
+ } = {},
556
+ ): HealthCheckFn {
557
+ const { expectedStatus = 200, timeout = 5000, headers = {} } = options;
558
+
559
+ return async (): Promise<CheckResult> => {
560
+ const start = Date.now();
561
+
562
+ try {
563
+ const controller = new AbortController();
564
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
565
+
566
+ const response = await fetch(url, {
567
+ method: "GET",
568
+ headers,
569
+ signal: controller.signal,
570
+ });
571
+
572
+ clearTimeout(timeoutId);
573
+
574
+ if (response.status === expectedStatus) {
575
+ return {
576
+ status: "healthy",
577
+ latency: Date.now() - start,
578
+ message: `HTTP ${url} returned ${response.status}`,
579
+ };
580
+ }
581
+
582
+ return {
583
+ status: "unhealthy",
584
+ latency: Date.now() - start,
585
+ message: `HTTP ${url} returned ${response.status}, expected ${expectedStatus}`,
586
+ };
587
+ } catch (error) {
588
+ return {
589
+ status: "unhealthy",
590
+ latency: Date.now() - start,
591
+ message: `HTTP ${url} failed: ${error instanceof Error ? error.message : "unknown error"}`,
592
+ };
593
+ }
594
+ };
595
+ }
596
+
597
+ // ============= Factory Functions =============
598
+
599
+ /**
600
+ * Create a new health check manager
601
+ */
602
+ export function createHealthManager(version?: string): HealthCheckManager {
603
+ return new HealthCheckManager(version);
604
+ }