@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
package/dist/index.js ADDED
@@ -0,0 +1,695 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // packages/core/dist/index.js
28
+ var require_dist = __commonJS({
29
+ "packages/core/dist/index.js"(exports, module) {
30
+ "use strict";
31
+ var __defProp2 = Object.defineProperty;
32
+ var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
33
+ var __getOwnPropNames2 = Object.getOwnPropertyNames;
34
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
35
+ var __export = (target, all) => {
36
+ for (var name in all)
37
+ __defProp2(target, name, { get: all[name], enumerable: true });
38
+ };
39
+ var __copyProps2 = (to, from, except, desc) => {
40
+ if (from && typeof from === "object" || typeof from === "function") {
41
+ for (let key of __getOwnPropNames2(from))
42
+ if (!__hasOwnProp2.call(to, key) && key !== except)
43
+ __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
44
+ }
45
+ return to;
46
+ };
47
+ var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
48
+ var index_exports = {};
49
+ __export(index_exports, {
50
+ MonitorCore: () => MonitorCore2
51
+ });
52
+ module.exports = __toCommonJS(index_exports);
53
+ var RequestRingBuffer = class {
54
+ constructor(capacity = 100) {
55
+ this.buffer = /* @__PURE__ */ new Map();
56
+ this.order = [];
57
+ this.capacity = Math.max(1, capacity);
58
+ }
59
+ push(id, request) {
60
+ if (this.buffer.has(id)) {
61
+ this.buffer.set(id, request);
62
+ return;
63
+ }
64
+ while (this.order.length >= this.capacity && this.order.length > 0) {
65
+ const oldest = this.order.shift();
66
+ this.buffer.delete(oldest);
67
+ }
68
+ this.order.push(id);
69
+ this.buffer.set(id, request);
70
+ }
71
+ get(id) {
72
+ return this.buffer.get(id);
73
+ }
74
+ getAll(limit = 100) {
75
+ const ids = this.order.slice(-limit).reverse();
76
+ return ids.map((id) => this.buffer.get(id)).filter(Boolean);
77
+ }
78
+ getLatest() {
79
+ if (this.order.length === 0) return void 0;
80
+ return this.buffer.get(this.order[this.order.length - 1]);
81
+ }
82
+ count() {
83
+ return this.buffer.size;
84
+ }
85
+ };
86
+ var DEFAULT_MAX_REQUESTS = 100;
87
+ var MonitorCore2 = class {
88
+ constructor(config = {}) {
89
+ this.current = /* @__PURE__ */ new Map();
90
+ this.startedAt = 0;
91
+ this.config = {
92
+ maxRequests: config.maxRequests ?? DEFAULT_MAX_REQUESTS
93
+ };
94
+ this.buffer = config.storage ?? new RequestRingBuffer(this.config.maxRequests);
95
+ }
96
+ /** Start the monitor (call once at bootstrap). */
97
+ start() {
98
+ this.startedAt = Date.now();
99
+ }
100
+ /** Begin capturing a request. Returns request id. */
101
+ captureRequest(initial) {
102
+ const id = initial.id || `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 9)}`;
103
+ const startTime = Date.now();
104
+ const heapAtStart = process.memoryUsage().heapUsed;
105
+ const snapshot = {
106
+ id,
107
+ type: "http",
108
+ method: initial.method ?? "",
109
+ uri: initial.uri ?? "",
110
+ headers: initial.headers ?? {},
111
+ getData: initial.getData ?? {},
112
+ postData: initial.postData,
113
+ cookies: initial.cookies,
114
+ responseStatus: 0,
115
+ responseTime: startTime,
116
+ responseDuration: 0,
117
+ memoryUsage: heapAtStart,
118
+ time: startTime / 1e3,
119
+ log: [],
120
+ databaseQueries: [],
121
+ timelineData: [],
122
+ controller: initial.controller
123
+ };
124
+ this.current.set(id, snapshot);
125
+ return id;
126
+ }
127
+ /** Attach a log entry to a request. */
128
+ captureLog(requestId, level, message, context) {
129
+ const req = this.current.get(requestId);
130
+ if (!req) return;
131
+ const startTime = req.time * 1e3;
132
+ req.log.push({
133
+ level,
134
+ message,
135
+ context,
136
+ time: (Date.now() - startTime) / 1e3,
137
+ source: "clockwork"
138
+ });
139
+ }
140
+ /** Attach a native (e.g. console) log entry. */
141
+ captureNativeLog(requestId, level, message, context, timeOffset) {
142
+ const req = this.current.get(requestId);
143
+ if (!req) return;
144
+ const startTime = req.time * 1e3;
145
+ req.log.push({
146
+ level,
147
+ message,
148
+ context,
149
+ time: timeOffset ?? (Date.now() - startTime) / 1e3,
150
+ source: "native"
151
+ });
152
+ }
153
+ /** Capture an error. If requestId is set, also attach to that request's log. */
154
+ captureError(error, requestId) {
155
+ const message = error instanceof Error ? error.message : String(error);
156
+ const context = error instanceof Error ? { name: error.name, stack: error.stack } : void 0;
157
+ if (requestId) {
158
+ this.captureLog(requestId, "error", message, context);
159
+ }
160
+ }
161
+ /** Add a query to a request. */
162
+ addQuery(requestId, data) {
163
+ const req = this.current.get(requestId);
164
+ if (!req) return;
165
+ req.databaseQueries.push(data);
166
+ }
167
+ /** Add a timeline event to a request. */
168
+ addEvent(requestId, data) {
169
+ const req = this.current.get(requestId);
170
+ if (!req) return;
171
+ req.timelineData.push(data);
172
+ }
173
+ /** Update request data (e.g. response status, duration, body). */
174
+ finalizeRequest(requestId, update) {
175
+ const req = this.current.get(requestId);
176
+ if (!req) return;
177
+ req.responseStatus = update.responseStatus;
178
+ req.responseDuration = update.responseDuration;
179
+ if (update.responseData !== void 0) req.responseData = update.responseData;
180
+ req.memoryUsage = process.memoryUsage().heapUsed - req.memoryUsage;
181
+ this.buffer.push(requestId, req);
182
+ this.current.delete(requestId);
183
+ }
184
+ /** Get full request by id. */
185
+ getRequest(id) {
186
+ return this.current.get(id) ?? this.buffer.get(id);
187
+ }
188
+ /** Get snapshot for UI: list of requests + optional metrics. */
189
+ getSnapshot(limit = 50) {
190
+ const all = this.buffer.getAll(limit);
191
+ const requests = all.map((r) => ({
192
+ id: r.id,
193
+ method: r.method,
194
+ uri: r.uri,
195
+ controller: r.controller,
196
+ responseStatus: r.responseStatus,
197
+ responseDuration: r.responseDuration,
198
+ time: r.time
199
+ }));
200
+ return {
201
+ requests,
202
+ metrics: {
203
+ timestamp: Date.now() / 1e3,
204
+ spans: []
205
+ }
206
+ };
207
+ }
208
+ /** For plugin/collector registration later. */
209
+ registerCollector(_name, _fn) {
210
+ }
211
+ };
212
+ }
213
+ });
214
+
215
+ // packages/transport-http/dist/index.js
216
+ var require_dist2 = __commonJS({
217
+ "packages/transport-http/dist/index.js"(exports, module) {
218
+ "use strict";
219
+ var __defProp2 = Object.defineProperty;
220
+ var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
221
+ var __getOwnPropNames2 = Object.getOwnPropertyNames;
222
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
223
+ var __export = (target, all) => {
224
+ for (var name in all)
225
+ __defProp2(target, name, { get: all[name], enumerable: true });
226
+ };
227
+ var __copyProps2 = (to, from, except, desc) => {
228
+ if (from && typeof from === "object" || typeof from === "function") {
229
+ for (let key of __getOwnPropNames2(from))
230
+ if (!__hasOwnProp2.call(to, key) && key !== except)
231
+ __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
232
+ }
233
+ return to;
234
+ };
235
+ var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
236
+ var index_exports = {};
237
+ __export(index_exports, {
238
+ createHttpAdapter: () => createHttpAdapter2
239
+ });
240
+ module.exports = __toCommonJS(index_exports);
241
+ var DEFAULT_REDACT_KEYS = [
242
+ "authorization",
243
+ "cookie",
244
+ "set-cookie",
245
+ "x-api-key",
246
+ "x-auth-token",
247
+ "password",
248
+ "passwd",
249
+ "secret",
250
+ "token",
251
+ "access_token",
252
+ "refresh_token",
253
+ "api_key",
254
+ "apikey",
255
+ "credential",
256
+ "credentials"
257
+ ];
258
+ function redactValue() {
259
+ return "[REDACTED]";
260
+ }
261
+ function truncate(str, maxLength) {
262
+ if (typeof str !== "string") return str;
263
+ if (str.length <= maxLength) return str;
264
+ return str.slice(0, maxLength) + "...[truncated]";
265
+ }
266
+ function shouldRedact(key, redactKeys) {
267
+ const lower = key.toLowerCase();
268
+ return redactKeys.some((k) => lower.includes(k.toLowerCase()) || k.toLowerCase().includes(lower));
269
+ }
270
+ function sanitizeHeaders(obj, options = {}) {
271
+ if (!obj || typeof obj !== "object") return {};
272
+ const keys = options.redactKeys ?? DEFAULT_REDACT_KEYS;
273
+ const maxLen = options.maxValueLength ?? 500;
274
+ const out = {};
275
+ for (const [k, v] of Object.entries(obj)) {
276
+ if (shouldRedact(k, keys)) {
277
+ out[k] = redactValue();
278
+ } else if (typeof v === "string") {
279
+ out[k] = truncate(v, maxLen);
280
+ } else {
281
+ out[k] = v;
282
+ }
283
+ }
284
+ return out;
285
+ }
286
+ var DEFAULT_MAX_DEPTH = 10;
287
+ var OMITTED_DEPTH = "[depth exceeded]";
288
+ function sanitizeBodyAtDepth(value, options) {
289
+ const keys = options.redactKeys ?? DEFAULT_REDACT_KEYS;
290
+ const maxLength = options.maxLength ?? 1e4;
291
+ const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
292
+ const depth = options._depth ?? 0;
293
+ if (value === null || value === void 0) return value;
294
+ if (typeof value === "string") return truncate(value, maxLength);
295
+ if (depth >= maxDepth) return OMITTED_DEPTH;
296
+ const nextOpts = {
297
+ redactKeys: keys,
298
+ maxLength,
299
+ maxDepth,
300
+ _depth: depth + 1
301
+ };
302
+ if (Array.isArray(value)) {
303
+ return value.slice(0, 50).map((item) => sanitizeBodyAtDepth(item, nextOpts));
304
+ }
305
+ if (typeof value === "object") {
306
+ const out = {};
307
+ for (const [k, v] of Object.entries(value)) {
308
+ if (shouldRedact(k, keys)) out[k] = redactValue();
309
+ else out[k] = sanitizeBodyAtDepth(v, nextOpts);
310
+ }
311
+ return out;
312
+ }
313
+ return value;
314
+ }
315
+ function sanitizeBody(value, options = {}) {
316
+ const { _depth, ...opts } = options;
317
+ return sanitizeBodyAtDepth(value, opts);
318
+ }
319
+ var DEFAULT_PATH2 = "/__clockwork";
320
+ var DEFAULT_REDACT_KEYS2 = [
321
+ "authorization",
322
+ "cookie",
323
+ "set-cookie",
324
+ "x-api-key",
325
+ "x-auth-token",
326
+ "password",
327
+ "passwd",
328
+ "secret",
329
+ "token",
330
+ "access_token",
331
+ "refresh_token"
332
+ ];
333
+ function getPathPrefix2(path3) {
334
+ return path3.replace(/\/$/, "") || DEFAULT_PATH2;
335
+ }
336
+ function getMethod(req) {
337
+ return (req.method || "GET").toUpperCase();
338
+ }
339
+ function getUri(req) {
340
+ return req.originalUrl ?? req.url ?? req.path ?? "/";
341
+ }
342
+ function getPathname2(req) {
343
+ const u = req.originalUrl ?? req.url ?? req.path ?? "/";
344
+ const q = u.indexOf("?");
345
+ return q === -1 ? u : u.slice(0, q);
346
+ }
347
+ function createHttpAdapter2(core, options = {}) {
348
+ const pathPrefix = getPathPrefix2(options.path ?? DEFAULT_PATH2);
349
+ const contextRunner = options.contextRunner;
350
+ const snapshotLimit = options.snapshotLimit ?? 50;
351
+ const redactKeys = options.redactKeys ?? DEFAULT_REDACT_KEYS2;
352
+ const maxBodySize = options.maxBodySize ?? 1e4;
353
+ const maxBodyDepth = options.maxBodyDepth ?? 10;
354
+ const captureRequestBody = options.captureRequestBody ?? true;
355
+ const captureResponseBody = options.captureResponseBody ?? true;
356
+ const ignoreStartsWith = options.ignoreStartsWith ?? [];
357
+ const sanitizeOpts = { redactKeys, maxLength: maxBodySize, maxDepth: maxBodyDepth };
358
+ function shouldIgnore(pathname) {
359
+ return ignoreStartsWith.some((p) => pathname.startsWith(p));
360
+ }
361
+ function isClockworkPath(pathname) {
362
+ return pathname === pathPrefix || pathname.startsWith(pathPrefix + "/");
363
+ }
364
+ function sendJson(res, body, statusCode) {
365
+ const payload = JSON.stringify(body);
366
+ if (statusCode != null && res.status) {
367
+ const r = res.status(statusCode);
368
+ if (r.json) r.json(body);
369
+ else r.end?.(payload);
370
+ } else if (res.json) {
371
+ res.json(body);
372
+ } else {
373
+ res.setHeader("Content-Type", "application/json");
374
+ res.end?.(payload);
375
+ }
376
+ }
377
+ const dataHandler = (req, res) => {
378
+ const pathname = getPathname2(req);
379
+ if (!isClockworkPath(pathname)) {
380
+ if (res.status) res.status(404).end?.("Not found");
381
+ else {
382
+ res.setHeader("Content-Type", "text/plain");
383
+ res.end?.("Not found");
384
+ }
385
+ return;
386
+ }
387
+ const relative = pathname.slice(pathPrefix.length).replace(/^\/+/, "") || "index";
388
+ const segments = relative.split("/");
389
+ if (segments[0] === "index" || segments[0] === "") {
390
+ sendJson(res, core.getSnapshot(snapshotLimit));
391
+ return;
392
+ }
393
+ if (segments[0] === "metrics") {
394
+ const snapshot = core.getSnapshot(1);
395
+ sendJson(res, snapshot.metrics ?? { timestamp: Date.now() / 1e3, spans: [] });
396
+ return;
397
+ }
398
+ if (segments[0] === "latest") {
399
+ const snapshot = core.getSnapshot(1);
400
+ const reqs = snapshot.requests;
401
+ if (reqs.length === 0) {
402
+ sendJson(res, { error: "No requests found" }, 404);
403
+ return;
404
+ }
405
+ const latest = core.getRequest(reqs[0].id);
406
+ sendJson(res, latest ?? {});
407
+ return;
408
+ }
409
+ const id = segments[0];
410
+ const request = core.getRequest(id);
411
+ if (!request) {
412
+ sendJson(res, { error: "Request not found" }, 404);
413
+ return;
414
+ }
415
+ sendJson(res, request);
416
+ };
417
+ const middleware = (req, res, next) => {
418
+ const pathname = getPathname2(req);
419
+ if (isClockworkPath(pathname)) {
420
+ dataHandler(req, res);
421
+ return;
422
+ }
423
+ if (shouldIgnore(pathname)) {
424
+ next();
425
+ return;
426
+ }
427
+ const headers = sanitizeHeaders(
428
+ req.headers,
429
+ { redactKeys, maxValueLength: 500 }
430
+ );
431
+ const getData = req.query ?? {};
432
+ const postData = captureRequestBody && req.body !== void 0 ? sanitizeBody(req.body, sanitizeOpts) : void 0;
433
+ const cookies = req.cookies !== void 0 ? sanitizeHeaders(req.cookies, { redactKeys }) : void 0;
434
+ const requestId = core.captureRequest({
435
+ method: getMethod(req),
436
+ uri: getUri(req),
437
+ headers,
438
+ getData: sanitizeBody(getData, sanitizeOpts),
439
+ postData,
440
+ cookies,
441
+ controller: req.route?.path
442
+ });
443
+ const startTimeMs = Date.now();
444
+ let capturedResponseBody = void 0;
445
+ const setHeader = res.setHeader.bind(res);
446
+ res.setHeader = function(name, value) {
447
+ if (!res.headersSent) {
448
+ if (name.toLowerCase() === "x-clockwork-id") {
449
+ setHeader("X-Clockwork-Id", String(value));
450
+ } else if (name.toLowerCase() === "x-clockwork-version") {
451
+ setHeader("X-Clockwork-Version", "2.0");
452
+ } else if (name.toLowerCase() === "x-clockwork-path") {
453
+ setHeader("X-Clockwork-Path", `${pathPrefix}/${value}`);
454
+ }
455
+ }
456
+ return setHeader(name, value);
457
+ };
458
+ const originalSend = res.send;
459
+ const originalJson = res.json;
460
+ if (originalSend) {
461
+ res.send = function(body) {
462
+ if (!res.headersSent) {
463
+ res.setHeader("X-Clockwork-Id", requestId);
464
+ res.setHeader("X-Clockwork-Version", "2.0");
465
+ res.setHeader("X-Clockwork-Path", `${pathPrefix}/${requestId}`);
466
+ }
467
+ if (captureResponseBody && body !== void 0) {
468
+ try {
469
+ const str = typeof body === "string" ? body : JSON.stringify(body);
470
+ capturedResponseBody = str.length <= maxBodySize ? typeof body === "string" ? body : body : str.slice(0, maxBodySize) + "...[truncated]";
471
+ } catch {
472
+ capturedResponseBody = "[unserializable]";
473
+ }
474
+ }
475
+ return originalSend.call(this, body);
476
+ };
477
+ }
478
+ if (originalJson) {
479
+ res.json = function(body) {
480
+ if (!res.headersSent) {
481
+ res.setHeader("X-Clockwork-Id", requestId);
482
+ res.setHeader("X-Clockwork-Version", "2.0");
483
+ res.setHeader("X-Clockwork-Path", `${pathPrefix}/${requestId}`);
484
+ }
485
+ if (captureResponseBody && body !== void 0) {
486
+ try {
487
+ const str = JSON.stringify(body);
488
+ capturedResponseBody = str.length <= maxBodySize ? body : str.slice(0, maxBodySize) + "...[truncated]";
489
+ } catch {
490
+ capturedResponseBody = "[unserializable]";
491
+ }
492
+ }
493
+ return originalJson.call(this, body);
494
+ };
495
+ }
496
+ res.on("finish", () => {
497
+ const statusCode = typeof res.statusCode === "number" ? res.statusCode : 200;
498
+ const duration = Date.now() - startTimeMs;
499
+ core.finalizeRequest(requestId, {
500
+ responseStatus: statusCode,
501
+ responseDuration: duration,
502
+ responseData: capturedResponseBody !== void 0 ? sanitizeBody(capturedResponseBody, sanitizeOpts) : void 0
503
+ });
504
+ });
505
+ req.clockworkId = requestId;
506
+ if (contextRunner) {
507
+ contextRunner(requestId, next);
508
+ } else {
509
+ next();
510
+ }
511
+ };
512
+ return { middleware, dataHandler };
513
+ }
514
+ }
515
+ });
516
+
517
+ // src/index.ts
518
+ var import_clockwork_core = __toESM(require_dist(), 1);
519
+ var import_clockwork_transport_http = __toESM(require_dist2(), 1);
520
+ import * as path2 from "path";
521
+ import { fileURLToPath } from "url";
522
+
523
+ // src/serve-static.ts
524
+ import fs from "fs";
525
+ import path from "path";
526
+ var MIMES = {
527
+ ".html": "text/html",
528
+ ".js": "application/javascript",
529
+ ".css": "text/css",
530
+ ".json": "application/json",
531
+ ".ico": "image/x-icon",
532
+ ".svg": "image/svg+xml",
533
+ ".woff": "font/woff",
534
+ ".woff2": "font/woff2"
535
+ };
536
+ function getPathname(req) {
537
+ const u = req.originalUrl ?? req.url ?? req.path ?? "/";
538
+ const q = u.indexOf("?");
539
+ return q === -1 ? u : u.slice(0, q);
540
+ }
541
+ function sendFile(res, filePath, contentType) {
542
+ const data = fs.readFileSync(filePath);
543
+ res.setHeader("Content-Type", contentType);
544
+ res.setHeader("Content-Length", String(data.length));
545
+ if (res.status) res.status(200);
546
+ if (res.end) res.end(data);
547
+ else if (res.send) res.send(data);
548
+ }
549
+ function send404(res) {
550
+ if (res.status) res.status(404);
551
+ res.setHeader("Content-Type", "text/plain");
552
+ if (res.end) res.end("Not Found");
553
+ }
554
+ function createServeStatic(dir, appPath) {
555
+ const normalizedApp = appPath.replace(/\/+$/, "") || "/app";
556
+ const dirResolved = path.resolve(dir);
557
+ return function serveStatic(req, res, next) {
558
+ const pathname = getPathname(req);
559
+ if (pathname !== normalizedApp && pathname !== normalizedApp + "/" && !pathname.startsWith(normalizedApp + "/")) {
560
+ return next();
561
+ }
562
+ let relative = pathname.slice(normalizedApp.length).replace(/^\/+/, "") || "";
563
+ if (relative === "" || pathname.endsWith("/")) relative = "index.html";
564
+ const filePath = path.join(dirResolved, relative);
565
+ const resolved = path.resolve(filePath);
566
+ if (!resolved.startsWith(dirResolved + path.sep) && resolved !== dirResolved) {
567
+ send404(res);
568
+ return;
569
+ }
570
+ if (!fs.existsSync(resolved) || !fs.statSync(resolved).isFile()) {
571
+ send404(res);
572
+ return;
573
+ }
574
+ const ext = path.extname(resolved);
575
+ const contentType = MIMES[ext] ?? "application/octet-stream";
576
+ sendFile(res, resolved, contentType);
577
+ };
578
+ }
579
+
580
+ // src/index.ts
581
+ import {
582
+ getDefaultPlugins,
583
+ contextPlugin,
584
+ consolePlugin,
585
+ processErrorsPlugin,
586
+ pinoPlugin,
587
+ winstonPlugin,
588
+ defaultCorePlugins,
589
+ defaultLogPlugins,
590
+ defaultDbPlugins,
591
+ pgPlugin,
592
+ mysql2Plugin
593
+ } from "@adjedaini/clockwork-plugins";
594
+ var __dirname = path2.dirname(fileURLToPath(import.meta.url));
595
+ var DEFAULT_PATH = "/__clockwork";
596
+ function getPathPrefix(p) {
597
+ return (p ?? DEFAULT_PATH).replace(/\/$/, "") || DEFAULT_PATH;
598
+ }
599
+ function startClockwork(options = {}) {
600
+ const coreConfig = options.core ?? {};
601
+ const core = new import_clockwork_core.MonitorCore(coreConfig);
602
+ core.start();
603
+ let getRequestIdRef = () => void 0;
604
+ let contextRunnerRef = null;
605
+ const pluginContext = {
606
+ get core() {
607
+ return core;
608
+ },
609
+ getRequestId() {
610
+ return getRequestIdRef();
611
+ },
612
+ registerContext(getRequestId, contextRunner2) {
613
+ getRequestIdRef = getRequestId;
614
+ contextRunnerRef = contextRunner2;
615
+ }
616
+ };
617
+ const plugins = options.plugins !== void 0 && options.plugins.length > 0 ? options.plugins : getDefaultPlugins({
618
+ console: options.autoConsole !== false,
619
+ errors: options.autoErrors !== false,
620
+ logPlugins: options.autoLogPlugins === true,
621
+ db: options.autoDb === true,
622
+ dbPlugins: options.dbPlugins
623
+ });
624
+ const restores = [];
625
+ for (const plugin of plugins) {
626
+ restores.push(plugin.install(pluginContext));
627
+ }
628
+ const contextRunner = contextRunnerRef ?? ((_, next) => next());
629
+ const pathPrefix = getPathPrefix(options.path ?? DEFAULT_PATH);
630
+ const adapter = (0, import_clockwork_transport_http.createHttpAdapter)(core, {
631
+ path: options.path,
632
+ contextRunner,
633
+ snapshotLimit: options.snapshotLimit,
634
+ redactKeys: options.redactKeys,
635
+ maxBodySize: options.maxBodySize,
636
+ maxBodyDepth: options.maxBodyDepth,
637
+ captureRequestBody: options.captureRequestBody,
638
+ captureResponseBody: options.captureResponseBody,
639
+ ignoreStartsWith: options.ignoreStartsWith
640
+ });
641
+ const uiPath = options.uiPath ?? path2.join(__dirname, "public");
642
+ const uiEnabled = options.ui !== false;
643
+ const serveUi = uiEnabled ? createServeStatic(uiPath, pathPrefix + "/app") : null;
644
+ function registerPlugin(plugin) {
645
+ restores.push(plugin.install(pluginContext));
646
+ }
647
+ const middleware = (req, res, next) => {
648
+ if (serveUi) {
649
+ serveUi(req, res, () => adapter.middleware(req, res, next));
650
+ } else {
651
+ adapter.middleware(req, res, next);
652
+ }
653
+ };
654
+ return {
655
+ core,
656
+ middleware,
657
+ handler: adapter.dataHandler,
658
+ uiPath,
659
+ registerPlugin,
660
+ restore() {
661
+ restores.forEach((r) => r());
662
+ }
663
+ };
664
+ }
665
+ var index_default = {
666
+ startClockwork,
667
+ MonitorCore: import_clockwork_core.MonitorCore,
668
+ createHttpAdapter: import_clockwork_transport_http.createHttpAdapter,
669
+ contextPlugin,
670
+ consolePlugin,
671
+ processErrorsPlugin,
672
+ pinoPlugin,
673
+ winstonPlugin,
674
+ pgPlugin,
675
+ mysql2Plugin,
676
+ defaultCorePlugins,
677
+ defaultLogPlugins,
678
+ defaultDbPlugins,
679
+ getDefaultPlugins
680
+ };
681
+ export {
682
+ consolePlugin,
683
+ contextPlugin,
684
+ index_default as default,
685
+ defaultCorePlugins,
686
+ defaultDbPlugins,
687
+ defaultLogPlugins,
688
+ getDefaultPlugins,
689
+ mysql2Plugin,
690
+ pgPlugin,
691
+ pinoPlugin,
692
+ processErrorsPlugin,
693
+ startClockwork,
694
+ winstonPlugin
695
+ };