@gravito/spectrum 3.0.0 → 3.0.2

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/dist/index.d.cts CHANGED
@@ -3,41 +3,98 @@ import { GravitoContext, GravitoOrbit, PlanetCore } from '@gravito/core';
3
3
  /**
4
4
  * @gravito/spectrum - Types
5
5
  */
6
+ /**
7
+ * Represents a detailed snapshot of an HTTP request processed by the application.
8
+ *
9
+ * @public
10
+ * @since 3.0.0
11
+ */
6
12
  interface CapturedRequest {
13
+ /** Unique execution ID. */
7
14
  id: string;
15
+ /** HTTP Method (GET, POST, etc.). */
8
16
  method: string;
17
+ /** URL Path. */
9
18
  path: string;
19
+ /** Full URL. */
10
20
  url: string;
21
+ /** HTTP response status code. */
11
22
  status: number;
23
+ /** Processing duration in milliseconds. */
12
24
  duration: number;
25
+ /** Epoch timestamp of when the request started. */
13
26
  startTime: number;
27
+ /** Client IP address. */
14
28
  ip: string;
29
+ /** Client user agent string. */
15
30
  userAgent?: string;
31
+ /** Incoming request headers. */
16
32
  requestHeaders: Record<string, string>;
33
+ /** Outgoing response headers. */
17
34
  responseHeaders: Record<string, string>;
35
+ /** Parsed request body (if captured). */
18
36
  requestBody?: any;
37
+ /** Parsed response body (if captured). */
19
38
  responseBody?: any;
39
+ /** Request ID for correlation with logs and queries. */
40
+ requestId?: string;
20
41
  }
42
+ /**
43
+ * Represents a log entry captured during application execution.
44
+ *
45
+ * @public
46
+ * @since 3.0.0
47
+ */
21
48
  interface CapturedLog {
49
+ /** Unique log entry ID. */
22
50
  id: string;
51
+ /** Log severity level. */
23
52
  level: 'debug' | 'info' | 'warn' | 'error';
53
+ /** The primary log message text. */
24
54
  message: string;
55
+ /** Additional arguments passed to the logger. */
25
56
  args: any[];
57
+ /** Epoch timestamp when the log was generated. */
26
58
  timestamp: number;
59
+ /** Request ID for correlation with the originating request. */
60
+ requestId?: string;
27
61
  }
62
+ /**
63
+ * Represents a database query captured during application execution.
64
+ *
65
+ * @public
66
+ * @since 3.0.0
67
+ */
28
68
  interface CapturedQuery {
69
+ /** Unique query execution ID. */
29
70
  id: string;
71
+ /** The name of the database connection used. */
30
72
  connection: string;
73
+ /** The raw or prepared SQL statement. */
31
74
  sql: string;
75
+ /** Prepared statement bindings/parameters. */
32
76
  bindings: any[];
77
+ /** Query execution duration in milliseconds. */
33
78
  duration: number;
79
+ /** Epoch timestamp when the query was executed. */
34
80
  timestamp: number;
81
+ /** Request ID for correlation with the originating request. */
82
+ requestId?: string;
35
83
  }
36
84
 
37
85
  /**
38
86
  * @gravito/spectrum - Storage Contract
39
87
  */
40
88
 
89
+ /**
90
+ * Interface for Spectrum storage backends.
91
+ *
92
+ * Implement this interface to provide custom storage for captured telemetry
93
+ * data (requests, logs, queries).
94
+ *
95
+ * @public
96
+ * @since 3.0.0
97
+ */
41
98
  interface SpectrumStorage {
42
99
  /**
43
100
  * Initialize storage driver
@@ -85,17 +142,30 @@ interface SpectrumStorage {
85
142
  * @gravito/spectrum - SpectrumOrbit
86
143
  */
87
144
 
145
+ /**
146
+ * Configuration options for the Spectrum observability orbit.
147
+ *
148
+ * @public
149
+ * @since 3.0.0
150
+ */
88
151
  interface SpectrumConfig {
152
+ /** The URL path where the dashboard UI will be served. @default '/gravito/spectrum' */
89
153
  path?: string;
154
+ /** Maximum number of records to keep in memory/disk per category. @default 100 */
90
155
  maxItems?: number;
156
+ /** Whether the spectrum capture is enabled. @default true */
91
157
  enabled?: boolean;
158
+ /** Custom storage backend for captured data. Defaults to MemoryStorage. */
92
159
  storage?: SpectrumStorage;
93
160
  /**
94
- * Authorization gate. Return true to allow access.
161
+ * Authorization gate for accessing the dashboard and its API.
162
+ * Return true to allow access, false to block.
95
163
  */
96
164
  gate?: (c: GravitoContext) => boolean | Promise<boolean>;
97
165
  /**
98
- * Sample rate (0.0 to 1.0). Default: 1.0 (100%)
166
+ * Probability sample rate (0.0 to 1.0).
167
+ * 1.0 captures everything, 0.0 captures nothing.
168
+ * @default 1.0
99
169
  */
100
170
  sampleRate?: number;
101
171
  }
@@ -111,21 +181,112 @@ interface SpectrumOrbitDeps {
111
181
  };
112
182
  } | null>;
113
183
  }
184
+ /**
185
+ * SpectrumOrbit is the official observability and debug dashboard for Gravito.
186
+ *
187
+ * It automatically captures HTTP requests, application logs, and database queries,
188
+ * providing a real-time view of your application's internals. It includes a
189
+ * built-in web dashboard for exploring and replaying captured data.
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * import { SpectrumOrbit } from '@gravito/spectrum';
194
+ *
195
+ * const spectrum = new SpectrumOrbit({
196
+ * gate: (ctx) => ctx.get('auth')?.user?.isAdmin
197
+ * });
198
+ * core.addOrbit(spectrum);
199
+ * ```
200
+ *
201
+ * @public
202
+ * @since 3.0.0
203
+ */
114
204
  declare class SpectrumOrbit implements GravitoOrbit {
205
+ /**
206
+ * Global instance of SpectrumOrbit.
207
+ *
208
+ * Used for internal access and singleton patterns within the framework.
209
+ */
115
210
  static instance: SpectrumOrbit | undefined;
116
211
  readonly name = "spectrum";
117
212
  private config;
118
213
  private listeners;
214
+ private currentRequestId;
119
215
  private warnedSecurity;
120
216
  private deps;
217
+ /**
218
+ * Initializes a new instance of SpectrumOrbit.
219
+ *
220
+ * @param config - Configuration options for behavior and storage
221
+ * @param deps - Internal dependencies for integration with other orbits
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * const spectrum = new SpectrumOrbit({ path: '/debug' });
226
+ * ```
227
+ */
121
228
  constructor(config?: SpectrumConfig, deps?: SpectrumOrbitDeps);
229
+ /**
230
+ * Checks if the current operation should be captured based on sample rate.
231
+ *
232
+ * @returns True if capture is allowed
233
+ */
122
234
  private shouldCapture;
235
+ /**
236
+ * Broadcasts telemetry data to all connected SSE clients.
237
+ *
238
+ * @param type - The category of the data
239
+ * @param data - The telemetry payload
240
+ */
123
241
  private broadcast;
242
+ /**
243
+ * Installs the Spectrum orbit into the Gravito core.
244
+ *
245
+ * Sets up collection listeners, initializes storage, and registers API/UI routes.
246
+ *
247
+ * @param core - The planet core instance
248
+ * @returns Resolves when installation is complete
249
+ * @throws {Error} If storage initialization fails
250
+ *
251
+ * @example
252
+ * ```typescript
253
+ * await spectrum.install(core);
254
+ * ```
255
+ */
124
256
  install(core: PlanetCore): Promise<void>;
257
+ /**
258
+ * Configures collection of database queries from Atlas orbit.
259
+ *
260
+ * @param core - The planet core instance
261
+ */
125
262
  private setupDatabaseCollection;
263
+ /**
264
+ * Configures interception of HTTP requests and responses.
265
+ *
266
+ * @param core - The planet core instance
267
+ */
126
268
  private setupHttpCollection;
269
+ /**
270
+ * Configures interception of application logs.
271
+ *
272
+ * Wraps the core logger to capture all log calls.
273
+ *
274
+ * @param core - The planet core instance
275
+ */
127
276
  private setupLogCollection;
277
+ /**
278
+ * Processes and stores a captured log entry.
279
+ *
280
+ * @param level - Log severity level
281
+ * @param message - Primary message string
282
+ * @param args - Additional log arguments
283
+ */
128
284
  private captureLog;
285
+ /**
286
+ * Registers all API and UI routes for the Spectrum dashboard.
287
+ *
288
+ * @param core - The planet core instance
289
+ */
129
290
  private registerRoutes;
130
291
  }
131
292
 
@@ -135,28 +296,129 @@ declare class SpectrumOrbit implements GravitoOrbit {
135
296
  * Persistent storage using JSONL files.
136
297
  */
137
298
 
299
+ /**
300
+ * Configuration for the `FileStorage` backend.
301
+ *
302
+ * @public
303
+ * @since 3.0.0
304
+ */
138
305
  interface FileStorageConfig {
306
+ /** The directory where captured telemetry data will be stored as JSONL files. */
139
307
  directory: string;
140
308
  }
309
+ /**
310
+ * FileStorage persists Spectrum telemetry data to the local file system.
311
+ *
312
+ * It uses newline-delimited JSON (JSONL) files for efficient appends and
313
+ * maintains an in-memory cache for fast dashboard retrieval.
314
+ *
315
+ * @public
316
+ * @since 3.0.0
317
+ */
141
318
  declare class FileStorage implements SpectrumStorage {
142
319
  private config;
143
320
  private requestsPath;
144
321
  private logsPath;
145
322
  private queriesPath;
146
323
  private cache;
324
+ /**
325
+ * Initializes a new instance of FileStorage.
326
+ *
327
+ * @param config - Configuration including the target directory for JSONL files
328
+ *
329
+ * @example
330
+ * ```typescript
331
+ * const storage = new FileStorage({ directory: './storage' });
332
+ * ```
333
+ */
147
334
  constructor(config: FileStorageConfig);
335
+ /**
336
+ * Initializes the storage by creating the directory and loading existing files into memory.
337
+ *
338
+ * @returns Resolves when initialization is complete
339
+ * @throws {Error} If directory creation fails
340
+ */
148
341
  init(): Promise<void>;
342
+ /**
343
+ * Loads newline-delimited JSON data from a file into a target array.
344
+ *
345
+ * @param path - The absolute path to the JSONL file
346
+ * @param target - The array to populate with parsed objects
347
+ */
149
348
  private loadCache;
349
+ /**
350
+ * Internal helper to append data to both the in-memory cache and the JSONL file.
351
+ *
352
+ * @param path - File path to append to
353
+ * @param data - The telemetry object
354
+ * @param list - The cache array
355
+ */
150
356
  private append;
357
+ /**
358
+ * Persists a captured HTTP request.
359
+ *
360
+ * @param req - The request snapshot
361
+ */
151
362
  storeRequest(req: CapturedRequest): Promise<void>;
363
+ /**
364
+ * Persists a captured log entry.
365
+ *
366
+ * @param log - The log snapshot
367
+ */
152
368
  storeLog(log: CapturedLog): Promise<void>;
369
+ /**
370
+ * Persists a captured database query.
371
+ *
372
+ * @param query - The query snapshot
373
+ */
153
374
  storeQuery(query: CapturedQuery): Promise<void>;
375
+ /**
376
+ * Retrieves recent HTTP requests from storage.
377
+ *
378
+ * @param limit - Maximum number of items to return
379
+ * @param offset - Pagination offset
380
+ * @returns Array of requests
381
+ */
154
382
  getRequests(limit?: number, offset?: number): Promise<CapturedRequest[]>;
383
+ /**
384
+ * Retrieves a specific HTTP request by its unique ID.
385
+ *
386
+ * @param id - The snapshot ID
387
+ * @returns The request or null if not found
388
+ */
155
389
  getRequest(id: string): Promise<CapturedRequest | null>;
390
+ /**
391
+ * Retrieves recent logs from storage.
392
+ *
393
+ * @param limit - Maximum number of items to return
394
+ * @param offset - Pagination offset
395
+ * @returns Array of logs
396
+ */
156
397
  getLogs(limit?: number, offset?: number): Promise<CapturedLog[]>;
398
+ /**
399
+ * Retrieves recent database queries from storage.
400
+ *
401
+ * @param limit - Maximum number of items to return
402
+ * @param offset - Pagination offset
403
+ * @returns Array of queries
404
+ */
157
405
  getQueries(limit?: number, offset?: number): Promise<CapturedQuery[]>;
406
+ /**
407
+ * Wipes all data from both cache and files.
408
+ */
158
409
  clear(): Promise<void>;
410
+ /**
411
+ * Truncates the storage to stay within the specified limit.
412
+ *
413
+ * @param maxItems - The maximum allowed records per category
414
+ */
159
415
  prune(maxItems: number): Promise<void>;
416
+ /**
417
+ * Overwrites the file content with the current in-memory data.
418
+ *
419
+ * @param path - File path to overwrite
420
+ * @param data - The array of data objects
421
+ */
160
422
  private rewrite;
161
423
  }
162
424
 
@@ -166,21 +428,100 @@ declare class FileStorage implements SpectrumStorage {
166
428
  * Non-persistent storage for development.
167
429
  */
168
430
 
431
+ /**
432
+ * MemoryStorage provides a fast, non-persistent storage backend for Spectrum telemetry.
433
+ *
434
+ * This implementation is ideal for local development environments where data persistence
435
+ * across server restarts is not required. It maintains all captured data in memory
436
+ * and automatically prunes old records based on the configured limits.
437
+ *
438
+ * @public
439
+ * @since 3.0.0
440
+ *
441
+ * @example
442
+ * ```typescript
443
+ * const storage = new MemoryStorage();
444
+ * ```
445
+ */
169
446
  declare class MemoryStorage implements SpectrumStorage {
170
447
  private requests;
171
448
  private logs;
172
449
  private queries;
173
450
  private maxItems;
451
+ /**
452
+ * Initializes the memory storage.
453
+ *
454
+ * As memory storage does not require external resources, this is a no-op.
455
+ *
456
+ * @returns Resolves immediately
457
+ */
174
458
  init(): Promise<void>;
459
+ /**
460
+ * Temporarily stores a captured HTTP request in memory.
461
+ *
462
+ * @param req - The request snapshot to store
463
+ */
175
464
  storeRequest(req: CapturedRequest): Promise<void>;
465
+ /**
466
+ * Temporarily stores a captured log entry in memory.
467
+ *
468
+ * @param log - The log entry to store
469
+ */
176
470
  storeLog(log: CapturedLog): Promise<void>;
471
+ /**
472
+ * Temporarily stores a captured database query in memory.
473
+ *
474
+ * @param query - The query information to store
475
+ */
177
476
  storeQuery(query: CapturedQuery): Promise<void>;
477
+ /**
478
+ * Retrieves a list of recent HTTP requests from memory.
479
+ *
480
+ * @param limit - Maximum number of requests to return
481
+ * @param offset - Number of requests to skip for pagination
482
+ * @returns A promise resolving to an array of captured requests
483
+ */
178
484
  getRequests(limit?: number, offset?: number): Promise<CapturedRequest[]>;
485
+ /**
486
+ * Finds a specific HTTP request by its unique identifier.
487
+ *
488
+ * @param id - The unique ID of the request to find
489
+ * @returns The found request or null if not present
490
+ */
179
491
  getRequest(id: string): Promise<CapturedRequest | null>;
492
+ /**
493
+ * Retrieves a list of recent application logs from memory.
494
+ *
495
+ * @param limit - Maximum number of logs to return
496
+ * @param offset - Number of logs to skip for pagination
497
+ * @returns A promise resolving to an array of captured logs
498
+ */
180
499
  getLogs(limit?: number, offset?: number): Promise<CapturedLog[]>;
500
+ /**
501
+ * Retrieves a list of recent database queries from memory.
502
+ *
503
+ * @param limit - Maximum number of queries to return
504
+ * @param offset - Number of queries to skip for pagination
505
+ * @returns A promise resolving to an array of captured queries
506
+ */
181
507
  getQueries(limit?: number, offset?: number): Promise<CapturedQuery[]>;
508
+ /**
509
+ * Wipes all captured telemetry data from memory.
510
+ *
511
+ * @returns Resolves when all collections are emptied
512
+ */
182
513
  clear(): Promise<void>;
514
+ /**
515
+ * Sets a new capacity limit and prunes existing data to fit.
516
+ *
517
+ * @param maxItems - The new maximum number of items to retain per category
518
+ */
183
519
  prune(maxItems: number): Promise<void>;
520
+ /**
521
+ * Truncates an array to ensure it does not exceed the maximum allowed capacity.
522
+ *
523
+ * @param arr - The target array to truncate
524
+ */
184
525
  private trim;
185
526
  }
186
527