@mantiq/health 0.1.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.
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@mantiq/health",
3
+ "version": "0.1.0",
4
+ "description": "Application health checks — database, cache, queue, filesystem, mail, and custom checks",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Abdullah Khan",
8
+ "homepage": "https://github.com/mantiqjs/mantiq/tree/main/packages/health",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/mantiqjs/mantiq.git",
12
+ "directory": "packages/health"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/mantiqjs/mantiq/issues"
16
+ },
17
+ "keywords": [
18
+ "mantiq",
19
+ "mantiqjs",
20
+ "health",
21
+ "healthcheck",
22
+ "monitoring"
23
+ ],
24
+ "engines": {
25
+ "bun": ">=1.1.0"
26
+ },
27
+ "main": "./src/index.ts",
28
+ "types": "./src/index.ts",
29
+ "exports": {
30
+ ".": {
31
+ "bun": "./src/index.ts",
32
+ "default": "./src/index.ts"
33
+ }
34
+ },
35
+ "files": [
36
+ "src/",
37
+ "package.json",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "scripts": {
42
+ "build": "bun build ./src/index.ts --outdir ./dist --target bun --packages=external",
43
+ "test": "bun test",
44
+ "typecheck": "tsc --noEmit",
45
+ "clean": "rm -rf dist"
46
+ },
47
+ "devDependencies": {
48
+ "bun-types": "latest",
49
+ "typescript": "^5.7.0"
50
+ },
51
+ "peerDependencies": {
52
+ "@mantiq/core": "^0.1.0"
53
+ },
54
+ "peerDependenciesMeta": {
55
+ "@mantiq/database": { "optional": true },
56
+ "@mantiq/cache": { "optional": true },
57
+ "@mantiq/queue": { "optional": true },
58
+ "@mantiq/filesystem": { "optional": true },
59
+ "@mantiq/mail": { "optional": true }
60
+ }
61
+ }
@@ -0,0 +1,69 @@
1
+ export type HealthStatus = 'ok' | 'degraded' | 'critical'
2
+
3
+ export interface CheckResult {
4
+ name: string
5
+ status: HealthStatus
6
+ message?: string
7
+ duration: number // ms
8
+ meta?: Record<string, any>
9
+ }
10
+
11
+ /**
12
+ * Base class for health checks. Extend this and implement `run()`.
13
+ *
14
+ * @example
15
+ * class CustomCheck extends HealthCheck {
16
+ * name = 'custom'
17
+ * async run(): Promise<void> {
18
+ * // throw to fail, or call this.degrade() for warnings
19
+ * }
20
+ * }
21
+ */
22
+ export abstract class HealthCheck {
23
+ abstract readonly name: string
24
+
25
+ private _status: HealthStatus = 'ok'
26
+ private _message?: string
27
+ private _meta: Record<string, any> = {}
28
+
29
+ /** Override to perform the actual check. Throw to fail. */
30
+ abstract run(): Promise<void>
31
+
32
+ /** Mark this check as degraded (warning, not critical). */
33
+ protected degrade(message: string): void {
34
+ this._status = 'degraded'
35
+ this._message = message
36
+ }
37
+
38
+ /** Attach metadata to the result (shown only in debug mode). */
39
+ protected meta(key: string, value: any): void {
40
+ this._meta[key] = value
41
+ }
42
+
43
+ /** @internal Execute the check and return a result. */
44
+ async execute(): Promise<CheckResult> {
45
+ this._status = 'ok'
46
+ this._message = undefined
47
+ this._meta = {}
48
+
49
+ const start = performance.now()
50
+ try {
51
+ await this.run()
52
+ return {
53
+ name: this.name,
54
+ status: this._status,
55
+ message: this._message,
56
+ duration: Math.round((performance.now() - start) * 100) / 100,
57
+ meta: Object.keys(this._meta).length > 0 ? this._meta : undefined,
58
+ }
59
+ } catch (e: any) {
60
+ return {
61
+ name: this.name,
62
+ status: 'critical',
63
+ message: e.message ?? String(e),
64
+ duration: Math.round((performance.now() - start) * 100) / 100,
65
+ meta: Object.keys(this._meta).length > 0 ? this._meta : undefined,
66
+ }
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,56 @@
1
+ import type { HealthManager, HealthReport } from './HealthManager.ts'
2
+
3
+ /**
4
+ * HTTP request handler for /health endpoint.
5
+ *
6
+ * - Debug mode: full report with all check details, durations, and metadata
7
+ * - Production: minimal response — just status and timestamp
8
+ *
9
+ * Returns 200 for ok/degraded, 503 for critical.
10
+ */
11
+ export function healthHandler(manager: HealthManager, debug = false) {
12
+ return async (_request: Request): Promise<Response> => {
13
+ const report = await manager.check()
14
+ const status = report.status === 'critical' ? 503 : 200
15
+
16
+ if (debug) {
17
+ return new Response(JSON.stringify(report, null, 2), {
18
+ status,
19
+ headers: { 'Content-Type': 'application/json' },
20
+ })
21
+ }
22
+
23
+ // Production: strip meta and detailed messages
24
+ const minimal: Record<string, any> = {
25
+ status: report.status,
26
+ timestamp: report.timestamp,
27
+ }
28
+
29
+ // Only include check names + status (no messages, no meta)
30
+ if (report.status !== 'ok') {
31
+ minimal.checks = report.checks
32
+ .filter((c) => c.status !== 'ok')
33
+ .map((c) => ({ name: c.name, status: c.status }))
34
+ }
35
+
36
+ return new Response(JSON.stringify(minimal), {
37
+ status,
38
+ headers: { 'Content-Type': 'application/json' },
39
+ })
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Returns the health status as a compact string for Heartbeat headers.
45
+ * Format: "ok" | "degraded:database,memory" | "critical:database"
46
+ */
47
+ export async function healthHeaderValue(manager: HealthManager): Promise<string> {
48
+ const report = manager.lastReport ?? await manager.check()
49
+ if (report.status === 'ok') return 'ok'
50
+
51
+ const failing = report.checks
52
+ .filter((c) => c.status !== 'ok')
53
+ .map((c) => c.name)
54
+
55
+ return `${report.status}:${failing.join(',')}`
56
+ }
@@ -0,0 +1,62 @@
1
+ import type { HealthCheck, CheckResult, HealthStatus } from './HealthCheck.ts'
2
+
3
+ export interface HealthReport {
4
+ status: HealthStatus
5
+ timestamp: string
6
+ duration: number // total ms
7
+ checks: CheckResult[]
8
+ }
9
+
10
+ export class HealthManager {
11
+ private checks: HealthCheck[] = []
12
+ private _lastReport: HealthReport | null = null
13
+
14
+ /** Register a health check. */
15
+ register(check: HealthCheck): this {
16
+ this.checks.push(check)
17
+ return this
18
+ }
19
+
20
+ /** Register multiple checks at once. */
21
+ registerMany(checks: HealthCheck[]): this {
22
+ for (const check of checks) this.register(check)
23
+ return this
24
+ }
25
+
26
+ /** Run all checks and return a full report. */
27
+ async check(): Promise<HealthReport> {
28
+ const start = performance.now()
29
+ const results = await Promise.all(this.checks.map((c) => c.execute()))
30
+
31
+ let overall: HealthStatus = 'ok'
32
+ for (const r of results) {
33
+ if (r.status === 'critical') { overall = 'critical'; break }
34
+ if (r.status === 'degraded') overall = 'degraded'
35
+ }
36
+
37
+ this._lastReport = {
38
+ status: overall,
39
+ timestamp: new Date().toISOString(),
40
+ duration: Math.round((performance.now() - start) * 100) / 100,
41
+ checks: results,
42
+ }
43
+
44
+ return this._lastReport
45
+ }
46
+
47
+ /** Returns the last cached report (without re-running checks). */
48
+ get lastReport(): HealthReport | null {
49
+ return this._lastReport
50
+ }
51
+
52
+ /** Quick status check — returns 'ok', 'degraded', or 'critical'. */
53
+ async status(): Promise<HealthStatus> {
54
+ const report = await this.check()
55
+ return report.status
56
+ }
57
+
58
+ /** Returns registered check names. */
59
+ getCheckNames(): string[] {
60
+ return this.checks.map((c) => c.name)
61
+ }
62
+ }
@@ -0,0 +1,36 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+
3
+ /**
4
+ * Verifies core application components are booted and functional.
5
+ * Checks: config loaded, encryption key set, app instance exists.
6
+ */
7
+ export class AppCheck extends HealthCheck {
8
+ readonly name = 'app'
9
+
10
+ constructor(private app: any) {
11
+ super()
12
+ }
13
+
14
+ override async run(): Promise<void> {
15
+ if (!this.app) throw new Error('Application instance is null')
16
+
17
+ // Check container is functional
18
+ try {
19
+ const name = this.app.config?.('app.name') ?? this.app.make?.('config')?.get?.('app.name')
20
+ this.meta('name', name ?? 'unknown')
21
+ } catch {
22
+ this.degrade('Config not accessible')
23
+ }
24
+
25
+ // Check environment
26
+ this.meta('env', process.env['APP_ENV'] ?? process.env['NODE_ENV'] ?? 'unknown')
27
+ this.meta('debug', process.env['APP_DEBUG'] === 'true')
28
+
29
+ // Check APP_KEY is set (critical for encryption/sessions)
30
+ const appKey = process.env['APP_KEY']
31
+ if (!appKey || appKey.length < 10) {
32
+ throw new Error('APP_KEY is missing or too short — run `bun mantiq key:generate`')
33
+ }
34
+ this.meta('key', 'set')
35
+ }
36
+ }
@@ -0,0 +1,29 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+
3
+ /**
4
+ * Verifies the auth system is configured — guards and providers exist.
5
+ */
6
+ export class AuthCheck extends HealthCheck {
7
+ readonly name = 'auth'
8
+
9
+ constructor(private auth: any) {
10
+ super()
11
+ }
12
+
13
+ override async run(): Promise<void> {
14
+ if (!this.auth) throw new Error('Auth instance is null')
15
+
16
+ const defaultGuard = this.auth.getDefaultGuard?.() ?? this.auth.defaultGuard ?? 'unknown'
17
+ this.meta('guard', typeof defaultGuard === 'string' ? defaultGuard : 'unknown')
18
+
19
+ try {
20
+ const guard = this.auth.guard?.() ?? this.auth.guard?.(defaultGuard)
21
+ if (!guard) {
22
+ throw new Error(`Default guard "${defaultGuard}" could not be resolved`)
23
+ }
24
+ this.meta('provider', guard.getProvider?.()?.constructor?.name ?? 'unknown')
25
+ } catch (e: any) {
26
+ throw new Error(`Auth not configured: ${e.message}`)
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,32 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+
3
+ /**
4
+ * Verifies the cache driver can read and write.
5
+ * Writes a test key, reads it back, then deletes it.
6
+ */
7
+ export class CacheCheck extends HealthCheck {
8
+ readonly name = 'cache'
9
+
10
+ constructor(private cache: any) {
11
+ super()
12
+ }
13
+
14
+ override async run(): Promise<void> {
15
+ if (!this.cache) throw new Error('Cache instance is null')
16
+
17
+ const driver = this.cache.getDefaultDriver?.() ?? this.cache.driver?.() ?? 'unknown'
18
+ this.meta('driver', typeof driver === 'string' ? driver : 'unknown')
19
+
20
+ const key = `__health_check_${Date.now()}`
21
+ const value = 'ok'
22
+
23
+ await this.cache.put(key, value, 10) // 10 seconds TTL
24
+ const read = await this.cache.get(key)
25
+
26
+ if (read !== value) {
27
+ throw new Error(`Cache write/read mismatch: wrote "${value}", got "${read}"`)
28
+ }
29
+
30
+ await this.cache.forget(key)
31
+ }
32
+ }
@@ -0,0 +1,39 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+
3
+ /**
4
+ * Verifies the database connection is alive by running a simple query.
5
+ *
6
+ * @example
7
+ * health.register(new DatabaseCheck(db().connection()))
8
+ */
9
+ export class DatabaseCheck extends HealthCheck {
10
+ readonly name = 'database'
11
+
12
+ constructor(private connection: any) {
13
+ super()
14
+ }
15
+
16
+ override async run(): Promise<void> {
17
+ const driver = this.connection.getDriverName?.() ?? 'unknown'
18
+ this.meta('driver', driver)
19
+
20
+ const start = performance.now()
21
+
22
+ if (driver === 'mongodb') {
23
+ // MongoDB: ping the server
24
+ const db = typeof this.connection.native === 'function'
25
+ ? await this.connection.native()
26
+ : null
27
+ if (db) {
28
+ await db.command({ ping: 1 })
29
+ } else {
30
+ throw new Error('Cannot access native MongoDB connection')
31
+ }
32
+ } else {
33
+ // SQL: run a trivial query
34
+ await this.connection.select('SELECT 1')
35
+ }
36
+
37
+ this.meta('latency', `${Math.round(performance.now() - start)}ms`)
38
+ }
39
+ }
@@ -0,0 +1,36 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+
3
+ /**
4
+ * Verifies required environment variables are set.
5
+ *
6
+ * @example
7
+ * health.register(new EnvironmentCheck(['APP_KEY', 'DB_DATABASE']))
8
+ */
9
+ export class EnvironmentCheck extends HealthCheck {
10
+ readonly name = 'environment'
11
+
12
+ constructor(private requiredVars: string[] = ['APP_KEY']) {
13
+ super()
14
+ }
15
+
16
+ override async run(): Promise<void> {
17
+ const missing: string[] = []
18
+ const present: string[] = []
19
+
20
+ for (const key of this.requiredVars) {
21
+ if (process.env[key]) {
22
+ present.push(key)
23
+ } else {
24
+ missing.push(key)
25
+ }
26
+ }
27
+
28
+ this.meta('checked', this.requiredVars.length)
29
+ this.meta('present', present.length)
30
+
31
+ if (missing.length > 0) {
32
+ this.meta('missing', missing)
33
+ throw new Error(`Missing environment variables: ${missing.join(', ')}`)
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,30 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+
3
+ /**
4
+ * Verifies the mail driver is configured and accessible.
5
+ * Does NOT send an actual email — just checks the driver can be resolved.
6
+ */
7
+ export class MailCheck extends HealthCheck {
8
+ readonly name = 'mail'
9
+
10
+ constructor(private mail: any) {
11
+ super()
12
+ }
13
+
14
+ override async run(): Promise<void> {
15
+ if (!this.mail) throw new Error('Mail instance is null')
16
+
17
+ const driver = this.mail.getDefaultDriver?.() ?? 'unknown'
18
+ this.meta('driver', typeof driver === 'string' ? driver : 'unknown')
19
+
20
+ // Try to resolve the transport — this validates config without sending
21
+ try {
22
+ const transport = this.mail.driver?.() ?? this.mail.transport?.()
23
+ if (!transport) {
24
+ this.degrade('Mail transport could not be resolved — check config')
25
+ }
26
+ } catch (e: any) {
27
+ throw new Error(`Mail driver not configured: ${e.message}`)
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,40 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+
3
+ /**
4
+ * Checks memory usage against a threshold.
5
+ * Degrades if usage exceeds the warning threshold, fails if critical.
6
+ *
7
+ * @example
8
+ * health.register(new MemoryCheck({ warnAt: 256, criticalAt: 512 })) // MB
9
+ */
10
+ export class MemoryCheck extends HealthCheck {
11
+ readonly name = 'memory'
12
+
13
+ private warnMB: number
14
+ private criticalMB: number
15
+
16
+ constructor(opts: { warnAt?: number; criticalAt?: number } = {}) {
17
+ super()
18
+ this.warnMB = opts.warnAt ?? 256
19
+ this.criticalMB = opts.criticalAt ?? 512
20
+ }
21
+
22
+ override async run(): Promise<void> {
23
+ const usage = process.memoryUsage()
24
+ const heapMB = Math.round(usage.heapUsed / 1024 / 1024 * 10) / 10
25
+ const rssMB = Math.round(usage.rss / 1024 / 1024 * 10) / 10
26
+
27
+ this.meta('heap', `${heapMB}MB`)
28
+ this.meta('rss', `${rssMB}MB`)
29
+ this.meta('threshold_warn', `${this.warnMB}MB`)
30
+ this.meta('threshold_critical', `${this.criticalMB}MB`)
31
+
32
+ if (heapMB >= this.criticalMB) {
33
+ throw new Error(`Heap usage ${heapMB}MB exceeds critical threshold ${this.criticalMB}MB`)
34
+ }
35
+
36
+ if (heapMB >= this.warnMB) {
37
+ this.degrade(`Heap usage ${heapMB}MB exceeds warning threshold ${this.warnMB}MB`)
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,26 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+
3
+ /**
4
+ * Verifies the queue driver is accessible and can report its size.
5
+ */
6
+ export class QueueCheck extends HealthCheck {
7
+ readonly name = 'queue'
8
+
9
+ constructor(private queue: any) {
10
+ super()
11
+ }
12
+
13
+ override async run(): Promise<void> {
14
+ if (!this.queue) throw new Error('Queue instance is null')
15
+
16
+ const driver = this.queue.getDefaultDriver?.() ?? 'unknown'
17
+ this.meta('driver', typeof driver === 'string' ? driver : 'unknown')
18
+
19
+ try {
20
+ const size = await this.queue.size?.('default')
21
+ this.meta('pending', size ?? 0)
22
+ } catch (e: any) {
23
+ throw new Error(`Queue driver not accessible: ${e.message}`)
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,41 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+
3
+ /**
4
+ * Verifies the router has routes registered and key endpoints exist.
5
+ */
6
+ export class RouterCheck extends HealthCheck {
7
+ readonly name = 'router'
8
+
9
+ constructor(
10
+ private router: any,
11
+ private expectedRoutes: string[] = [],
12
+ ) {
13
+ super()
14
+ }
15
+
16
+ override async run(): Promise<void> {
17
+ if (!this.router) throw new Error('Router instance is null')
18
+
19
+ const routes = this.router.getRoutes?.() ?? this.router.routes ?? []
20
+ const routeCount = Array.isArray(routes) ? routes.length : Object.keys(routes).length
21
+ this.meta('routes', routeCount)
22
+
23
+ if (routeCount === 0) {
24
+ throw new Error('No routes registered')
25
+ }
26
+
27
+ // Verify expected routes exist
28
+ if (this.expectedRoutes.length > 0) {
29
+ const registeredPaths = Array.isArray(routes)
30
+ ? routes.map((r: any) => r.path ?? r.uri ?? '')
31
+ : Object.keys(routes)
32
+
33
+ const missing = this.expectedRoutes.filter((p) => !registeredPaths.some((rp: string) => rp === p || rp.includes(p)))
34
+
35
+ if (missing.length > 0) {
36
+ this.meta('missing', missing)
37
+ this.degrade(`Missing expected routes: ${missing.join(', ')}`)
38
+ }
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,24 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+
3
+ /**
4
+ * Verifies scheduled tasks are registered and the scheduler is running.
5
+ */
6
+ export class SchedulerCheck extends HealthCheck {
7
+ readonly name = 'scheduler'
8
+
9
+ constructor(private scheduler: any) {
10
+ super()
11
+ }
12
+
13
+ override async run(): Promise<void> {
14
+ if (!this.scheduler) throw new Error('Scheduler instance is null')
15
+
16
+ const tasks = this.scheduler.events?.() ?? this.scheduler.tasks ?? []
17
+ const count = Array.isArray(tasks) ? tasks.length : 0
18
+ this.meta('tasks', count)
19
+
20
+ if (count === 0) {
21
+ this.degrade('No scheduled tasks registered')
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,39 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+ import { existsSync, mkdirSync, writeFileSync, unlinkSync } from 'node:fs'
3
+ import { join } from 'node:path'
4
+
5
+ /**
6
+ * Verifies the storage directory is writable.
7
+ *
8
+ * @example
9
+ * health.register(new StorageCheck('./storage'))
10
+ */
11
+ export class StorageCheck extends HealthCheck {
12
+ readonly name = 'storage'
13
+
14
+ constructor(private storagePath: string = './storage') {
15
+ super()
16
+ }
17
+
18
+ override async run(): Promise<void> {
19
+ this.meta('path', this.storagePath)
20
+
21
+ if (!existsSync(this.storagePath)) {
22
+ try {
23
+ mkdirSync(this.storagePath, { recursive: true })
24
+ } catch {
25
+ throw new Error(`Storage directory does not exist and cannot be created: ${this.storagePath}`)
26
+ }
27
+ }
28
+
29
+ // Write and delete a temp file to verify write access
30
+ const testFile = join(this.storagePath, `.health-check-${Date.now()}`)
31
+ try {
32
+ writeFileSync(testFile, 'ok')
33
+ unlinkSync(testFile)
34
+ this.meta('writable', true)
35
+ } catch (e: any) {
36
+ throw new Error(`Storage directory is not writable: ${e.message}`)
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,24 @@
1
+ import { HealthCheck } from '../HealthCheck.ts'
2
+
3
+ /**
4
+ * Reports process uptime. Always passes.
5
+ */
6
+ export class UptimeCheck extends HealthCheck {
7
+ readonly name = 'uptime'
8
+
9
+ override async run(): Promise<void> {
10
+ const seconds = Math.floor(process.uptime())
11
+ const hours = Math.floor(seconds / 3600)
12
+ const minutes = Math.floor((seconds % 3600) / 60)
13
+ const secs = seconds % 60
14
+
15
+ const parts: string[] = []
16
+ if (hours > 0) parts.push(`${hours}h`)
17
+ if (minutes > 0) parts.push(`${minutes}m`)
18
+ parts.push(`${secs}s`)
19
+
20
+ this.meta('seconds', seconds)
21
+ this.meta('formatted', parts.join(' '))
22
+ this.meta('pid', process.pid)
23
+ }
24
+ }
package/src/index.ts ADDED
@@ -0,0 +1,24 @@
1
+ // ── Core ─────────────────────────────────────────────────────────────────────
2
+ export { HealthCheck } from './HealthCheck.ts'
3
+ export type { CheckResult, HealthStatus } from './HealthCheck.ts'
4
+ export { HealthManager } from './HealthManager.ts'
5
+ export type { HealthReport } from './HealthManager.ts'
6
+
7
+ // ── Handler ──────────────────────────────────────────────────────────────────
8
+ export { healthHandler, healthHeaderValue } from './HealthHandler.ts'
9
+
10
+ // ── Infrastructure Checks ────────────────────────────────────────────────────
11
+ export { DatabaseCheck } from './checks/DatabaseCheck.ts'
12
+ export { StorageCheck } from './checks/StorageCheck.ts'
13
+ export { EnvironmentCheck } from './checks/EnvironmentCheck.ts'
14
+ export { MemoryCheck } from './checks/MemoryCheck.ts'
15
+ export { UptimeCheck } from './checks/UptimeCheck.ts'
16
+
17
+ // ── Application Checks ──────────────────────────────────────────────────────
18
+ export { AppCheck } from './checks/AppCheck.ts'
19
+ export { CacheCheck } from './checks/CacheCheck.ts'
20
+ export { QueueCheck } from './checks/QueueCheck.ts'
21
+ export { RouterCheck } from './checks/RouterCheck.ts'
22
+ export { MailCheck } from './checks/MailCheck.ts'
23
+ export { AuthCheck } from './checks/AuthCheck.ts'
24
+ export { SchedulerCheck } from './checks/SchedulerCheck.ts'