@mantiq/heartbeat 0.5.5 → 0.5.7

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.5",
3
+ "version": "0.5.7",
4
4
  "description": "Observability, APM & queue monitoring for MantiqJS",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -48,7 +48,13 @@ export class HeartbeatServiceProvider extends ServiceProvider {
48
48
  }
49
49
 
50
50
  override async boot(): Promise<void> {
51
- const heartbeat = this.app.make(Heartbeat)
51
+ let heartbeat: Heartbeat
52
+ try {
53
+ heartbeat = this.app.make(Heartbeat)
54
+ } catch (e) {
55
+ console.warn('[Mantiq] HeartbeatServiceProvider skipped — database not configured. Run `bun mantiq migrate` to set up.')
56
+ return
57
+ }
52
58
  const config = heartbeat.config
53
59
 
54
60
  if (!config.enabled) return
@@ -141,36 +141,41 @@ export class HeartbeatMiddleware implements Middleware {
141
141
  }
142
142
 
143
143
  // Debug mode: attach X-Heartbeat header + inject widget
144
+ // Only for browser requests (HTML pages or SPA navigation), not raw API calls
144
145
  if (process.env.APP_DEBUG === 'true' && response!) {
145
- const totalDuration = performance.now() - startTime
146
- const totalMemory = Math.abs(process.memoryUsage().rss - startMemory)
147
- const mem = (totalMemory / 1024 / 1024).toFixed(1)
148
- const statsHeader = `${Math.round(totalDuration)}ms;${mem}MB;${response!.status};0q`
149
-
150
- try {
151
- const ct = response!.headers.get('content-type') ?? ''
152
- const isHtml = ct.includes('text/html') && response!.status < 400
153
- const cloned = response!.clone()
154
- const body = await cloned.text()
155
- const headers = new Headers(response!.headers)
156
-
157
- headers.set('X-Heartbeat', statsHeader)
158
- headers.set('Access-Control-Expose-Headers', [headers.get('Access-Control-Expose-Headers'), 'X-Heartbeat'].filter(Boolean).join(', '))
159
-
160
- let finalBody = body
161
- if (isHtml && this.heartbeat.config.widget?.enabled !== false && body.includes('</body>')) {
162
- const widget = renderWidget({
163
- duration: totalDuration,
164
- memory: totalMemory,
165
- status: response!.status,
166
- queries: 0,
167
- dashboardPath: this.heartbeat.config.dashboard.path,
168
- })
169
- finalBody = body.replace('</body>', widget + '\n</body>')
170
- }
171
-
172
- response = new Response(finalBody, { status: response!.status, statusText: response!.statusText, headers })
173
- } catch (e) { console.error('[Heartbeat Widget]', e) }
146
+ const ct = response!.headers.get('content-type') ?? ''
147
+ const isHtml = ct.includes('text/html') && response!.status < 400
148
+ const isSPA = request.header('X-Mantiq') === 'true'
149
+
150
+ if (isHtml || isSPA) {
151
+ const totalDuration = performance.now() - startTime
152
+ const totalMemory = Math.abs(process.memoryUsage().rss - startMemory)
153
+ const mem = (totalMemory / 1024 / 1024).toFixed(1)
154
+ const statsHeader = `${Math.round(totalDuration)}ms;${mem}MB;${response!.status};0q`
155
+
156
+ try {
157
+ const cloned = response!.clone()
158
+ const body = await cloned.text()
159
+ const headers = new Headers(response!.headers)
160
+
161
+ headers.set('X-Heartbeat', statsHeader)
162
+ headers.set('Access-Control-Expose-Headers', [headers.get('Access-Control-Expose-Headers'), 'X-Heartbeat'].filter(Boolean).join(', '))
163
+
164
+ let finalBody = body
165
+ if (isHtml && this.heartbeat.config.widget?.enabled !== false && body.includes('</body>')) {
166
+ const widget = renderWidget({
167
+ duration: totalDuration,
168
+ memory: totalMemory,
169
+ status: response!.status,
170
+ queries: 0,
171
+ dashboardPath: this.heartbeat.config.dashboard.path,
172
+ })
173
+ finalBody = body.replace('</body>', widget + '\n</body>')
174
+ }
175
+
176
+ response = new Response(finalBody, { status: response!.status, statusText: response!.statusText, headers })
177
+ } catch (e) { console.error('[Heartbeat Widget]', e) }
178
+ }
174
179
  }
175
180
 
176
181
  return response!