@lensjs/core 2.0.0 → 2.1.1

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 (89) hide show
  1. package/README.md +69 -0
  2. package/dist/abstracts/store.cjs +13 -0
  3. package/dist/abstracts/store.d.cts +6 -3
  4. package/dist/abstracts/store.d.ts +6 -3
  5. package/dist/abstracts/store.js +13 -0
  6. package/dist/core/api_controller.cjs +22 -1
  7. package/dist/core/api_controller.d.cts +4 -2
  8. package/dist/core/api_controller.d.ts +4 -2
  9. package/dist/core/api_controller.js +22 -1
  10. package/dist/core/lens.cjs +52 -4
  11. package/dist/core/lens.js +52 -4
  12. package/dist/exception-3AZsPtAg.d.ts +52 -0
  13. package/dist/exception-C69UCHPk.d.cts +52 -0
  14. package/dist/index.cjs +207 -29
  15. package/dist/index.d.cts +4 -2
  16. package/dist/index.d.ts +4 -2
  17. package/dist/index.js +204 -29
  18. package/dist/stores/better_sqlite.cjs +19 -3
  19. package/dist/stores/better_sqlite.d.cts +9 -1
  20. package/dist/stores/better_sqlite.d.ts +9 -1
  21. package/dist/stores/better_sqlite.js +19 -3
  22. package/dist/stores/index.cjs +19 -3
  23. package/dist/stores/index.js +19 -3
  24. package/dist/types/index.cjs +1 -0
  25. package/dist/types/index.d.cts +26 -2
  26. package/dist/types/index.d.ts +26 -2
  27. package/dist/types/index.js +1 -0
  28. package/dist/ui/assets/{CacheActionBadge-3jjmNjC6.js → CacheActionBadge-CK7JdKoE.js} +1 -1
  29. package/dist/ui/assets/CacheEntriesTable-C5HcgCZI.js +1 -0
  30. package/dist/ui/assets/CacheEntryContainer-C0no2_6_.js +2 -0
  31. package/dist/ui/assets/{CacheEntryDetails-CHt_pNTk.js → CacheEntryDetails-D9Xy7d9u.js} +1 -1
  32. package/dist/ui/assets/CacheEntryDetailsContainer-BcwliP55.js +2 -0
  33. package/dist/ui/assets/ExceptionContainer-CQalcd8x.js +2 -0
  34. package/dist/ui/assets/ExceptionDetails-BbIFoM7M.js +16 -0
  35. package/dist/ui/assets/ExceptionDetailsContainer-fajmF7id.js +2 -0
  36. package/dist/ui/assets/ExceptionTable-DY3mmGT4.js +1 -0
  37. package/dist/ui/assets/{LoadMore-DHOrhPsi.js → LoadMore-CJh7FLbl.js} +1 -1
  38. package/dist/ui/assets/QueriesContainer-DWTsKzEk.js +2 -0
  39. package/dist/ui/assets/{QueryDetailsContainer-eoLkgEjj.js → QueryDetailsContainer-7CA9a5de.js} +7 -7
  40. package/dist/ui/assets/{QueryTable-BXSzT-Cm.js → QueryTable-pn7Ayura.js} +1 -1
  41. package/dist/ui/assets/RequestDetails-CYSM4og8.js +1 -0
  42. package/dist/ui/assets/{RequestDetailsContainer-BaH6fUK7.js → RequestDetailsContainer-BECT0XJh.js} +2 -2
  43. package/dist/ui/assets/RequestsContainer-DLkjpX67.js +2 -0
  44. package/dist/ui/assets/{RequetsTable-B51VXisk.js → RequetsTable-Cgas07Fe.js} +1 -1
  45. package/dist/ui/assets/{StatusCode-DVhX11V3.js → StatusCode-C5lihzKZ.js} +1 -1
  46. package/dist/ui/assets/TabbedDataViewer-BUMQ0QVm.js +1 -0
  47. package/dist/ui/assets/{Table-D1Kpw7PA.js → Table-BesHc4Lc.js} +1 -1
  48. package/dist/ui/assets/columns-C1CwS8yE.js +1 -0
  49. package/dist/ui/assets/{columns-jYfhBxOM.js → columns-CULxhcpY.js} +1 -1
  50. package/dist/ui/assets/{columns-BIDLCW64.js → columns-gYFQU5qH.js} +1 -1
  51. package/dist/ui/assets/index-B2QCOgug.css +1 -0
  52. package/dist/ui/assets/{index-CpP2Ap5X.js → index-BRRKsoNv.js} +1 -1
  53. package/dist/ui/assets/{index-BdvbrZNf.js → index-PEcJ5nx0.js} +26 -21
  54. package/dist/ui/assets/{useCacheEntries-vuHEIj6E.js → useCacheEntries-jbGe2CRY.js} +1 -1
  55. package/dist/ui/assets/useExceptions-uYUhAW-J.js +1 -0
  56. package/dist/ui/assets/useLensApi-BsDmB7vx.js +1 -0
  57. package/dist/ui/assets/{useLoadMore-twYxPJ-d.js → useLoadMore-sLsrekV5.js} +1 -1
  58. package/dist/ui/assets/{useQueries-BYFLoUQR.js → useQueries-DJE91mYq.js} +1 -1
  59. package/dist/ui/index.html +2 -2
  60. package/dist/utils/async_context.cjs +113 -0
  61. package/dist/utils/async_context.d.cts +6 -1
  62. package/dist/utils/async_context.d.ts +6 -1
  63. package/dist/utils/async_context.js +102 -0
  64. package/dist/utils/exception.cjs +130 -0
  65. package/dist/utils/exception.d.cts +3 -0
  66. package/dist/utils/exception.d.ts +3 -0
  67. package/dist/utils/exception.js +91 -0
  68. package/dist/utils/index.cjs +1 -0
  69. package/dist/utils/index.js +1 -0
  70. package/dist/watchers/cache_watcher.cjs +12 -16
  71. package/dist/watchers/cache_watcher.js +12 -16
  72. package/dist/watchers/exception_watcher.cjs +108 -0
  73. package/dist/watchers/exception_watcher.d.cts +10 -0
  74. package/dist/watchers/exception_watcher.d.ts +10 -0
  75. package/dist/watchers/exception_watcher.js +75 -0
  76. package/dist/watchers/index.cjs +53 -16
  77. package/dist/watchers/index.d.cts +1 -0
  78. package/dist/watchers/index.d.ts +1 -0
  79. package/dist/watchers/index.js +42 -16
  80. package/package.json +8 -6
  81. package/dist/ui/assets/CacheEntriesTable-DPLre6br.js +0 -1
  82. package/dist/ui/assets/CacheEntryContainer-WN6LkoCR.js +0 -2
  83. package/dist/ui/assets/CacheEntryDetailsContainer-BhquSApO.js +0 -2
  84. package/dist/ui/assets/QueriesContainer-Cl6rq4dH.js +0 -2
  85. package/dist/ui/assets/RequestDetails-CIB7_XWh.js +0 -1
  86. package/dist/ui/assets/RequestsContainer-DLS17BWP.js +0 -2
  87. package/dist/ui/assets/TabbedDataViewer-CNSEhc6h.js +0 -1
  88. package/dist/ui/assets/index-C04tuZDI.css +0 -1
  89. package/dist/ui/assets/useLensApi-Bzmx8hps.js +0 -1
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # @lensjs/core
2
+
3
+ The core library for Lens, providing the fundamental architecture for monitoring and debugging applications. It defines the abstract concepts of adapters, stores, and watchers, along with utilities for event emission, asynchronous context management, and SQL formatting. This package also includes the embedded UI for the Lens dashboard.
4
+
5
+ ## Features
6
+
7
+ * **`Lens` class**: The central class for initializing Lens, setting up adapters and watchers, and starting the monitoring process.
8
+ * **`LensAdapter` (abstract class)**: Defines the interface for integrating Lens with different application frameworks (e.g., Express, Adonis). It handles route registration and UI serving.
9
+ * **`LensStore` (abstract class)**: Defines the interface for data storage, allowing Lens to persist and retrieve captured events (requests, queries, cache entries). Includes methods for saving, retrieving, and truncating data.
10
+ * **`LensWatcher` (abstract class)**: Defines the interface for capturing specific types of events within an application.
11
+ * **Concrete Watchers**:
12
+ * `RequestWatcher`: Captures and logs details of incoming HTTP requests.
13
+ * `QueryWatcher`: Captures and logs database queries.
14
+ * `CacheWatcher`: Captures and logs cache interactions.
15
+ * `ExceptionWatcher`: Captures and logs exceptions and errors.
16
+ * **`ApiController`**: Provides the API endpoints for the Lens UI to fetch monitoring data.
17
+ * **`lensEmitter`**: A global event emitter for internal communication between different parts of Lens.
18
+ * **`lensContext`**: Utilizes `AsyncLocalStorage` for managing asynchronous context, primarily to associate events with a specific request ID.
19
+ * **`lensUtils`**: A collection of utility functions, including:
20
+ * `generateRandomUuid`: Generates unique IDs.
21
+ * `interpolateQuery`: Interpolates SQL query placeholders with actual values.
22
+ * `formatSqlQuery`: Formats SQL queries for readability.
23
+ * `getMeta`: Provides `__filename` and `__dirname` in both CommonJS and ESM environments.
24
+ * `isStaticFile`, `stripBeforeAssetsPath`: Utilities for handling static file paths.
25
+ * `prepareIgnoredPaths`, `shouldIgnoreCurrentPath`: Logic for path-based filtering.
26
+ * `prettyHrTime`: Formats high-resolution time differences.
27
+ * **`BetterSqliteStore`**: A concrete implementation of `LensStore` using Better SQLite for data persistence.
28
+ * **Embedded UI**: Includes a built-in web interface for visualizing captured application data.
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pnpm add @lensjs/core
34
+ ```
35
+
36
+ ## Usage Example (Conceptual - typically used via framework adapters)
37
+
38
+ ```typescript
39
+ import { Lens, RequestWatcher, QueryWatcher, CacheWatcher } from '@lensjs/core';
40
+ import { BetterSqliteStore } from '@lensjs/core/stores';
41
+ // Assuming you have a custom adapter for your framework
42
+ import MyFrameworkAdapter from './my-framework-adapter';
43
+
44
+ async function bootstrapLens(appInstance: any) {
45
+ const store = new BetterSqliteStore();
46
+ await store.initialize();
47
+
48
+ const adapter = new MyFrameworkAdapter({ app: appInstance });
49
+
50
+ await Lens.setStore(store)
51
+ .setAdapter(adapter)
52
+ .setWatchers([
53
+ new RequestWatcher(),
54
+ new QueryWatcher(),
55
+ new CacheWatcher(),
56
+ new ExceptionWatcher(),
57
+ ])
58
+ .start({
59
+ appName: 'My Application',
60
+ enabled: process.env.NODE_ENV !== 'production',
61
+ basePath: 'lens-dashboard', // UI will be served at /lens-dashboard
62
+ });
63
+
64
+ console.log('Lens core initialized.');
65
+ }
66
+
67
+ // In your application's main entry point:
68
+ // bootstrapLens(yourFrameworkAppInstance);
69
+ ```
@@ -24,6 +24,9 @@ __export(store_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(store_exports);
26
26
  var Store = class {
27
+ getAllExceptions(_paginationParams) {
28
+ return this.defaultMinimalPaginate();
29
+ }
27
30
  stringifyData(data) {
28
31
  if (typeof data === "string") {
29
32
  return data;
@@ -34,4 +37,14 @@ var Store = class {
34
37
  console.error(`Failed to stringify lens data: ${e}`);
35
38
  }
36
39
  }
40
+ defaultMinimalPaginate() {
41
+ return Promise.resolve({
42
+ data: [],
43
+ meta: {
44
+ currentPage: 0,
45
+ lastPage: 0,
46
+ total: 0
47
+ }
48
+ });
49
+ }
37
50
  };
@@ -1,6 +1,7 @@
1
1
  import { WatcherTypeEnum, PaginationParams, Paginator, LensEntry } from '../types/index.cjs';
2
2
  import 'sql-formatter';
3
3
 
4
+ type MinimalPaginatePromise = Promise<Paginator<Omit<LensEntry, "data">[]>>;
4
5
  declare abstract class Store {
5
6
  abstract initialize(): Promise<void>;
6
7
  abstract save(entry: {
@@ -11,15 +12,17 @@ declare abstract class Store {
11
12
  timestamp?: string;
12
13
  requestId?: string;
13
14
  }): Promise<void>;
14
- abstract getAllRequests(paginationParams: PaginationParams): Promise<Paginator<Omit<LensEntry, "data">[]>>;
15
+ abstract getAllRequests(paginationParams: PaginationParams): MinimalPaginatePromise;
15
16
  abstract getAllQueries(paginationParams: PaginationParams): Promise<Paginator<LensEntry[]>>;
16
- abstract allByRequestId(requestId: string, type: WatcherTypeEnum): Promise<LensEntry[]>;
17
- abstract getAllCacheEntries(paginationParams: PaginationParams): Promise<Paginator<Omit<LensEntry, "data">[]>>;
17
+ abstract getAllCacheEntries(paginationParams: PaginationParams): MinimalPaginatePromise;
18
+ abstract allByRequestId(requestId: string, type: WatcherTypeEnum, includeFullData?: boolean): Promise<LensEntry[]>;
18
19
  abstract find(type: WatcherTypeEnum, id: string): Promise<LensEntry | null>;
19
20
  abstract truncate(): Promise<void>;
20
21
  abstract paginate<T>(type: WatcherTypeEnum, pagination: PaginationParams): Promise<Paginator<T>>;
21
22
  abstract count(type: WatcherTypeEnum): Promise<number>;
23
+ getAllExceptions(_paginationParams: PaginationParams): MinimalPaginatePromise;
22
24
  protected stringifyData(data: Record<string, any> | string): string | undefined;
25
+ protected defaultMinimalPaginate(): MinimalPaginatePromise;
23
26
  }
24
27
 
25
28
  export { Store as default };
@@ -1,6 +1,7 @@
1
1
  import { WatcherTypeEnum, PaginationParams, Paginator, LensEntry } from '../types/index.js';
2
2
  import 'sql-formatter';
3
3
 
4
+ type MinimalPaginatePromise = Promise<Paginator<Omit<LensEntry, "data">[]>>;
4
5
  declare abstract class Store {
5
6
  abstract initialize(): Promise<void>;
6
7
  abstract save(entry: {
@@ -11,15 +12,17 @@ declare abstract class Store {
11
12
  timestamp?: string;
12
13
  requestId?: string;
13
14
  }): Promise<void>;
14
- abstract getAllRequests(paginationParams: PaginationParams): Promise<Paginator<Omit<LensEntry, "data">[]>>;
15
+ abstract getAllRequests(paginationParams: PaginationParams): MinimalPaginatePromise;
15
16
  abstract getAllQueries(paginationParams: PaginationParams): Promise<Paginator<LensEntry[]>>;
16
- abstract allByRequestId(requestId: string, type: WatcherTypeEnum): Promise<LensEntry[]>;
17
- abstract getAllCacheEntries(paginationParams: PaginationParams): Promise<Paginator<Omit<LensEntry, "data">[]>>;
17
+ abstract getAllCacheEntries(paginationParams: PaginationParams): MinimalPaginatePromise;
18
+ abstract allByRequestId(requestId: string, type: WatcherTypeEnum, includeFullData?: boolean): Promise<LensEntry[]>;
18
19
  abstract find(type: WatcherTypeEnum, id: string): Promise<LensEntry | null>;
19
20
  abstract truncate(): Promise<void>;
20
21
  abstract paginate<T>(type: WatcherTypeEnum, pagination: PaginationParams): Promise<Paginator<T>>;
21
22
  abstract count(type: WatcherTypeEnum): Promise<number>;
23
+ getAllExceptions(_paginationParams: PaginationParams): MinimalPaginatePromise;
22
24
  protected stringifyData(data: Record<string, any> | string): string | undefined;
25
+ protected defaultMinimalPaginate(): MinimalPaginatePromise;
23
26
  }
24
27
 
25
28
  export { Store as default };
@@ -1,5 +1,8 @@
1
1
  // src/abstracts/store.ts
2
2
  var Store = class {
3
+ getAllExceptions(_paginationParams) {
4
+ return this.defaultMinimalPaginate();
5
+ }
3
6
  stringifyData(data) {
4
7
  if (typeof data === "string") {
5
8
  return data;
@@ -10,6 +13,16 @@ var Store = class {
10
13
  console.error(`Failed to stringify lens data: ${e}`);
11
14
  }
12
15
  }
16
+ defaultMinimalPaginate() {
17
+ return Promise.resolve({
18
+ data: [],
19
+ meta: {
20
+ currentPage: 0,
21
+ lastPage: 0,
22
+ total: 0
23
+ }
24
+ });
25
+ }
13
26
  };
14
27
  export {
15
28
  Store as default
@@ -87,10 +87,16 @@ var ApiController = class {
87
87
  request.id,
88
88
  "cache" /* CACHE */
89
89
  );
90
+ const exceptions = await getStore().allByRequestId(
91
+ request.id,
92
+ "exception" /* EXCEPTION */,
93
+ false
94
+ );
90
95
  return this.resourceResponse({
91
96
  request,
92
97
  queries,
93
- cacheEntries
98
+ cacheEntries,
99
+ exceptions
94
100
  });
95
101
  }
96
102
  static async getQueries({
@@ -122,6 +128,21 @@ var ApiController = class {
122
128
  }
123
129
  return this.resourceResponse(cacheEntry);
124
130
  }
131
+ static async getExceptions({ qs }) {
132
+ return this.paginatedResponse(
133
+ await getStore().getAllExceptions(this.extractPaginationParams(qs))
134
+ );
135
+ }
136
+ static async getException({ params }) {
137
+ const exception = await getStore().find(
138
+ "exception" /* EXCEPTION */,
139
+ params.id
140
+ );
141
+ if (!exception) {
142
+ return this.notFoundResponse();
143
+ }
144
+ return this.resourceResponse(exception);
145
+ }
125
146
  static async truncate() {
126
147
  await getStore().truncate();
127
148
  return this.baseResponse({}, 200, "All entries cleared");
@@ -1,4 +1,4 @@
1
- import { RouteDefinitionHandler, ApiResponse, LensEntry } from '../types/index.cjs';
1
+ import { RouteDefinitionHandler, ApiResponse, LensEntry, Paginator } from '../types/index.cjs';
2
2
  import 'sql-formatter';
3
3
 
4
4
  declare class ApiController {
@@ -8,6 +8,8 @@ declare class ApiController {
8
8
  static getQuery({ params, }: RouteDefinitionHandler): Promise<ApiResponse<LensEntry>>;
9
9
  static getCacheEntries({ qs }: RouteDefinitionHandler): Promise<ApiResponse<Omit<LensEntry, "data">[]>>;
10
10
  static getCacheEntry({ params }: RouteDefinitionHandler): Promise<ApiResponse<Object>>;
11
+ static getExceptions({ qs }: RouteDefinitionHandler): Promise<ApiResponse<Omit<LensEntry, "data">[]>>;
12
+ static getException({ params }: RouteDefinitionHandler): Promise<ApiResponse<Object>>;
11
13
  static truncate(): Promise<ApiResponse<{}>>;
12
14
  static fetchUiConfig(): {
13
15
  appName: string;
@@ -20,7 +22,7 @@ declare class ApiController {
20
22
  private static extractPaginationParams;
21
23
  private static resourceResponse;
22
24
  private static notFoundResponse;
23
- private static paginatedResponse;
25
+ static paginatedResponse<T extends Object>(data: Paginator<T>): ApiResponse<T>;
24
26
  private static baseResponse;
25
27
  }
26
28
 
@@ -1,4 +1,4 @@
1
- import { RouteDefinitionHandler, ApiResponse, LensEntry } from '../types/index.js';
1
+ import { RouteDefinitionHandler, ApiResponse, LensEntry, Paginator } from '../types/index.js';
2
2
  import 'sql-formatter';
3
3
 
4
4
  declare class ApiController {
@@ -8,6 +8,8 @@ declare class ApiController {
8
8
  static getQuery({ params, }: RouteDefinitionHandler): Promise<ApiResponse<LensEntry>>;
9
9
  static getCacheEntries({ qs }: RouteDefinitionHandler): Promise<ApiResponse<Omit<LensEntry, "data">[]>>;
10
10
  static getCacheEntry({ params }: RouteDefinitionHandler): Promise<ApiResponse<Object>>;
11
+ static getExceptions({ qs }: RouteDefinitionHandler): Promise<ApiResponse<Omit<LensEntry, "data">[]>>;
12
+ static getException({ params }: RouteDefinitionHandler): Promise<ApiResponse<Object>>;
11
13
  static truncate(): Promise<ApiResponse<{}>>;
12
14
  static fetchUiConfig(): {
13
15
  appName: string;
@@ -20,7 +22,7 @@ declare class ApiController {
20
22
  private static extractPaginationParams;
21
23
  private static resourceResponse;
22
24
  private static notFoundResponse;
23
- private static paginatedResponse;
25
+ static paginatedResponse<T extends Object>(data: Paginator<T>): ApiResponse<T>;
24
26
  private static baseResponse;
25
27
  }
26
28
 
@@ -61,10 +61,16 @@ var ApiController = class {
61
61
  request.id,
62
62
  "cache" /* CACHE */
63
63
  );
64
+ const exceptions = await getStore().allByRequestId(
65
+ request.id,
66
+ "exception" /* EXCEPTION */,
67
+ false
68
+ );
64
69
  return this.resourceResponse({
65
70
  request,
66
71
  queries,
67
- cacheEntries
72
+ cacheEntries,
73
+ exceptions
68
74
  });
69
75
  }
70
76
  static async getQueries({
@@ -96,6 +102,21 @@ var ApiController = class {
96
102
  }
97
103
  return this.resourceResponse(cacheEntry);
98
104
  }
105
+ static async getExceptions({ qs }) {
106
+ return this.paginatedResponse(
107
+ await getStore().getAllExceptions(this.extractPaginationParams(qs))
108
+ );
109
+ }
110
+ static async getException({ params }) {
111
+ const exception = await getStore().find(
112
+ "exception" /* EXCEPTION */,
113
+ params.id
114
+ );
115
+ if (!exception) {
116
+ return this.notFoundResponse();
117
+ }
118
+ return this.resourceResponse(exception);
119
+ }
99
120
  static async truncate() {
100
121
  await getStore().truncate();
101
122
  return this.baseResponse({}, 200, "All entries cleared");
@@ -97,10 +97,16 @@ var ApiController = class {
97
97
  request.id,
98
98
  "cache" /* CACHE */
99
99
  );
100
+ const exceptions = await getStore().allByRequestId(
101
+ request.id,
102
+ "exception" /* EXCEPTION */,
103
+ false
104
+ );
100
105
  return this.resourceResponse({
101
106
  request,
102
107
  queries,
103
- cacheEntries
108
+ cacheEntries,
109
+ exceptions
104
110
  });
105
111
  }
106
112
  static async getQueries({
@@ -132,6 +138,21 @@ var ApiController = class {
132
138
  }
133
139
  return this.resourceResponse(cacheEntry);
134
140
  }
141
+ static async getExceptions({ qs }) {
142
+ return this.paginatedResponse(
143
+ await getStore().getAllExceptions(this.extractPaginationParams(qs))
144
+ );
145
+ }
146
+ static async getException({ params }) {
147
+ const exception = await getStore().find(
148
+ "exception" /* EXCEPTION */,
149
+ params.id
150
+ );
151
+ if (!exception) {
152
+ return this.notFoundResponse();
153
+ }
154
+ return this.resourceResponse(exception);
155
+ }
135
156
  static async truncate() {
136
157
  await getStore().truncate();
137
158
  return this.baseResponse({}, 200, "All entries cleared");
@@ -183,6 +204,9 @@ var path2 = __toESM(require("path"), 1);
183
204
 
184
205
  // src/abstracts/store.ts
185
206
  var Store = class {
207
+ getAllExceptions(_paginationParams) {
208
+ return this.defaultMinimalPaginate();
209
+ }
186
210
  stringifyData(data) {
187
211
  if (typeof data === "string") {
188
212
  return data;
@@ -193,6 +217,16 @@ var Store = class {
193
217
  console.error(`Failed to stringify lens data: ${e}`);
194
218
  }
195
219
  }
220
+ defaultMinimalPaginate() {
221
+ return Promise.resolve({
222
+ data: [],
223
+ meta: {
224
+ currentPage: 0,
225
+ lastPage: 0,
226
+ total: 0
227
+ }
228
+ });
229
+ }
196
230
  };
197
231
 
198
232
  // src/stores/better_sqlite.ts
@@ -231,11 +265,14 @@ var BetterSqliteStore = class extends Store {
231
265
  async getAllCacheEntries(pagination) {
232
266
  return await this.paginate("cache" /* CACHE */, pagination);
233
267
  }
234
- async allByRequestId(requestId, type) {
268
+ async getAllExceptions(pagination) {
269
+ return await this.paginate("exception" /* EXCEPTION */, pagination, false);
270
+ }
271
+ async allByRequestId(requestId, type, includeFullData = true) {
235
272
  const rows = this.connection.prepare(
236
- `${this.getSelectedColumns()} FROM ${TABLE_NAME} WHERE type = $type AND lens_entry_id = $requestId ORDER BY created_at DESC`
273
+ `${this.getSelectedColumns(includeFullData)} FROM ${TABLE_NAME} WHERE type = $type AND lens_entry_id = $requestId ORDER BY created_at DESC`
237
274
  ).all({ type, requestId });
238
- return this.mapRows(rows);
275
+ return this.mapRows(rows, includeFullData);
239
276
  }
240
277
  async paginate(type, { page, perPage }, includeFullData = true) {
241
278
  const offset = (page - 1) * perPage;
@@ -397,6 +434,7 @@ var Lens = class {
397
434
  requests: `/${config.basePath}/api/requests`,
398
435
  queries: `/${config.basePath}/api/queries`,
399
436
  cache: `/${config.basePath}/api/cache`,
437
+ exceptions: `/${config.basePath}/api/exceptions`,
400
438
  truncate: `/${config.basePath}/api/truncate`
401
439
  }
402
440
  };
@@ -439,6 +477,16 @@ var Lens = class {
439
477
  path: `${basePath}/api/cache/:id`,
440
478
  handler: async (data) => await ApiController.getCacheEntry(data)
441
479
  },
480
+ {
481
+ method: "GET",
482
+ path: `${basePath}/api/exceptions`,
483
+ handler: async (data) => await ApiController.getExceptions(data)
484
+ },
485
+ {
486
+ method: "GET",
487
+ path: `${basePath}/api/exceptions/:id`,
488
+ handler: async (data) => await ApiController.getException(data)
489
+ },
442
490
  {
443
491
  method: "DELETE",
444
492
  path: `${basePath}/api/truncate`,
package/dist/core/lens.js CHANGED
@@ -61,10 +61,16 @@ var ApiController = class {
61
61
  request.id,
62
62
  "cache" /* CACHE */
63
63
  );
64
+ const exceptions = await getStore().allByRequestId(
65
+ request.id,
66
+ "exception" /* EXCEPTION */,
67
+ false
68
+ );
64
69
  return this.resourceResponse({
65
70
  request,
66
71
  queries,
67
- cacheEntries
72
+ cacheEntries,
73
+ exceptions
68
74
  });
69
75
  }
70
76
  static async getQueries({
@@ -96,6 +102,21 @@ var ApiController = class {
96
102
  }
97
103
  return this.resourceResponse(cacheEntry);
98
104
  }
105
+ static async getExceptions({ qs }) {
106
+ return this.paginatedResponse(
107
+ await getStore().getAllExceptions(this.extractPaginationParams(qs))
108
+ );
109
+ }
110
+ static async getException({ params }) {
111
+ const exception = await getStore().find(
112
+ "exception" /* EXCEPTION */,
113
+ params.id
114
+ );
115
+ if (!exception) {
116
+ return this.notFoundResponse();
117
+ }
118
+ return this.resourceResponse(exception);
119
+ }
99
120
  static async truncate() {
100
121
  await getStore().truncate();
101
122
  return this.baseResponse({}, 200, "All entries cleared");
@@ -147,6 +168,9 @@ import * as path2 from "path";
147
168
 
148
169
  // src/abstracts/store.ts
149
170
  var Store = class {
171
+ getAllExceptions(_paginationParams) {
172
+ return this.defaultMinimalPaginate();
173
+ }
150
174
  stringifyData(data) {
151
175
  if (typeof data === "string") {
152
176
  return data;
@@ -157,6 +181,16 @@ var Store = class {
157
181
  console.error(`Failed to stringify lens data: ${e}`);
158
182
  }
159
183
  }
184
+ defaultMinimalPaginate() {
185
+ return Promise.resolve({
186
+ data: [],
187
+ meta: {
188
+ currentPage: 0,
189
+ lastPage: 0,
190
+ total: 0
191
+ }
192
+ });
193
+ }
160
194
  };
161
195
 
162
196
  // src/stores/better_sqlite.ts
@@ -195,11 +229,14 @@ var BetterSqliteStore = class extends Store {
195
229
  async getAllCacheEntries(pagination) {
196
230
  return await this.paginate("cache" /* CACHE */, pagination);
197
231
  }
198
- async allByRequestId(requestId, type) {
232
+ async getAllExceptions(pagination) {
233
+ return await this.paginate("exception" /* EXCEPTION */, pagination, false);
234
+ }
235
+ async allByRequestId(requestId, type, includeFullData = true) {
199
236
  const rows = this.connection.prepare(
200
- `${this.getSelectedColumns()} FROM ${TABLE_NAME} WHERE type = $type AND lens_entry_id = $requestId ORDER BY created_at DESC`
237
+ `${this.getSelectedColumns(includeFullData)} FROM ${TABLE_NAME} WHERE type = $type AND lens_entry_id = $requestId ORDER BY created_at DESC`
201
238
  ).all({ type, requestId });
202
- return this.mapRows(rows);
239
+ return this.mapRows(rows, includeFullData);
203
240
  }
204
241
  async paginate(type, { page, perPage }, includeFullData = true) {
205
242
  const offset = (page - 1) * perPage;
@@ -360,6 +397,7 @@ var Lens = class {
360
397
  requests: `/${config.basePath}/api/requests`,
361
398
  queries: `/${config.basePath}/api/queries`,
362
399
  cache: `/${config.basePath}/api/cache`,
400
+ exceptions: `/${config.basePath}/api/exceptions`,
363
401
  truncate: `/${config.basePath}/api/truncate`
364
402
  }
365
403
  };
@@ -402,6 +440,16 @@ var Lens = class {
402
440
  path: `${basePath}/api/cache/:id`,
403
441
  handler: async (data) => await ApiController.getCacheEntry(data)
404
442
  },
443
+ {
444
+ method: "GET",
445
+ path: `${basePath}/api/exceptions`,
446
+ handler: async (data) => await ApiController.getExceptions(data)
447
+ },
448
+ {
449
+ method: "GET",
450
+ path: `${basePath}/api/exceptions/:id`,
451
+ handler: async (data) => await ApiController.getException(data)
452
+ },
405
453
  {
406
454
  method: "DELETE",
407
455
  path: `${basePath}/api/truncate`,
@@ -0,0 +1,52 @@
1
+ import { ExceptionEntry } from './types/index.js';
2
+
3
+ /**
4
+ * Clean a raw stack trace string, removing internal Node.js frames.
5
+ */
6
+ declare function cleanStack(stack?: string): string;
7
+ /**
8
+ * Extract file information from the top frame of a stack trace.
9
+ */
10
+ declare function getFileInfo(stack?: string): {
11
+ file: string;
12
+ line: number;
13
+ column: number;
14
+ function: string;
15
+ };
16
+ /**
17
+ * Parse a stack trace into an array of structured frames.
18
+ */
19
+ declare function getStackTrace(stack?: string): string[];
20
+ /**
21
+ * Extract surrounding code lines (context) from a file where the error occurred.
22
+ */
23
+ declare function extractCodeFrame({ file, line, column, contextLines, }: {
24
+ file: string;
25
+ line: number;
26
+ column: number;
27
+ contextLines?: number;
28
+ }): {
29
+ file: string;
30
+ line: number;
31
+ column: number;
32
+ context: {
33
+ pre: string[];
34
+ error: string;
35
+ post: string[];
36
+ };
37
+ } | null;
38
+ /**
39
+ * Construct a normalized error object with metadata, stack trace, and code frame.
40
+ */
41
+ declare function constructErrorObject(err: Error): ExceptionEntry;
42
+
43
+ declare const exception_cleanStack: typeof cleanStack;
44
+ declare const exception_constructErrorObject: typeof constructErrorObject;
45
+ declare const exception_extractCodeFrame: typeof extractCodeFrame;
46
+ declare const exception_getFileInfo: typeof getFileInfo;
47
+ declare const exception_getStackTrace: typeof getStackTrace;
48
+ declare namespace exception {
49
+ export { exception_cleanStack as cleanStack, exception_constructErrorObject as constructErrorObject, exception_extractCodeFrame as extractCodeFrame, exception_getFileInfo as getFileInfo, exception_getStackTrace as getStackTrace };
50
+ }
51
+
52
+ export { getStackTrace as a, extractCodeFrame as b, cleanStack as c, constructErrorObject as d, exception as e, getFileInfo as g };
@@ -0,0 +1,52 @@
1
+ import { ExceptionEntry } from './types/index.cjs';
2
+
3
+ /**
4
+ * Clean a raw stack trace string, removing internal Node.js frames.
5
+ */
6
+ declare function cleanStack(stack?: string): string;
7
+ /**
8
+ * Extract file information from the top frame of a stack trace.
9
+ */
10
+ declare function getFileInfo(stack?: string): {
11
+ file: string;
12
+ line: number;
13
+ column: number;
14
+ function: string;
15
+ };
16
+ /**
17
+ * Parse a stack trace into an array of structured frames.
18
+ */
19
+ declare function getStackTrace(stack?: string): string[];
20
+ /**
21
+ * Extract surrounding code lines (context) from a file where the error occurred.
22
+ */
23
+ declare function extractCodeFrame({ file, line, column, contextLines, }: {
24
+ file: string;
25
+ line: number;
26
+ column: number;
27
+ contextLines?: number;
28
+ }): {
29
+ file: string;
30
+ line: number;
31
+ column: number;
32
+ context: {
33
+ pre: string[];
34
+ error: string;
35
+ post: string[];
36
+ };
37
+ } | null;
38
+ /**
39
+ * Construct a normalized error object with metadata, stack trace, and code frame.
40
+ */
41
+ declare function constructErrorObject(err: Error): ExceptionEntry;
42
+
43
+ declare const exception_cleanStack: typeof cleanStack;
44
+ declare const exception_constructErrorObject: typeof constructErrorObject;
45
+ declare const exception_extractCodeFrame: typeof extractCodeFrame;
46
+ declare const exception_getFileInfo: typeof getFileInfo;
47
+ declare const exception_getStackTrace: typeof getStackTrace;
48
+ declare namespace exception {
49
+ export { exception_cleanStack as cleanStack, exception_constructErrorObject as constructErrorObject, exception_extractCodeFrame as extractCodeFrame, exception_getFileInfo as getFileInfo, exception_getStackTrace as getStackTrace };
50
+ }
51
+
52
+ export { getStackTrace as a, extractCodeFrame as b, cleanStack as c, constructErrorObject as d, exception as e, getFileInfo as g };