@adjedaini/clockwork-node 0.0.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 (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +225 -0
  3. package/dist/globals.d.ts +27 -0
  4. package/dist/index.d.ts +61 -0
  5. package/dist/index.js +695 -0
  6. package/dist/public/assets/index-B2HEyS_P.css +1 -0
  7. package/dist/public/assets/index-B83PrqXa.css +1 -0
  8. package/dist/public/assets/index-CdsiP1dN.css +1 -0
  9. package/dist/public/assets/index-Df9idoqY.js +198 -0
  10. package/dist/public/assets/index-KmGT-iQM.js +198 -0
  11. package/dist/public/assets/index-znhjCgo1.js +198 -0
  12. package/dist/public/index.html +13 -0
  13. package/node_modules/@adjedaini/clockwork-core/dist/index.d.ts +53 -0
  14. package/node_modules/@adjedaini/clockwork-core/dist/index.js +192 -0
  15. package/node_modules/@adjedaini/clockwork-core/package.json +17 -0
  16. package/node_modules/@adjedaini/clockwork-core/src/index.ts +194 -0
  17. package/node_modules/@adjedaini/clockwork-core/src/ring-buffer.ts +47 -0
  18. package/node_modules/@adjedaini/clockwork-core/tsconfig.build.json +6 -0
  19. package/node_modules/@adjedaini/clockwork-core/tsconfig.json +10 -0
  20. package/node_modules/@adjedaini/clockwork-core/tsup.config.ts +13 -0
  21. package/node_modules/@adjedaini/clockwork-db-interceptor/dist/index.d.ts +33 -0
  22. package/node_modules/@adjedaini/clockwork-db-interceptor/dist/index.js +163 -0
  23. package/node_modules/@adjedaini/clockwork-db-interceptor/package.json +18 -0
  24. package/node_modules/@adjedaini/clockwork-db-interceptor/src/index.ts +28 -0
  25. package/node_modules/@adjedaini/clockwork-db-interceptor/src/mysql2.ts +84 -0
  26. package/node_modules/@adjedaini/clockwork-db-interceptor/src/pg.ts +56 -0
  27. package/node_modules/@adjedaini/clockwork-db-interceptor/tsconfig.build.json +6 -0
  28. package/node_modules/@adjedaini/clockwork-db-interceptor/tsconfig.json +10 -0
  29. package/node_modules/@adjedaini/clockwork-db-interceptor/tsup.config.ts +13 -0
  30. package/node_modules/@adjedaini/clockwork-log-interceptor/dist/index.d.ts +25 -0
  31. package/node_modules/@adjedaini/clockwork-log-interceptor/dist/index.js +153 -0
  32. package/node_modules/@adjedaini/clockwork-log-interceptor/package.json +16 -0
  33. package/node_modules/@adjedaini/clockwork-log-interceptor/src/index.ts +14 -0
  34. package/node_modules/@adjedaini/clockwork-log-interceptor/src/pino.ts +78 -0
  35. package/node_modules/@adjedaini/clockwork-log-interceptor/src/winston.ts +66 -0
  36. package/node_modules/@adjedaini/clockwork-log-interceptor/tsconfig.build.json +4 -0
  37. package/node_modules/@adjedaini/clockwork-log-interceptor/tsconfig.json +10 -0
  38. package/node_modules/@adjedaini/clockwork-log-interceptor/tsup.config.ts +13 -0
  39. package/node_modules/@adjedaini/clockwork-plugins/dist/index.d.ts +45 -0
  40. package/node_modules/@adjedaini/clockwork-plugins/dist/index.js +172 -0
  41. package/node_modules/@adjedaini/clockwork-plugins/package.json +19 -0
  42. package/node_modules/@adjedaini/clockwork-plugins/src/console.ts +70 -0
  43. package/node_modules/@adjedaini/clockwork-plugins/src/context.ts +30 -0
  44. package/node_modules/@adjedaini/clockwork-plugins/src/index.ts +50 -0
  45. package/node_modules/@adjedaini/clockwork-plugins/src/process-errors.ts +33 -0
  46. package/node_modules/@adjedaini/clockwork-plugins/tsconfig.build.json +1 -0
  47. package/node_modules/@adjedaini/clockwork-plugins/tsconfig.json +16 -0
  48. package/node_modules/@adjedaini/clockwork-plugins/tsup.config.ts +13 -0
  49. package/node_modules/@adjedaini/clockwork-shared/dist/index.d.ts +97 -0
  50. package/node_modules/@adjedaini/clockwork-shared/dist/index.js +18 -0
  51. package/node_modules/@adjedaini/clockwork-shared/package.json +14 -0
  52. package/node_modules/@adjedaini/clockwork-shared/src/index.ts +96 -0
  53. package/node_modules/@adjedaini/clockwork-shared/tsconfig.build.json +6 -0
  54. package/node_modules/@adjedaini/clockwork-shared/tsconfig.json +9 -0
  55. package/node_modules/@adjedaini/clockwork-shared/tsup.config.ts +13 -0
  56. package/node_modules/@adjedaini/clockwork-transport-http/dist/index.d.ts +75 -0
  57. package/node_modules/@adjedaini/clockwork-transport-http/dist/index.js +306 -0
  58. package/node_modules/@adjedaini/clockwork-transport-http/package.json +18 -0
  59. package/node_modules/@adjedaini/clockwork-transport-http/src/index.ts +277 -0
  60. package/node_modules/@adjedaini/clockwork-transport-http/src/sanitize.ts +92 -0
  61. package/node_modules/@adjedaini/clockwork-transport-http/src/types.ts +37 -0
  62. package/node_modules/@adjedaini/clockwork-transport-http/tsconfig.build.json +6 -0
  63. package/node_modules/@adjedaini/clockwork-transport-http/tsconfig.json +10 -0
  64. package/node_modules/@adjedaini/clockwork-transport-http/tsup.config.ts +13 -0
  65. package/package.json +69 -0
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Clockwork — Node.js Debugging &amp; Monitoring</title>
7
+ <script type="module" crossorigin src="/__clockwork/app/assets/index-KmGT-iQM.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/__clockwork/app/assets/index-B2HEyS_P.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
@@ -0,0 +1,53 @@
1
+ import { CoreConfig, RequestSnapshot, LogData, QueryData, EventData, Snapshot } from '@adjedaini/clockwork-shared';
2
+ export { CoreConfig, IRequestStorage, RequestMetadata, RequestSnapshot, Snapshot } from '@adjedaini/clockwork-shared';
3
+
4
+ /**
5
+ * @adjedaini/clockwork-core
6
+ * Framework-agnostic monitoring engine. No Express, Fastify, or React.
7
+ */
8
+
9
+ /** Context passed to every plugin. getRequestId() returns current request id when inside middleware. */
10
+ interface IPluginContext {
11
+ core: MonitorCore;
12
+ getRequestId(): string | undefined;
13
+ }
14
+ /** Generic plugin: install patches and return a restore function. */
15
+ interface ClockworkPlugin {
16
+ name: string;
17
+ install(ctx: IPluginContext): () => void;
18
+ }
19
+ declare class MonitorCore {
20
+ private buffer;
21
+ private current;
22
+ private startedAt;
23
+ private config;
24
+ constructor(config?: CoreConfig);
25
+ /** Start the monitor (call once at bootstrap). */
26
+ start(): void;
27
+ /** Begin capturing a request. Returns request id. */
28
+ captureRequest(initial: Partial<RequestSnapshot>): string;
29
+ /** Attach a log entry to a request. */
30
+ captureLog(requestId: string, level: LogData['level'], message: string, context?: Record<string, unknown>): void;
31
+ /** Attach a native (e.g. console) log entry. */
32
+ captureNativeLog(requestId: string, level: LogData['level'], message: string, context?: Record<string, unknown>, timeOffset?: number): void;
33
+ /** Capture an error. If requestId is set, also attach to that request's log. */
34
+ captureError(error: unknown, requestId?: string): void;
35
+ /** Add a query to a request. */
36
+ addQuery(requestId: string, data: QueryData): void;
37
+ /** Add a timeline event to a request. */
38
+ addEvent(requestId: string, data: EventData): void;
39
+ /** Update request data (e.g. response status, duration, body). */
40
+ finalizeRequest(requestId: string, update: {
41
+ responseStatus: number;
42
+ responseDuration: number;
43
+ responseData?: unknown;
44
+ }): void;
45
+ /** Get full request by id. */
46
+ getRequest(id: string): RequestSnapshot | undefined;
47
+ /** Get snapshot for UI: list of requests + optional metrics. */
48
+ getSnapshot(limit?: number): Snapshot;
49
+ /** For plugin/collector registration later. */
50
+ registerCollector(_name: string, _fn: () => unknown): void;
51
+ }
52
+
53
+ export { type ClockworkPlugin, type IPluginContext, MonitorCore };
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ MonitorCore: () => MonitorCore
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/ring-buffer.ts
28
+ var RequestRingBuffer = class {
29
+ constructor(capacity = 100) {
30
+ this.buffer = /* @__PURE__ */ new Map();
31
+ this.order = [];
32
+ this.capacity = Math.max(1, capacity);
33
+ }
34
+ push(id, request) {
35
+ if (this.buffer.has(id)) {
36
+ this.buffer.set(id, request);
37
+ return;
38
+ }
39
+ while (this.order.length >= this.capacity && this.order.length > 0) {
40
+ const oldest = this.order.shift();
41
+ this.buffer.delete(oldest);
42
+ }
43
+ this.order.push(id);
44
+ this.buffer.set(id, request);
45
+ }
46
+ get(id) {
47
+ return this.buffer.get(id);
48
+ }
49
+ getAll(limit = 100) {
50
+ const ids = this.order.slice(-limit).reverse();
51
+ return ids.map((id) => this.buffer.get(id)).filter(Boolean);
52
+ }
53
+ getLatest() {
54
+ if (this.order.length === 0) return void 0;
55
+ return this.buffer.get(this.order[this.order.length - 1]);
56
+ }
57
+ count() {
58
+ return this.buffer.size;
59
+ }
60
+ };
61
+
62
+ // src/index.ts
63
+ var DEFAULT_MAX_REQUESTS = 100;
64
+ var MonitorCore = class {
65
+ constructor(config = {}) {
66
+ this.current = /* @__PURE__ */ new Map();
67
+ this.startedAt = 0;
68
+ this.config = {
69
+ maxRequests: config.maxRequests ?? DEFAULT_MAX_REQUESTS
70
+ };
71
+ this.buffer = config.storage ?? new RequestRingBuffer(this.config.maxRequests);
72
+ }
73
+ /** Start the monitor (call once at bootstrap). */
74
+ start() {
75
+ this.startedAt = Date.now();
76
+ }
77
+ /** Begin capturing a request. Returns request id. */
78
+ captureRequest(initial) {
79
+ const id = initial.id || `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 9)}`;
80
+ const startTime = Date.now();
81
+ const heapAtStart = process.memoryUsage().heapUsed;
82
+ const snapshot = {
83
+ id,
84
+ type: "http",
85
+ method: initial.method ?? "",
86
+ uri: initial.uri ?? "",
87
+ headers: initial.headers ?? {},
88
+ getData: initial.getData ?? {},
89
+ postData: initial.postData,
90
+ cookies: initial.cookies,
91
+ responseStatus: 0,
92
+ responseTime: startTime,
93
+ responseDuration: 0,
94
+ memoryUsage: heapAtStart,
95
+ time: startTime / 1e3,
96
+ log: [],
97
+ databaseQueries: [],
98
+ timelineData: [],
99
+ controller: initial.controller
100
+ };
101
+ this.current.set(id, snapshot);
102
+ return id;
103
+ }
104
+ /** Attach a log entry to a request. */
105
+ captureLog(requestId, level, message, context) {
106
+ const req = this.current.get(requestId);
107
+ if (!req) return;
108
+ const startTime = req.time * 1e3;
109
+ req.log.push({
110
+ level,
111
+ message,
112
+ context,
113
+ time: (Date.now() - startTime) / 1e3,
114
+ source: "clockwork"
115
+ });
116
+ }
117
+ /** Attach a native (e.g. console) log entry. */
118
+ captureNativeLog(requestId, level, message, context, timeOffset) {
119
+ const req = this.current.get(requestId);
120
+ if (!req) return;
121
+ const startTime = req.time * 1e3;
122
+ req.log.push({
123
+ level,
124
+ message,
125
+ context,
126
+ time: timeOffset ?? (Date.now() - startTime) / 1e3,
127
+ source: "native"
128
+ });
129
+ }
130
+ /** Capture an error. If requestId is set, also attach to that request's log. */
131
+ captureError(error, requestId) {
132
+ const message = error instanceof Error ? error.message : String(error);
133
+ const context = error instanceof Error ? { name: error.name, stack: error.stack } : void 0;
134
+ if (requestId) {
135
+ this.captureLog(requestId, "error", message, context);
136
+ }
137
+ }
138
+ /** Add a query to a request. */
139
+ addQuery(requestId, data) {
140
+ const req = this.current.get(requestId);
141
+ if (!req) return;
142
+ req.databaseQueries.push(data);
143
+ }
144
+ /** Add a timeline event to a request. */
145
+ addEvent(requestId, data) {
146
+ const req = this.current.get(requestId);
147
+ if (!req) return;
148
+ req.timelineData.push(data);
149
+ }
150
+ /** Update request data (e.g. response status, duration, body). */
151
+ finalizeRequest(requestId, update) {
152
+ const req = this.current.get(requestId);
153
+ if (!req) return;
154
+ req.responseStatus = update.responseStatus;
155
+ req.responseDuration = update.responseDuration;
156
+ if (update.responseData !== void 0) req.responseData = update.responseData;
157
+ req.memoryUsage = process.memoryUsage().heapUsed - req.memoryUsage;
158
+ this.buffer.push(requestId, req);
159
+ this.current.delete(requestId);
160
+ }
161
+ /** Get full request by id. */
162
+ getRequest(id) {
163
+ return this.current.get(id) ?? this.buffer.get(id);
164
+ }
165
+ /** Get snapshot for UI: list of requests + optional metrics. */
166
+ getSnapshot(limit = 50) {
167
+ const all = this.buffer.getAll(limit);
168
+ const requests = all.map((r) => ({
169
+ id: r.id,
170
+ method: r.method,
171
+ uri: r.uri,
172
+ controller: r.controller,
173
+ responseStatus: r.responseStatus,
174
+ responseDuration: r.responseDuration,
175
+ time: r.time
176
+ }));
177
+ return {
178
+ requests,
179
+ metrics: {
180
+ timestamp: Date.now() / 1e3,
181
+ spans: []
182
+ }
183
+ };
184
+ }
185
+ /** For plugin/collector registration later. */
186
+ registerCollector(_name, _fn) {
187
+ }
188
+ };
189
+ // Annotate the CommonJS export names for ESM import in node:
190
+ 0 && (module.exports = {
191
+ MonitorCore
192
+ });
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@adjedaini/clockwork-core",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsup src/index.ts --format cjs --dts"
9
+ },
10
+ "dependencies": {
11
+ "@adjedaini/clockwork-shared": "*"
12
+ },
13
+ "devDependencies": {
14
+ "tsup": "^8.0.0",
15
+ "typescript": "^5.5.0"
16
+ }
17
+ }
@@ -0,0 +1,194 @@
1
+ /**
2
+ * @adjedaini/clockwork-core
3
+ * Framework-agnostic monitoring engine. No Express, Fastify, or React.
4
+ */
5
+
6
+ import type {
7
+ RequestSnapshot,
8
+ RequestMetadata,
9
+ LogData,
10
+ QueryData,
11
+ EventData,
12
+ Snapshot,
13
+ CoreConfig,
14
+ IRequestStorage,
15
+ } from '@adjedaini/clockwork-shared';
16
+ import { RequestRingBuffer } from './ring-buffer';
17
+
18
+ export type { RequestSnapshot, RequestMetadata, Snapshot, CoreConfig, IRequestStorage } from '@adjedaini/clockwork-shared';
19
+
20
+ /** Context passed to every plugin. getRequestId() returns current request id when inside middleware. */
21
+ export interface IPluginContext {
22
+ core: MonitorCore;
23
+ getRequestId(): string | undefined;
24
+ }
25
+
26
+ /** Generic plugin: install patches and return a restore function. */
27
+ export interface ClockworkPlugin {
28
+ name: string;
29
+ install(ctx: IPluginContext): () => void;
30
+ }
31
+
32
+ const DEFAULT_MAX_REQUESTS = 100;
33
+
34
+ export class MonitorCore {
35
+ private buffer: IRequestStorage;
36
+ private current: Map<string, RequestSnapshot> = new Map();
37
+ private startedAt: number = 0;
38
+ private config: Required<Pick<CoreConfig, 'maxRequests'>>;
39
+
40
+ constructor(config: CoreConfig = {}) {
41
+ this.config = {
42
+ maxRequests: config.maxRequests ?? DEFAULT_MAX_REQUESTS,
43
+ };
44
+ this.buffer = config.storage ?? new RequestRingBuffer(this.config.maxRequests);
45
+ }
46
+
47
+ /** Start the monitor (call once at bootstrap). */
48
+ start(): void {
49
+ this.startedAt = Date.now();
50
+ }
51
+
52
+ /** Begin capturing a request. Returns request id. */
53
+ captureRequest(initial: Partial<RequestSnapshot>): string {
54
+ const id =
55
+ (initial.id as string) ||
56
+ `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 9)}`;
57
+ const startTime = Date.now();
58
+ const heapAtStart = process.memoryUsage().heapUsed;
59
+ const snapshot: RequestSnapshot = {
60
+ id,
61
+ type: 'http',
62
+ method: initial.method ?? '',
63
+ uri: initial.uri ?? '',
64
+ headers: initial.headers ?? {},
65
+ getData: initial.getData ?? {},
66
+ postData: initial.postData,
67
+ cookies: initial.cookies,
68
+ responseStatus: 0,
69
+ responseTime: startTime,
70
+ responseDuration: 0,
71
+ memoryUsage: heapAtStart,
72
+ time: startTime / 1000,
73
+ log: [],
74
+ databaseQueries: [],
75
+ timelineData: [],
76
+ controller: initial.controller,
77
+ };
78
+ this.current.set(id, snapshot);
79
+ return id;
80
+ }
81
+
82
+ /** Attach a log entry to a request. */
83
+ captureLog(
84
+ requestId: string,
85
+ level: LogData['level'],
86
+ message: string,
87
+ context?: Record<string, unknown>
88
+ ): void {
89
+ const req = this.current.get(requestId);
90
+ if (!req) return;
91
+ const startTime = req.time * 1000;
92
+ req.log.push({
93
+ level,
94
+ message,
95
+ context,
96
+ time: (Date.now() - startTime) / 1000,
97
+ source: 'clockwork',
98
+ });
99
+ }
100
+
101
+ /** Attach a native (e.g. console) log entry. */
102
+ captureNativeLog(
103
+ requestId: string,
104
+ level: LogData['level'],
105
+ message: string,
106
+ context?: Record<string, unknown>,
107
+ timeOffset?: number
108
+ ): void {
109
+ const req = this.current.get(requestId);
110
+ if (!req) return;
111
+ const startTime = req.time * 1000;
112
+ req.log.push({
113
+ level,
114
+ message,
115
+ context,
116
+ time: timeOffset ?? (Date.now() - startTime) / 1000,
117
+ source: 'native',
118
+ });
119
+ }
120
+
121
+ /** Capture an error. If requestId is set, also attach to that request's log. */
122
+ captureError(error: unknown, requestId?: string): void {
123
+ const message = error instanceof Error ? error.message : String(error);
124
+ const context = error instanceof Error ? { name: error.name, stack: error.stack } : undefined;
125
+ if (requestId) {
126
+ this.captureLog(requestId, 'error', message, context as Record<string, unknown>);
127
+ }
128
+ // Global errors could be stored in a ring buffer here for getSnapshot(); optional for later.
129
+ }
130
+
131
+ /** Add a query to a request. */
132
+ addQuery(requestId: string, data: QueryData): void {
133
+ const req = this.current.get(requestId);
134
+ if (!req) return;
135
+ req.databaseQueries.push(data);
136
+ }
137
+
138
+ /** Add a timeline event to a request. */
139
+ addEvent(requestId: string, data: EventData): void {
140
+ const req = this.current.get(requestId);
141
+ if (!req) return;
142
+ req.timelineData.push(data);
143
+ }
144
+
145
+ /** Update request data (e.g. response status, duration, body). */
146
+ finalizeRequest(
147
+ requestId: string,
148
+ update: {
149
+ responseStatus: number;
150
+ responseDuration: number;
151
+ responseData?: unknown;
152
+ }
153
+ ): void {
154
+ const req = this.current.get(requestId);
155
+ if (!req) return;
156
+ req.responseStatus = update.responseStatus;
157
+ req.responseDuration = update.responseDuration;
158
+ if (update.responseData !== undefined) req.responseData = update.responseData;
159
+ req.memoryUsage = process.memoryUsage().heapUsed - req.memoryUsage;
160
+ this.buffer.push(requestId, req);
161
+ this.current.delete(requestId);
162
+ }
163
+
164
+ /** Get full request by id. */
165
+ getRequest(id: string): RequestSnapshot | undefined {
166
+ return this.current.get(id) ?? this.buffer.get(id);
167
+ }
168
+
169
+ /** Get snapshot for UI: list of requests + optional metrics. */
170
+ getSnapshot(limit: number = 50): Snapshot {
171
+ const all = this.buffer.getAll(limit);
172
+ const requests: RequestMetadata[] = all.map((r) => ({
173
+ id: r.id,
174
+ method: r.method,
175
+ uri: r.uri,
176
+ controller: r.controller,
177
+ responseStatus: r.responseStatus,
178
+ responseDuration: r.responseDuration,
179
+ time: r.time,
180
+ }));
181
+ return {
182
+ requests,
183
+ metrics: {
184
+ timestamp: Date.now() / 1000,
185
+ spans: [],
186
+ },
187
+ };
188
+ }
189
+
190
+ /** For plugin/collector registration later. */
191
+ registerCollector(_name: string, _fn: () => unknown): void {
192
+ // no-op for now; extend for plugins
193
+ }
194
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * In-memory ring buffer for request storage. Evicts oldest when at capacity.
3
+ * Implements IRequestStorage for pluggable backends.
4
+ */
5
+
6
+ import type { RequestSnapshot, IRequestStorage } from '@adjedaini/clockwork-shared';
7
+
8
+ export class RequestRingBuffer implements IRequestStorage {
9
+ private buffer: Map<string, RequestSnapshot> = new Map();
10
+ private order: string[] = [];
11
+ private readonly capacity: number;
12
+
13
+ constructor(capacity: number = 100) {
14
+ this.capacity = Math.max(1, capacity);
15
+ }
16
+
17
+ push(id: string, request: RequestSnapshot): void {
18
+ if (this.buffer.has(id)) {
19
+ this.buffer.set(id, request);
20
+ return;
21
+ }
22
+ while (this.order.length >= this.capacity && this.order.length > 0) {
23
+ const oldest = this.order.shift()!;
24
+ this.buffer.delete(oldest);
25
+ }
26
+ this.order.push(id);
27
+ this.buffer.set(id, request);
28
+ }
29
+
30
+ get(id: string): RequestSnapshot | undefined {
31
+ return this.buffer.get(id);
32
+ }
33
+
34
+ getAll(limit: number = 100): RequestSnapshot[] {
35
+ const ids = this.order.slice(-limit).reverse();
36
+ return ids.map((id) => this.buffer.get(id)!).filter(Boolean);
37
+ }
38
+
39
+ getLatest(): RequestSnapshot | undefined {
40
+ if (this.order.length === 0) return undefined;
41
+ return this.buffer.get(this.order[this.order.length - 1]);
42
+ }
43
+
44
+ count(): number {
45
+ return this.buffer.size;
46
+ }
47
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "composite": false
5
+ }
6
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src",
6
+ "composite": true
7
+ },
8
+ "include": ["src/**/*"],
9
+ "references": [{ "path": "../shared" }]
10
+ }
@@ -0,0 +1,13 @@
1
+ import path from 'path';
2
+ import { fileURLToPath } from 'url';
3
+ import { defineConfig } from 'tsup';
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+
7
+ export default defineConfig({
8
+ entry: ['src/index.ts'],
9
+ format: ['cjs'],
10
+ dts: true,
11
+ outDir: 'dist',
12
+ tsconfig: path.join(__dirname, 'tsconfig.build.json'),
13
+ });
@@ -0,0 +1,33 @@
1
+ import { MonitorCore, ClockworkPlugin } from '@adjedaini/clockwork-core';
2
+ export { ClockworkPlugin, IPluginContext } from '@adjedaini/clockwork-core';
3
+
4
+ /**
5
+ * Patch pg Client.query so queries are attached to the current request (when in context).
6
+ * Only applied if the 'pg' module is installed.
7
+ */
8
+
9
+ type GetRequestId$2 = () => string | undefined;
10
+ declare function patchPg(core: MonitorCore, getRequestId: GetRequestId$2): () => void;
11
+
12
+ /**
13
+ * Patch mysql2 so Connection.query/execute are tracked. Only applied if 'mysql2' is installed.
14
+ * Wraps createConnection to patch the returned connection.
15
+ */
16
+
17
+ type GetRequestId$1 = () => string | undefined;
18
+ declare function patchMysql2(core: MonitorCore, getRequestId: GetRequestId$1): () => void;
19
+
20
+ /**
21
+ * @adjedaini/clockwork-db-interceptor
22
+ * Optional DB query instrumentation as pluggable plugins (pg, mysql2).
23
+ * Implements generic ClockworkPlugin from core (IPluginContext).
24
+ */
25
+
26
+ type GetRequestId = () => string | undefined;
27
+ /** DB plugins conform to generic ClockworkPlugin. */
28
+ declare const pgPlugin: ClockworkPlugin;
29
+ declare const mysql2Plugin: ClockworkPlugin;
30
+ /** Default set of DB plugins (pg + mysql2). */
31
+ declare const defaultDbPlugins: ClockworkPlugin[];
32
+
33
+ export { type GetRequestId, defaultDbPlugins, mysql2Plugin, patchMysql2, patchPg, pgPlugin };