@mantiq/heartbeat 0.5.15 → 0.5.16

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mantiq/heartbeat",
3
- "version": "0.5.15",
3
+ "version": "0.5.16",
4
4
  "description": "Observability, APM & queue monitoring for MantiqJS",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,6 +1,7 @@
1
1
  import { ServiceProvider, ConfigRepository, RouterImpl, HttpKernel, CacheManager } from '@mantiq/core'
2
2
  import type { EventDispatcher } from '@mantiq/core'
3
- import { DatabaseManager, SQLiteConnection } from '@mantiq/database'
3
+ import { SQLiteConnection, DatabaseManager } from '@mantiq/database'
4
+ import { mkdirSync } from 'node:fs'
4
5
  import type { HeartbeatConfig } from './contracts/HeartbeatConfig.ts'
5
6
  import { DEFAULT_CONFIG } from './contracts/HeartbeatConfig.ts'
6
7
  import { Heartbeat } from './Heartbeat.ts'
@@ -29,11 +30,29 @@ import { SimpleEventBus } from './helpers/SimpleEventBus.ts'
29
30
  export class HeartbeatServiceProvider extends ServiceProvider {
30
31
  override register(): void {
31
32
  this.app.singleton(Heartbeat, (c) => {
32
- const config = c.make(ConfigRepository).get<HeartbeatConfig>('heartbeat', DEFAULT_CONFIG)
33
+ const userConfig = c.make(ConfigRepository).get<Partial<HeartbeatConfig>>('heartbeat', {})
34
+ const config: HeartbeatConfig = {
35
+ ...DEFAULT_CONFIG,
36
+ ...userConfig,
37
+ storage: { ...DEFAULT_CONFIG.storage, ...userConfig?.storage },
38
+ watchers: { ...DEFAULT_CONFIG.watchers, ...userConfig?.watchers },
39
+ dashboard: { ...DEFAULT_CONFIG.dashboard, ...userConfig?.dashboard },
40
+ }
33
41
 
34
- // Resolve connection — undefined means use app's default database connection
35
- const dbManager = c.make(DatabaseManager)
36
- const connection = dbManager.connection(config.storage.connection)
42
+ // Resolve database connection
43
+ let connection: any
44
+ if (config.storage.driver === 'database' && config.storage.connection) {
45
+ // Use an existing app database connection
46
+ connection = c.make(DatabaseManager).connection(config.storage.connection)
47
+ } else {
48
+ // Default: dedicated SQLite file for heartbeat telemetry
49
+ const basePath = c.make(ConfigRepository).get<string>('app.basePath', process.cwd())
50
+ const storagePath = config.storage.path
51
+ const dbPath = storagePath.startsWith('/') ? storagePath : `${basePath}/${storagePath}`
52
+ const dir = dbPath.substring(0, dbPath.lastIndexOf('/'))
53
+ try { mkdirSync(dir, { recursive: true }) } catch {}
54
+ connection = new SQLiteConnection({ driver: 'sqlite', database: dbPath })
55
+ }
37
56
 
38
57
  const heartbeat = new Heartbeat(config, connection)
39
58
  setHeartbeat(heartbeat)
@@ -52,7 +71,7 @@ export class HeartbeatServiceProvider extends ServiceProvider {
52
71
  try {
53
72
  heartbeat = this.app.make(Heartbeat)
54
73
  } catch (e) {
55
- console.warn('[Mantiq] HeartbeatServiceProvider skipped database not configured. Run `bun mantiq migrate` to set up.')
74
+ if (process.env.APP_DEBUG === 'true') console.warn('[Mantiq] HeartbeatServiceProvider skipped:', (e as Error)?.message ?? e)
56
75
  return
57
76
  }
58
77
  const config = heartbeat.config
@@ -91,11 +110,15 @@ export class HeartbeatServiceProvider extends ServiceProvider {
91
110
  systemMetrics.start()
92
111
 
93
112
  // Register HeartbeatMiddleware as first global middleware
94
- this.registerMiddleware(heartbeat, tracer, requestWatcher, metrics)
113
+ try {
114
+ this.registerMiddleware(heartbeat, tracer, requestWatcher, metrics)
115
+ } catch { /* HttpKernel not available */ }
95
116
 
96
117
  // Register dashboard routes
97
118
  if (config.dashboard.enabled) {
98
- this.registerDashboardRoutes(heartbeat, metrics, config)
119
+ try {
120
+ this.registerDashboardRoutes(heartbeat, metrics, config)
121
+ } catch { /* Router not available */ }
99
122
  }
100
123
  }
101
124
 
@@ -105,7 +128,8 @@ export class HeartbeatServiceProvider extends ServiceProvider {
105
128
  requestWatcher: RequestWatcher | null,
106
129
  metrics: MetricsCollector,
107
130
  ): void {
108
- const kernel = this.app.make(HttpKernel)
131
+ let kernel: any
132
+ try { kernel = this.app.make(HttpKernel) } catch { return }
109
133
 
110
134
  // Register the middleware instance in the container
111
135
  const middleware = new HeartbeatMiddleware(heartbeat, tracer, requestWatcher, metrics)
@@ -1,7 +1,9 @@
1
1
  export interface HeartbeatConfig {
2
2
  enabled: boolean
3
3
  storage: {
4
- connection?: string | undefined
4
+ driver: 'sqlite' | 'database'
5
+ path: string // SQLite file path (used when driver is 'sqlite')
6
+ connection?: string | undefined // database connection name (used when driver is 'database')
5
7
  retention: number
6
8
  pruneInterval: number
7
9
  }
@@ -32,7 +34,9 @@ export interface HeartbeatConfig {
32
34
  export const DEFAULT_CONFIG: HeartbeatConfig = {
33
35
  enabled: true,
34
36
  storage: {
35
- connection: undefined, // uses app's default database connection
37
+ driver: 'sqlite',
38
+ path: 'storage/heartbeat/heartbeat.sqlite',
39
+ connection: undefined,
36
40
  retention: 86_400, // 24 hours
37
41
  pruneInterval: 300, // 5 minutes
38
42
  },