@lensjs/core 1.0.12 → 2.0.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.
Files changed (74) hide show
  1. package/dist/abstracts/store.cjs +10 -0
  2. package/dist/abstracts/store.d.cts +2 -0
  3. package/dist/abstracts/store.d.ts +2 -0
  4. package/dist/abstracts/store.js +10 -0
  5. package/dist/core/api_controller.cjs +26 -4
  6. package/dist/core/api_controller.d.cts +3 -1
  7. package/dist/core/api_controller.d.ts +3 -1
  8. package/dist/core/api_controller.js +26 -4
  9. package/dist/core/lens.cjs +58 -7
  10. package/dist/core/lens.js +59 -8
  11. package/dist/index.cjs +112 -7
  12. package/dist/index.d.cts +5 -2
  13. package/dist/index.d.ts +5 -2
  14. package/dist/index.js +110 -8
  15. package/dist/stores/better_sqlite.cjs +21 -3
  16. package/dist/stores/better_sqlite.d.cts +8 -0
  17. package/dist/stores/better_sqlite.d.ts +8 -0
  18. package/dist/stores/better_sqlite.js +22 -4
  19. package/dist/stores/index.cjs +21 -3
  20. package/dist/stores/index.js +22 -4
  21. package/dist/types/index.cjs +1 -0
  22. package/dist/types/index.d.cts +25 -2
  23. package/dist/types/index.d.ts +25 -2
  24. package/dist/types/index.js +1 -0
  25. package/dist/ui/assets/CacheActionBadge-3jjmNjC6.js +1 -0
  26. package/dist/ui/assets/CacheEntriesTable-DPLre6br.js +1 -0
  27. package/dist/ui/assets/CacheEntryContainer-WN6LkoCR.js +2 -0
  28. package/dist/ui/assets/CacheEntryDetails-CHt_pNTk.js +1 -0
  29. package/dist/ui/assets/CacheEntryDetailsContainer-BhquSApO.js +2 -0
  30. package/dist/ui/assets/LoadMore-DHOrhPsi.js +1 -0
  31. package/dist/ui/assets/QueriesContainer-Cl6rq4dH.js +2 -0
  32. package/dist/ui/assets/{QueryDetailsContainer-E7P-IO7f.js → QueryDetailsContainer-eoLkgEjj.js} +15 -15
  33. package/dist/ui/assets/QueryTable-BXSzT-Cm.js +1 -0
  34. package/dist/ui/assets/RequestDetails-CIB7_XWh.js +1 -0
  35. package/dist/ui/assets/{RequestDetailsContainer-DuDo-IqS.js → RequestDetailsContainer-BaH6fUK7.js} +2 -2
  36. package/dist/ui/assets/RequestsContainer-DLS17BWP.js +2 -0
  37. package/dist/ui/assets/RequetsTable-B51VXisk.js +1 -0
  38. package/dist/ui/assets/{StatusCode-FQEjz7gK.js → StatusCode-DVhX11V3.js} +1 -1
  39. package/dist/ui/assets/{TabbedDataViewer-cBDdPwIz.js → TabbedDataViewer-CNSEhc6h.js} +1 -1
  40. package/dist/ui/assets/{Table-DYaXk80S.js → Table-D1Kpw7PA.js} +2 -2
  41. package/dist/ui/assets/columns-BIDLCW64.js +1 -0
  42. package/dist/ui/assets/columns-jYfhBxOM.js +1 -0
  43. package/dist/ui/assets/{index-BS8XxorB.js → index-BdvbrZNf.js} +24 -19
  44. package/dist/ui/assets/index-C04tuZDI.css +1 -0
  45. package/dist/ui/assets/useCacheEntries-vuHEIj6E.js +1 -0
  46. package/dist/ui/assets/useLensApi-Bzmx8hps.js +1 -0
  47. package/dist/ui/assets/{useLoadMore-CJltToLI.js → useLoadMore-twYxPJ-d.js} +1 -1
  48. package/dist/ui/assets/useQueries-BYFLoUQR.js +1 -0
  49. package/dist/ui/index.html +2 -2
  50. package/dist/utils/async_context.cjs +31 -0
  51. package/dist/utils/async_context.d.cts +8 -0
  52. package/dist/utils/async_context.d.ts +8 -0
  53. package/dist/utils/async_context.js +6 -0
  54. package/dist/utils/event_emitter.cjs +5 -2
  55. package/dist/utils/event_emitter.d.cts +8 -1
  56. package/dist/utils/event_emitter.d.ts +8 -1
  57. package/dist/utils/event_emitter.js +3 -1
  58. package/dist/watchers/cache_watcher.cjs +111 -0
  59. package/dist/watchers/cache_watcher.d.cts +11 -0
  60. package/dist/watchers/cache_watcher.d.ts +11 -0
  61. package/dist/watchers/cache_watcher.js +88 -0
  62. package/dist/watchers/index.cjs +44 -0
  63. package/dist/watchers/index.d.cts +1 -0
  64. package/dist/watchers/index.d.ts +1 -0
  65. package/dist/watchers/index.js +43 -0
  66. package/package.json +1 -1
  67. package/dist/ui/assets/QueriesContainer-CAAsjjW5.js +0 -2
  68. package/dist/ui/assets/QueryTable-BcrtUssT.js +0 -1
  69. package/dist/ui/assets/RequestDetails-C2DZBu5H.js +0 -1
  70. package/dist/ui/assets/RequestsContainer-DK3hQVz9.js +0 -2
  71. package/dist/ui/assets/RequetsTable-DgP8p60b.js +0 -1
  72. package/dist/ui/assets/index-DzNHqeKh.css +0 -1
  73. package/dist/ui/assets/useLensApi-DG6atd6d.js +0 -1
  74. package/dist/ui/assets/useQueries-C8mDDDc6.js +0 -1
@@ -24,4 +24,14 @@ __export(store_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(store_exports);
26
26
  var Store = class {
27
+ stringifyData(data) {
28
+ if (typeof data === "string") {
29
+ return data;
30
+ }
31
+ try {
32
+ return JSON.stringify(data);
33
+ } catch (e) {
34
+ console.error(`Failed to stringify lens data: ${e}`);
35
+ }
36
+ }
27
37
  };
@@ -14,10 +14,12 @@ declare abstract class Store {
14
14
  abstract getAllRequests(paginationParams: PaginationParams): Promise<Paginator<Omit<LensEntry, "data">[]>>;
15
15
  abstract getAllQueries(paginationParams: PaginationParams): Promise<Paginator<LensEntry[]>>;
16
16
  abstract allByRequestId(requestId: string, type: WatcherTypeEnum): Promise<LensEntry[]>;
17
+ abstract getAllCacheEntries(paginationParams: PaginationParams): Promise<Paginator<Omit<LensEntry, "data">[]>>;
17
18
  abstract find(type: WatcherTypeEnum, id: string): Promise<LensEntry | null>;
18
19
  abstract truncate(): Promise<void>;
19
20
  abstract paginate<T>(type: WatcherTypeEnum, pagination: PaginationParams): Promise<Paginator<T>>;
20
21
  abstract count(type: WatcherTypeEnum): Promise<number>;
22
+ protected stringifyData(data: Record<string, any> | string): string | undefined;
21
23
  }
22
24
 
23
25
  export { Store as default };
@@ -14,10 +14,12 @@ declare abstract class Store {
14
14
  abstract getAllRequests(paginationParams: PaginationParams): Promise<Paginator<Omit<LensEntry, "data">[]>>;
15
15
  abstract getAllQueries(paginationParams: PaginationParams): Promise<Paginator<LensEntry[]>>;
16
16
  abstract allByRequestId(requestId: string, type: WatcherTypeEnum): Promise<LensEntry[]>;
17
+ abstract getAllCacheEntries(paginationParams: PaginationParams): Promise<Paginator<Omit<LensEntry, "data">[]>>;
17
18
  abstract find(type: WatcherTypeEnum, id: string): Promise<LensEntry | null>;
18
19
  abstract truncate(): Promise<void>;
19
20
  abstract paginate<T>(type: WatcherTypeEnum, pagination: PaginationParams): Promise<Paginator<T>>;
20
21
  abstract count(type: WatcherTypeEnum): Promise<number>;
22
+ protected stringifyData(data: Record<string, any> | string): string | undefined;
21
23
  }
22
24
 
23
25
  export { Store as default };
@@ -1,5 +1,15 @@
1
1
  // src/abstracts/store.ts
2
2
  var Store = class {
3
+ stringifyData(data) {
4
+ if (typeof data === "string") {
5
+ return data;
6
+ }
7
+ try {
8
+ return JSON.stringify(data);
9
+ } catch (e) {
10
+ console.error(`Failed to stringify lens data: ${e}`);
11
+ }
12
+ }
3
13
  };
4
14
  export {
5
15
  Store as default
@@ -74,14 +74,24 @@ var ApiController = class {
74
74
  await getStore().getAllRequests(this.extractPaginationParams(qs))
75
75
  );
76
76
  }
77
- static async getRequest({
78
- params
79
- }) {
77
+ static async getRequest({ params }) {
80
78
  const request = await getStore().find("request" /* REQUEST */, params.id);
81
79
  if (!request) {
82
80
  return this.notFoundResponse();
83
81
  }
84
- return this.resourceResponse(request);
82
+ const queries = await getStore().allByRequestId(
83
+ request.id,
84
+ "query" /* QUERY */
85
+ );
86
+ const cacheEntries = await getStore().allByRequestId(
87
+ request.id,
88
+ "cache" /* CACHE */
89
+ );
90
+ return this.resourceResponse({
91
+ request,
92
+ queries,
93
+ cacheEntries
94
+ });
85
95
  }
86
96
  static async getQueries({
87
97
  qs
@@ -100,6 +110,18 @@ var ApiController = class {
100
110
  }
101
111
  return this.resourceResponse(query);
102
112
  }
113
+ static async getCacheEntries({ qs }) {
114
+ return this.paginatedResponse(
115
+ await getStore().getAllCacheEntries(this.extractPaginationParams(qs))
116
+ );
117
+ }
118
+ static async getCacheEntry({ params }) {
119
+ const cacheEntry = await getStore().find("cache" /* CACHE */, params.id);
120
+ if (!cacheEntry) {
121
+ return this.notFoundResponse();
122
+ }
123
+ return this.resourceResponse(cacheEntry);
124
+ }
103
125
  static async truncate() {
104
126
  await getStore().truncate();
105
127
  return this.baseResponse({}, 200, "All entries cleared");
@@ -3,9 +3,11 @@ import 'sql-formatter';
3
3
 
4
4
  declare class ApiController {
5
5
  static getRequests({ qs }: RouteDefinitionHandler): Promise<ApiResponse<Omit<LensEntry, "data">[]>>;
6
- static getRequest({ params, }: RouteDefinitionHandler): Promise<ApiResponse<LensEntry>>;
6
+ static getRequest({ params }: RouteDefinitionHandler): Promise<ApiResponse<Object>>;
7
7
  static getQueries({ qs, }: RouteDefinitionHandler): Promise<ApiResponse<LensEntry[]>>;
8
8
  static getQuery({ params, }: RouteDefinitionHandler): Promise<ApiResponse<LensEntry>>;
9
+ static getCacheEntries({ qs }: RouteDefinitionHandler): Promise<ApiResponse<Omit<LensEntry, "data">[]>>;
10
+ static getCacheEntry({ params }: RouteDefinitionHandler): Promise<ApiResponse<Object>>;
9
11
  static truncate(): Promise<ApiResponse<{}>>;
10
12
  static fetchUiConfig(): {
11
13
  appName: string;
@@ -3,9 +3,11 @@ import 'sql-formatter';
3
3
 
4
4
  declare class ApiController {
5
5
  static getRequests({ qs }: RouteDefinitionHandler): Promise<ApiResponse<Omit<LensEntry, "data">[]>>;
6
- static getRequest({ params, }: RouteDefinitionHandler): Promise<ApiResponse<LensEntry>>;
6
+ static getRequest({ params }: RouteDefinitionHandler): Promise<ApiResponse<Object>>;
7
7
  static getQueries({ qs, }: RouteDefinitionHandler): Promise<ApiResponse<LensEntry[]>>;
8
8
  static getQuery({ params, }: RouteDefinitionHandler): Promise<ApiResponse<LensEntry>>;
9
+ static getCacheEntries({ qs }: RouteDefinitionHandler): Promise<ApiResponse<Omit<LensEntry, "data">[]>>;
10
+ static getCacheEntry({ params }: RouteDefinitionHandler): Promise<ApiResponse<Object>>;
9
11
  static truncate(): Promise<ApiResponse<{}>>;
10
12
  static fetchUiConfig(): {
11
13
  appName: string;
@@ -48,14 +48,24 @@ var ApiController = class {
48
48
  await getStore().getAllRequests(this.extractPaginationParams(qs))
49
49
  );
50
50
  }
51
- static async getRequest({
52
- params
53
- }) {
51
+ static async getRequest({ params }) {
54
52
  const request = await getStore().find("request" /* REQUEST */, params.id);
55
53
  if (!request) {
56
54
  return this.notFoundResponse();
57
55
  }
58
- return this.resourceResponse(request);
56
+ const queries = await getStore().allByRequestId(
57
+ request.id,
58
+ "query" /* QUERY */
59
+ );
60
+ const cacheEntries = await getStore().allByRequestId(
61
+ request.id,
62
+ "cache" /* CACHE */
63
+ );
64
+ return this.resourceResponse({
65
+ request,
66
+ queries,
67
+ cacheEntries
68
+ });
59
69
  }
60
70
  static async getQueries({
61
71
  qs
@@ -74,6 +84,18 @@ var ApiController = class {
74
84
  }
75
85
  return this.resourceResponse(query);
76
86
  }
87
+ static async getCacheEntries({ qs }) {
88
+ return this.paginatedResponse(
89
+ await getStore().getAllCacheEntries(this.extractPaginationParams(qs))
90
+ );
91
+ }
92
+ static async getCacheEntry({ params }) {
93
+ const cacheEntry = await getStore().find("cache" /* CACHE */, params.id);
94
+ if (!cacheEntry) {
95
+ return this.notFoundResponse();
96
+ }
97
+ return this.resourceResponse(cacheEntry);
98
+ }
77
99
  static async truncate() {
78
100
  await getStore().truncate();
79
101
  return this.baseResponse({}, 200, "All entries cleared");
@@ -84,14 +84,24 @@ var ApiController = class {
84
84
  await getStore().getAllRequests(this.extractPaginationParams(qs))
85
85
  );
86
86
  }
87
- static async getRequest({
88
- params
89
- }) {
87
+ static async getRequest({ params }) {
90
88
  const request = await getStore().find("request" /* REQUEST */, params.id);
91
89
  if (!request) {
92
90
  return this.notFoundResponse();
93
91
  }
94
- return this.resourceResponse(request);
92
+ const queries = await getStore().allByRequestId(
93
+ request.id,
94
+ "query" /* QUERY */
95
+ );
96
+ const cacheEntries = await getStore().allByRequestId(
97
+ request.id,
98
+ "cache" /* CACHE */
99
+ );
100
+ return this.resourceResponse({
101
+ request,
102
+ queries,
103
+ cacheEntries
104
+ });
95
105
  }
96
106
  static async getQueries({
97
107
  qs
@@ -110,6 +120,18 @@ var ApiController = class {
110
120
  }
111
121
  return this.resourceResponse(query);
112
122
  }
123
+ static async getCacheEntries({ qs }) {
124
+ return this.paginatedResponse(
125
+ await getStore().getAllCacheEntries(this.extractPaginationParams(qs))
126
+ );
127
+ }
128
+ static async getCacheEntry({ params }) {
129
+ const cacheEntry = await getStore().find("cache" /* CACHE */, params.id);
130
+ if (!cacheEntry) {
131
+ return this.notFoundResponse();
132
+ }
133
+ return this.resourceResponse(cacheEntry);
134
+ }
113
135
  static async truncate() {
114
136
  await getStore().truncate();
115
137
  return this.baseResponse({}, 200, "All entries cleared");
@@ -161,6 +183,16 @@ var path2 = __toESM(require("path"), 1);
161
183
 
162
184
  // src/abstracts/store.ts
163
185
  var Store = class {
186
+ stringifyData(data) {
187
+ if (typeof data === "string") {
188
+ return data;
189
+ }
190
+ try {
191
+ return JSON.stringify(data);
192
+ } catch (e) {
193
+ console.error(`Failed to stringify lens data: ${e}`);
194
+ }
195
+ }
164
196
  };
165
197
 
166
198
  // src/stores/better_sqlite.ts
@@ -183,11 +215,11 @@ var BetterSqliteStore = class extends Store {
183
215
  `INSERT INTO ${TABLE_NAME} (id, data, type, created_at, lens_entry_id, minimal_data) values($id, $data, $type, $created_at, $lens_entry_id, $minimalData)`
184
216
  ).run({
185
217
  id: entry.id ?? (0, import_crypto.randomUUID)(),
186
- data: JSON.stringify(entry.data),
218
+ data: this.stringifyData(entry.data),
187
219
  type: entry.type,
188
- created_at: entry.timestamp ?? (0, import_date.sqlDateTime)(),
220
+ created_at: entry.timestamp ?? (0, import_date.nowISO)(),
189
221
  lens_entry_id: entry.requestId || null,
190
- minimalData: JSON.stringify(entry.minimal_data ?? {})
222
+ minimalData: this.stringifyData(entry.minimal_data ?? {})
191
223
  });
192
224
  }
193
225
  async getAllQueries(pagination) {
@@ -196,6 +228,9 @@ var BetterSqliteStore = class extends Store {
196
228
  async getAllRequests(pagination) {
197
229
  return await this.paginate("request" /* REQUEST */, pagination, false);
198
230
  }
231
+ async getAllCacheEntries(pagination) {
232
+ return await this.paginate("cache" /* CACHE */, pagination);
233
+ }
199
234
  async allByRequestId(requestId, type) {
200
235
  const rows = this.connection.prepare(
201
236
  `${this.getSelectedColumns()} FROM ${TABLE_NAME} WHERE type = $type AND lens_entry_id = $requestId ORDER BY created_at DESC`
@@ -248,8 +283,13 @@ var BetterSqliteStore = class extends Store {
248
283
  CREATE INDEX IF NOT EXISTS lens_entries_id_type_index
249
284
  ON ${TABLE_NAME} (id, type);
250
285
  `;
286
+ const lensEntryIdIndex = `
287
+ CREATE INDEX IF NOT EXISTS lens_entry_id_index
288
+ ON ${TABLE_NAME} (lens_entry_id);
289
+ `;
251
290
  this.connection.exec(createTable);
252
291
  this.connection.exec(createIndex);
292
+ this.connection.exec(lensEntryIdIndex);
253
293
  }
254
294
  mapRow(row, includeFullData = true) {
255
295
  let data = includeFullData ? JSON.parse(row.data) : {};
@@ -356,6 +396,7 @@ var Lens = class {
356
396
  api: {
357
397
  requests: `/${config.basePath}/api/requests`,
358
398
  queries: `/${config.basePath}/api/queries`,
399
+ cache: `/${config.basePath}/api/cache`,
359
400
  truncate: `/${config.basePath}/api/truncate`
360
401
  }
361
402
  };
@@ -388,6 +429,16 @@ var Lens = class {
388
429
  path: `${basePath}/api/queries/:id`,
389
430
  handler: async (data) => await ApiController.getQuery(data)
390
431
  },
432
+ {
433
+ method: "GET",
434
+ path: `${basePath}/api/cache`,
435
+ handler: async (data) => await ApiController.getCacheEntries(data)
436
+ },
437
+ {
438
+ method: "GET",
439
+ path: `${basePath}/api/cache/:id`,
440
+ handler: async (data) => await ApiController.getCacheEntry(data)
441
+ },
391
442
  {
392
443
  method: "DELETE",
393
444
  path: `${basePath}/api/truncate`,
package/dist/core/lens.js CHANGED
@@ -48,14 +48,24 @@ var ApiController = class {
48
48
  await getStore().getAllRequests(this.extractPaginationParams(qs))
49
49
  );
50
50
  }
51
- static async getRequest({
52
- params
53
- }) {
51
+ static async getRequest({ params }) {
54
52
  const request = await getStore().find("request" /* REQUEST */, params.id);
55
53
  if (!request) {
56
54
  return this.notFoundResponse();
57
55
  }
58
- return this.resourceResponse(request);
56
+ const queries = await getStore().allByRequestId(
57
+ request.id,
58
+ "query" /* QUERY */
59
+ );
60
+ const cacheEntries = await getStore().allByRequestId(
61
+ request.id,
62
+ "cache" /* CACHE */
63
+ );
64
+ return this.resourceResponse({
65
+ request,
66
+ queries,
67
+ cacheEntries
68
+ });
59
69
  }
60
70
  static async getQueries({
61
71
  qs
@@ -74,6 +84,18 @@ var ApiController = class {
74
84
  }
75
85
  return this.resourceResponse(query);
76
86
  }
87
+ static async getCacheEntries({ qs }) {
88
+ return this.paginatedResponse(
89
+ await getStore().getAllCacheEntries(this.extractPaginationParams(qs))
90
+ );
91
+ }
92
+ static async getCacheEntry({ params }) {
93
+ const cacheEntry = await getStore().find("cache" /* CACHE */, params.id);
94
+ if (!cacheEntry) {
95
+ return this.notFoundResponse();
96
+ }
97
+ return this.resourceResponse(cacheEntry);
98
+ }
77
99
  static async truncate() {
78
100
  await getStore().truncate();
79
101
  return this.baseResponse({}, 200, "All entries cleared");
@@ -125,12 +147,22 @@ import * as path2 from "path";
125
147
 
126
148
  // src/abstracts/store.ts
127
149
  var Store = class {
150
+ stringifyData(data) {
151
+ if (typeof data === "string") {
152
+ return data;
153
+ }
154
+ try {
155
+ return JSON.stringify(data);
156
+ } catch (e) {
157
+ console.error(`Failed to stringify lens data: ${e}`);
158
+ }
159
+ }
128
160
  };
129
161
 
130
162
  // src/stores/better_sqlite.ts
131
163
  import { randomUUID } from "crypto";
132
164
  import Database from "libsql";
133
- import { sqlDateTime } from "@lensjs/date";
165
+ import { nowISO } from "@lensjs/date";
134
166
  var TABLE_NAME = "lens_entries";
135
167
  var BetterSqliteStore = class extends Store {
136
168
  connection;
@@ -147,11 +179,11 @@ var BetterSqliteStore = class extends Store {
147
179
  `INSERT INTO ${TABLE_NAME} (id, data, type, created_at, lens_entry_id, minimal_data) values($id, $data, $type, $created_at, $lens_entry_id, $minimalData)`
148
180
  ).run({
149
181
  id: entry.id ?? randomUUID(),
150
- data: JSON.stringify(entry.data),
182
+ data: this.stringifyData(entry.data),
151
183
  type: entry.type,
152
- created_at: entry.timestamp ?? sqlDateTime(),
184
+ created_at: entry.timestamp ?? nowISO(),
153
185
  lens_entry_id: entry.requestId || null,
154
- minimalData: JSON.stringify(entry.minimal_data ?? {})
186
+ minimalData: this.stringifyData(entry.minimal_data ?? {})
155
187
  });
156
188
  }
157
189
  async getAllQueries(pagination) {
@@ -160,6 +192,9 @@ var BetterSqliteStore = class extends Store {
160
192
  async getAllRequests(pagination) {
161
193
  return await this.paginate("request" /* REQUEST */, pagination, false);
162
194
  }
195
+ async getAllCacheEntries(pagination) {
196
+ return await this.paginate("cache" /* CACHE */, pagination);
197
+ }
163
198
  async allByRequestId(requestId, type) {
164
199
  const rows = this.connection.prepare(
165
200
  `${this.getSelectedColumns()} FROM ${TABLE_NAME} WHERE type = $type AND lens_entry_id = $requestId ORDER BY created_at DESC`
@@ -212,8 +247,13 @@ var BetterSqliteStore = class extends Store {
212
247
  CREATE INDEX IF NOT EXISTS lens_entries_id_type_index
213
248
  ON ${TABLE_NAME} (id, type);
214
249
  `;
250
+ const lensEntryIdIndex = `
251
+ CREATE INDEX IF NOT EXISTS lens_entry_id_index
252
+ ON ${TABLE_NAME} (lens_entry_id);
253
+ `;
215
254
  this.connection.exec(createTable);
216
255
  this.connection.exec(createIndex);
256
+ this.connection.exec(lensEntryIdIndex);
217
257
  }
218
258
  mapRow(row, includeFullData = true) {
219
259
  let data = includeFullData ? JSON.parse(row.data) : {};
@@ -319,6 +359,7 @@ var Lens = class {
319
359
  api: {
320
360
  requests: `/${config.basePath}/api/requests`,
321
361
  queries: `/${config.basePath}/api/queries`,
362
+ cache: `/${config.basePath}/api/cache`,
322
363
  truncate: `/${config.basePath}/api/truncate`
323
364
  }
324
365
  };
@@ -351,6 +392,16 @@ var Lens = class {
351
392
  path: `${basePath}/api/queries/:id`,
352
393
  handler: async (data) => await ApiController.getQuery(data)
353
394
  },
395
+ {
396
+ method: "GET",
397
+ path: `${basePath}/api/cache`,
398
+ handler: async (data) => await ApiController.getCacheEntries(data)
399
+ },
400
+ {
401
+ method: "GET",
402
+ path: `${basePath}/api/cache/:id`,
403
+ handler: async (data) => await ApiController.getCacheEntry(data)
404
+ },
354
405
  {
355
406
  method: "DELETE",
356
407
  path: `${basePath}/api/truncate`,
package/dist/index.cjs CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  BetterSqliteStore: () => BetterSqliteStore,
34
+ CacheWatcher: () => CacheWatcher,
34
35
  Lens: () => Lens,
35
36
  LensAdapter: () => Adapter,
36
37
  LensStore: () => Store,
@@ -40,6 +41,8 @@ __export(index_exports, {
40
41
  WatcherTypeEnum: () => WatcherTypeEnum,
41
42
  createEmittery: () => createEmittery,
42
43
  getLensStore: () => getStore,
44
+ lensContext: () => lensContext,
45
+ lensEmitter: () => lensEmitter,
43
46
  lensUtils: () => utils_exports
44
47
  });
45
48
  module.exports = __toCommonJS(index_exports);
@@ -91,6 +94,7 @@ var getUiConfig = () => {
91
94
  var WatcherTypeEnum = /* @__PURE__ */ ((WatcherTypeEnum2) => {
92
95
  WatcherTypeEnum2["REQUEST"] = "request";
93
96
  WatcherTypeEnum2["QUERY"] = "query";
97
+ WatcherTypeEnum2["CACHE"] = "cache";
94
98
  return WatcherTypeEnum2;
95
99
  })(WatcherTypeEnum || {});
96
100
 
@@ -101,14 +105,24 @@ var ApiController = class {
101
105
  await getStore().getAllRequests(this.extractPaginationParams(qs))
102
106
  );
103
107
  }
104
- static async getRequest({
105
- params
106
- }) {
108
+ static async getRequest({ params }) {
107
109
  const request = await getStore().find("request" /* REQUEST */, params.id);
108
110
  if (!request) {
109
111
  return this.notFoundResponse();
110
112
  }
111
- return this.resourceResponse(request);
113
+ const queries = await getStore().allByRequestId(
114
+ request.id,
115
+ "query" /* QUERY */
116
+ );
117
+ const cacheEntries = await getStore().allByRequestId(
118
+ request.id,
119
+ "cache" /* CACHE */
120
+ );
121
+ return this.resourceResponse({
122
+ request,
123
+ queries,
124
+ cacheEntries
125
+ });
112
126
  }
113
127
  static async getQueries({
114
128
  qs
@@ -127,6 +141,18 @@ var ApiController = class {
127
141
  }
128
142
  return this.resourceResponse(query);
129
143
  }
144
+ static async getCacheEntries({ qs }) {
145
+ return this.paginatedResponse(
146
+ await getStore().getAllCacheEntries(this.extractPaginationParams(qs))
147
+ );
148
+ }
149
+ static async getCacheEntry({ params }) {
150
+ const cacheEntry = await getStore().find("cache" /* CACHE */, params.id);
151
+ if (!cacheEntry) {
152
+ return this.notFoundResponse();
153
+ }
154
+ return this.resourceResponse(cacheEntry);
155
+ }
130
156
  static async truncate() {
131
157
  await getStore().truncate();
132
158
  return this.baseResponse({}, 200, "All entries cleared");
@@ -178,6 +204,16 @@ var path2 = __toESM(require("path"), 1);
178
204
 
179
205
  // src/abstracts/store.ts
180
206
  var Store = class {
207
+ stringifyData(data) {
208
+ if (typeof data === "string") {
209
+ return data;
210
+ }
211
+ try {
212
+ return JSON.stringify(data);
213
+ } catch (e) {
214
+ console.error(`Failed to stringify lens data: ${e}`);
215
+ }
216
+ }
181
217
  };
182
218
 
183
219
  // src/stores/better_sqlite.ts
@@ -200,11 +236,11 @@ var BetterSqliteStore = class extends Store {
200
236
  `INSERT INTO ${TABLE_NAME} (id, data, type, created_at, lens_entry_id, minimal_data) values($id, $data, $type, $created_at, $lens_entry_id, $minimalData)`
201
237
  ).run({
202
238
  id: entry.id ?? (0, import_crypto.randomUUID)(),
203
- data: JSON.stringify(entry.data),
239
+ data: this.stringifyData(entry.data),
204
240
  type: entry.type,
205
- created_at: entry.timestamp ?? (0, import_date.sqlDateTime)(),
241
+ created_at: entry.timestamp ?? (0, import_date.nowISO)(),
206
242
  lens_entry_id: entry.requestId || null,
207
- minimalData: JSON.stringify(entry.minimal_data ?? {})
243
+ minimalData: this.stringifyData(entry.minimal_data ?? {})
208
244
  });
209
245
  }
210
246
  async getAllQueries(pagination) {
@@ -213,6 +249,9 @@ var BetterSqliteStore = class extends Store {
213
249
  async getAllRequests(pagination) {
214
250
  return await this.paginate("request" /* REQUEST */, pagination, false);
215
251
  }
252
+ async getAllCacheEntries(pagination) {
253
+ return await this.paginate("cache" /* CACHE */, pagination);
254
+ }
216
255
  async allByRequestId(requestId, type) {
217
256
  const rows = this.connection.prepare(
218
257
  `${this.getSelectedColumns()} FROM ${TABLE_NAME} WHERE type = $type AND lens_entry_id = $requestId ORDER BY created_at DESC`
@@ -265,8 +304,13 @@ var BetterSqliteStore = class extends Store {
265
304
  CREATE INDEX IF NOT EXISTS lens_entries_id_type_index
266
305
  ON ${TABLE_NAME} (id, type);
267
306
  `;
307
+ const lensEntryIdIndex = `
308
+ CREATE INDEX IF NOT EXISTS lens_entry_id_index
309
+ ON ${TABLE_NAME} (lens_entry_id);
310
+ `;
268
311
  this.connection.exec(createTable);
269
312
  this.connection.exec(createIndex);
313
+ this.connection.exec(lensEntryIdIndex);
270
314
  }
271
315
  mapRow(row, includeFullData = true) {
272
316
  let data = includeFullData ? JSON.parse(row.data) : {};
@@ -475,6 +519,7 @@ var Lens = class {
475
519
  api: {
476
520
  requests: `/${config.basePath}/api/requests`,
477
521
  queries: `/${config.basePath}/api/queries`,
522
+ cache: `/${config.basePath}/api/cache`,
478
523
  truncate: `/${config.basePath}/api/truncate`
479
524
  }
480
525
  };
@@ -507,6 +552,16 @@ var Lens = class {
507
552
  path: `${basePath}/api/queries/:id`,
508
553
  handler: async (data) => await ApiController.getQuery(data)
509
554
  },
555
+ {
556
+ method: "GET",
557
+ path: `${basePath}/api/cache`,
558
+ handler: async (data) => await ApiController.getCacheEntries(data)
559
+ },
560
+ {
561
+ method: "GET",
562
+ path: `${basePath}/api/cache/:id`,
563
+ handler: async (data) => await ApiController.getCacheEntry(data)
564
+ },
510
565
  {
511
566
  method: "DELETE",
512
567
  path: `${basePath}/api/truncate`,
@@ -565,6 +620,48 @@ var RequestWatcher = class extends Watcher {
565
620
  }
566
621
  };
567
622
 
623
+ // src/watchers/cache_watcher.ts
624
+ var CacheWatcher = class extends Watcher {
625
+ name = "cache" /* CACHE */;
626
+ async log(data) {
627
+ const payload = {
628
+ action: data.action,
629
+ data: this.normalizePayload(data),
630
+ requestId: data.requestId ?? "",
631
+ createdAt: data.createdAt
632
+ };
633
+ await getStore().save({
634
+ requestId: data.requestId ?? "",
635
+ type: this.name,
636
+ data: payload,
637
+ minimal_data: {
638
+ action: data.action,
639
+ key: payload.data.key,
640
+ createdAt: payload.createdAt
641
+ }
642
+ });
643
+ }
644
+ normalizePayload(data) {
645
+ let normalizedData = "data" in data ? data.data : {
646
+ key: "",
647
+ value: ""
648
+ };
649
+ if (!normalizedData || typeof normalizedData === "object" && Object.keys(normalizedData).length === 0) {
650
+ normalizedData = {
651
+ key: "",
652
+ value: ""
653
+ };
654
+ }
655
+ if (!normalizedData["key"]) {
656
+ normalizedData.key = "";
657
+ }
658
+ if (!normalizedData["value"]) {
659
+ normalizedData["value"] = "";
660
+ }
661
+ return normalizedData;
662
+ }
663
+ };
664
+
568
665
  // src/abstracts/adapter.ts
569
666
  var Adapter = class {
570
667
  watchers = [];
@@ -595,9 +692,15 @@ var import_emittery = __toESM(require("emittery"), 1);
595
692
  var createEmittery = () => {
596
693
  return new import_emittery.default();
597
694
  };
695
+ var lensEmitter = createEmittery();
696
+
697
+ // src/utils/async_context.ts
698
+ var import_async_hooks = require("async_hooks");
699
+ var lensContext = new import_async_hooks.AsyncLocalStorage();
598
700
  // Annotate the CommonJS export names for ESM import in node:
599
701
  0 && (module.exports = {
600
702
  BetterSqliteStore,
703
+ CacheWatcher,
601
704
  Lens,
602
705
  LensAdapter,
603
706
  LensStore,
@@ -607,5 +710,7 @@ var createEmittery = () => {
607
710
  WatcherTypeEnum,
608
711
  createEmittery,
609
712
  getLensStore,
713
+ lensContext,
714
+ lensEmitter,
610
715
  lensUtils
611
716
  });
package/dist/index.d.cts CHANGED
@@ -2,13 +2,16 @@ export { default as Lens } from './core/lens.cjs';
2
2
  export { default as BetterSqliteStore } from './stores/better_sqlite.cjs';
3
3
  export { default as QueryWatcher } from './watchers/query_watcher.cjs';
4
4
  export { default as RequestWatcher } from './watchers/request_watcher.cjs';
5
- export { ApiResponse, Entry, HttpMethod, LensConfig, LensEntry, PaginationParams, Paginator, QueryEntry, QueryType, RequestEntry, RouteDefinition, RouteDefinitionHandler, RouteHttpMethod, SqlQueryType, UserEntry, WatcherTypeEnum } from './types/index.cjs';
5
+ export { default as CacheWatcher } from './watchers/cache_watcher.cjs';
6
+ export { ApiResponse, CacheAction, CacheEntry, Entry, HttpMethod, LensConfig, LensEntry, PaginationParams, Paginator, QueryEntry, QueryType, RequestEntry, RouteDefinition, RouteDefinitionHandler, RouteHttpMethod, SqlQueryType, UserEntry, WatcherTypeEnum } from './types/index.cjs';
6
7
  export { default as LensAdapter } from './abstracts/adapter.cjs';
7
8
  export { default as LensStore } from './abstracts/store.cjs';
8
9
  export { default as LensWatcher } from './core/watcher.cjs';
9
10
  export { getStore as getLensStore } from './context/context.cjs';
10
11
  export { i as lensUtils } from './index-DiLfwsvc.cjs';
11
- export { createEmittery } from './utils/event_emitter.cjs';
12
+ export { createEmittery, lensEmitter } from './utils/event_emitter.cjs';
13
+ export { lensContext } from './utils/async_context.cjs';
12
14
  import 'libsql';
13
15
  import 'sql-formatter';
14
16
  import 'emittery';
17
+ import 'async_hooks';