@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,14 @@
1
+ {
2
+ "name": "@adjedaini/clockwork-shared",
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
+ "devDependencies": {
11
+ "tsup": "^8.0.0",
12
+ "typescript": "^5.5.0"
13
+ }
14
+ }
@@ -0,0 +1,96 @@
1
+ /** Shared types for @adjedaini/clockwork-node. Framework-agnostic. */
2
+
3
+ /** Per-request context (AsyncLocalStorage). Used to correlate logs/queries to the current request. */
4
+ export interface ClockworkContext {
5
+ requestId: string;
6
+ }
7
+
8
+ export interface LogData {
9
+ level: 'debug' | 'info' | 'warning' | 'error';
10
+ message: string;
11
+ context?: Record<string, unknown>;
12
+ time: number;
13
+ source?: 'native' | 'clockwork';
14
+ }
15
+
16
+ export interface QueryData {
17
+ query: string;
18
+ bindings?: unknown[];
19
+ duration?: number;
20
+ connection?: string;
21
+ }
22
+
23
+ export interface EventData {
24
+ name: string;
25
+ description?: string;
26
+ duration?: number;
27
+ start?: number;
28
+ end?: number;
29
+ data?: Record<string, unknown>;
30
+ color?: string;
31
+ }
32
+
33
+ export interface RequestSnapshot {
34
+ id: string;
35
+ type: 'http';
36
+ method: string;
37
+ uri: string;
38
+ headers: Record<string, unknown>;
39
+ getData: Record<string, unknown>;
40
+ postData?: unknown;
41
+ responseData?: unknown;
42
+ cookies?: Record<string, unknown>;
43
+ responseStatus: number;
44
+ responseTime: number;
45
+ responseDuration: number;
46
+ memoryUsage: number;
47
+ time: number;
48
+ log: LogData[];
49
+ databaseQueries: QueryData[];
50
+ timelineData: EventData[];
51
+ controller?: string;
52
+ }
53
+
54
+ export interface RequestMetadata {
55
+ id: string;
56
+ method: string;
57
+ uri: string;
58
+ controller?: string;
59
+ responseStatus: number;
60
+ responseDuration: number;
61
+ time: number;
62
+ }
63
+
64
+ export interface MetricsSpan {
65
+ interval: number;
66
+ retention: number;
67
+ responseTime: number[];
68
+ rps: number[];
69
+ statusCodes?: Record<string, number>[];
70
+ }
71
+
72
+ export interface Snapshot {
73
+ requests: RequestMetadata[];
74
+ metrics?: {
75
+ spans: MetricsSpan[];
76
+ timestamp: number;
77
+ os?: { cpu: number; memory: number; heapUsed: number; heapTotal: number; rss: number };
78
+ process?: { uptime: number; eventLoopDelay?: number };
79
+ };
80
+ }
81
+
82
+ /** Storage backend for request snapshots. Implement for Redis, SQLite, file, etc. */
83
+ export interface IRequestStorage {
84
+ push(id: string, request: RequestSnapshot): void;
85
+ get(id: string): RequestSnapshot | undefined;
86
+ getAll(limit: number): RequestSnapshot[];
87
+ getLatest(): RequestSnapshot | undefined;
88
+ }
89
+
90
+ export interface CoreConfig {
91
+ maxRequests?: number;
92
+ maxBodyDepth?: number;
93
+ maxBodySize?: number;
94
+ /** Custom storage backend. Default: in-memory ring buffer. */
95
+ storage?: IRequestStorage;
96
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "composite": false
5
+ }
6
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src",
6
+ "composite": true
7
+ },
8
+ "include": ["src/**/*"]
9
+ }
@@ -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,75 @@
1
+ import { MonitorCore } from '@adjedaini/clockwork-core';
2
+
3
+ /**
4
+ * Minimal HTTP request/response-like types.
5
+ * No hard dependency on Express; compatible with Express, Fastify (with adapters), etc.
6
+ */
7
+ interface ClockworkRequestLike {
8
+ method: string;
9
+ url?: string;
10
+ originalUrl?: string;
11
+ path?: string;
12
+ headers: Record<string, string | string[] | undefined>;
13
+ body?: unknown;
14
+ /** Parsed query (e.g. from ?foo=bar). */
15
+ query?: Record<string, unknown>;
16
+ /** Parsed cookies if available. */
17
+ cookies?: Record<string, unknown>;
18
+ /** Route pattern if available (e.g. "/user/:id"). */
19
+ route?: {
20
+ path?: string;
21
+ };
22
+ }
23
+ interface ClockworkResponseLike {
24
+ setHeader(name: string, value: string | number): void;
25
+ getHeader?(name: string): string | number | string[] | undefined;
26
+ statusCode: number;
27
+ on(event: 'finish', fn: () => void): void;
28
+ /** Set status and return chainable res (Express-style). */
29
+ status?(code: number): ClockworkResponseLike;
30
+ /** Send body (string or Buffer). */
31
+ send?(body?: unknown): unknown;
32
+ /** Send JSON. */
33
+ json?(body?: unknown): unknown;
34
+ /** End response with optional body. */
35
+ end?(body?: string): void;
36
+ headersSent?: boolean;
37
+ }
38
+ type NextLike = (err?: unknown) => void;
39
+
40
+ /**
41
+ * @adjedaini/clockwork-transport-http
42
+ * HTTP adapter: wraps core, exposes middleware + data handler.
43
+ * No hard dependency on Express types.
44
+ */
45
+
46
+ type ContextRunner = (requestId: string, next: NextLike) => void;
47
+ interface HttpAdapterOptions {
48
+ /** Base path for API and UI (e.g. "/__clockwork"). No trailing slash. */
49
+ path?: string;
50
+ /** Run the rest of the request (next) inside this context (e.g. AsyncLocalStorage.run). Enables per-request correlation. */
51
+ contextRunner?: ContextRunner;
52
+ /** Max request list returned by snapshot. */
53
+ snapshotLimit?: number;
54
+ /** Redact these keys in headers/body. */
55
+ redactKeys?: string[];
56
+ /** Max body size to capture (chars). */
57
+ maxBodySize?: number;
58
+ /** Max depth when serializing body. */
59
+ maxBodyDepth?: number;
60
+ /** Capture request body. */
61
+ captureRequestBody?: boolean;
62
+ /** Capture response body. */
63
+ captureResponseBody?: boolean;
64
+ /** Skip paths that start with any of these. */
65
+ ignoreStartsWith?: string[];
66
+ }
67
+ interface HttpAdapter {
68
+ /** Middleware: capture request, call next(), finalize on res finish. */
69
+ middleware(req: ClockworkRequestLike, res: ClockworkResponseLike, next: NextLike): void;
70
+ /** Handler: serve JSON API (snapshot, by id). Call for GET path, path/latest, path/:id. */
71
+ dataHandler(req: ClockworkRequestLike, res: ClockworkResponseLike): void;
72
+ }
73
+ declare function createHttpAdapter(core: MonitorCore, options?: HttpAdapterOptions): HttpAdapter;
74
+
75
+ export { type ClockworkRequestLike, type ClockworkResponseLike, type ContextRunner, type HttpAdapter, type HttpAdapterOptions, type NextLike, createHttpAdapter };
@@ -0,0 +1,306 @@
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
+ createHttpAdapter: () => createHttpAdapter
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/sanitize.ts
28
+ var DEFAULT_REDACT_KEYS = [
29
+ "authorization",
30
+ "cookie",
31
+ "set-cookie",
32
+ "x-api-key",
33
+ "x-auth-token",
34
+ "password",
35
+ "passwd",
36
+ "secret",
37
+ "token",
38
+ "access_token",
39
+ "refresh_token",
40
+ "api_key",
41
+ "apikey",
42
+ "credential",
43
+ "credentials"
44
+ ];
45
+ function redactValue() {
46
+ return "[REDACTED]";
47
+ }
48
+ function truncate(str, maxLength) {
49
+ if (typeof str !== "string") return str;
50
+ if (str.length <= maxLength) return str;
51
+ return str.slice(0, maxLength) + "...[truncated]";
52
+ }
53
+ function shouldRedact(key, redactKeys) {
54
+ const lower = key.toLowerCase();
55
+ return redactKeys.some((k) => lower.includes(k.toLowerCase()) || k.toLowerCase().includes(lower));
56
+ }
57
+ function sanitizeHeaders(obj, options = {}) {
58
+ if (!obj || typeof obj !== "object") return {};
59
+ const keys = options.redactKeys ?? DEFAULT_REDACT_KEYS;
60
+ const maxLen = options.maxValueLength ?? 500;
61
+ const out = {};
62
+ for (const [k, v] of Object.entries(obj)) {
63
+ if (shouldRedact(k, keys)) {
64
+ out[k] = redactValue();
65
+ } else if (typeof v === "string") {
66
+ out[k] = truncate(v, maxLen);
67
+ } else {
68
+ out[k] = v;
69
+ }
70
+ }
71
+ return out;
72
+ }
73
+ var DEFAULT_MAX_DEPTH = 10;
74
+ var OMITTED_DEPTH = "[depth exceeded]";
75
+ function sanitizeBodyAtDepth(value, options) {
76
+ const keys = options.redactKeys ?? DEFAULT_REDACT_KEYS;
77
+ const maxLength = options.maxLength ?? 1e4;
78
+ const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
79
+ const depth = options._depth ?? 0;
80
+ if (value === null || value === void 0) return value;
81
+ if (typeof value === "string") return truncate(value, maxLength);
82
+ if (depth >= maxDepth) return OMITTED_DEPTH;
83
+ const nextOpts = {
84
+ redactKeys: keys,
85
+ maxLength,
86
+ maxDepth,
87
+ _depth: depth + 1
88
+ };
89
+ if (Array.isArray(value)) {
90
+ return value.slice(0, 50).map((item) => sanitizeBodyAtDepth(item, nextOpts));
91
+ }
92
+ if (typeof value === "object") {
93
+ const out = {};
94
+ for (const [k, v] of Object.entries(value)) {
95
+ if (shouldRedact(k, keys)) out[k] = redactValue();
96
+ else out[k] = sanitizeBodyAtDepth(v, nextOpts);
97
+ }
98
+ return out;
99
+ }
100
+ return value;
101
+ }
102
+ function sanitizeBody(value, options = {}) {
103
+ const { _depth, ...opts } = options;
104
+ return sanitizeBodyAtDepth(value, opts);
105
+ }
106
+
107
+ // src/index.ts
108
+ var DEFAULT_PATH = "/__clockwork";
109
+ var DEFAULT_REDACT_KEYS2 = [
110
+ "authorization",
111
+ "cookie",
112
+ "set-cookie",
113
+ "x-api-key",
114
+ "x-auth-token",
115
+ "password",
116
+ "passwd",
117
+ "secret",
118
+ "token",
119
+ "access_token",
120
+ "refresh_token"
121
+ ];
122
+ function getPathPrefix(path) {
123
+ return path.replace(/\/$/, "") || DEFAULT_PATH;
124
+ }
125
+ function getMethod(req) {
126
+ return (req.method || "GET").toUpperCase();
127
+ }
128
+ function getUri(req) {
129
+ return req.originalUrl ?? req.url ?? req.path ?? "/";
130
+ }
131
+ function getPathname(req) {
132
+ const u = req.originalUrl ?? req.url ?? req.path ?? "/";
133
+ const q = u.indexOf("?");
134
+ return q === -1 ? u : u.slice(0, q);
135
+ }
136
+ function createHttpAdapter(core, options = {}) {
137
+ const pathPrefix = getPathPrefix(options.path ?? DEFAULT_PATH);
138
+ const contextRunner = options.contextRunner;
139
+ const snapshotLimit = options.snapshotLimit ?? 50;
140
+ const redactKeys = options.redactKeys ?? DEFAULT_REDACT_KEYS2;
141
+ const maxBodySize = options.maxBodySize ?? 1e4;
142
+ const maxBodyDepth = options.maxBodyDepth ?? 10;
143
+ const captureRequestBody = options.captureRequestBody ?? true;
144
+ const captureResponseBody = options.captureResponseBody ?? true;
145
+ const ignoreStartsWith = options.ignoreStartsWith ?? [];
146
+ const sanitizeOpts = { redactKeys, maxLength: maxBodySize, maxDepth: maxBodyDepth };
147
+ function shouldIgnore(pathname) {
148
+ return ignoreStartsWith.some((p) => pathname.startsWith(p));
149
+ }
150
+ function isClockworkPath(pathname) {
151
+ return pathname === pathPrefix || pathname.startsWith(pathPrefix + "/");
152
+ }
153
+ function sendJson(res, body, statusCode) {
154
+ const payload = JSON.stringify(body);
155
+ if (statusCode != null && res.status) {
156
+ const r = res.status(statusCode);
157
+ if (r.json) r.json(body);
158
+ else r.end?.(payload);
159
+ } else if (res.json) {
160
+ res.json(body);
161
+ } else {
162
+ res.setHeader("Content-Type", "application/json");
163
+ res.end?.(payload);
164
+ }
165
+ }
166
+ const dataHandler = (req, res) => {
167
+ const pathname = getPathname(req);
168
+ if (!isClockworkPath(pathname)) {
169
+ if (res.status) res.status(404).end?.("Not found");
170
+ else {
171
+ res.setHeader("Content-Type", "text/plain");
172
+ res.end?.("Not found");
173
+ }
174
+ return;
175
+ }
176
+ const relative = pathname.slice(pathPrefix.length).replace(/^\/+/, "") || "index";
177
+ const segments = relative.split("/");
178
+ if (segments[0] === "index" || segments[0] === "") {
179
+ sendJson(res, core.getSnapshot(snapshotLimit));
180
+ return;
181
+ }
182
+ if (segments[0] === "metrics") {
183
+ const snapshot = core.getSnapshot(1);
184
+ sendJson(res, snapshot.metrics ?? { timestamp: Date.now() / 1e3, spans: [] });
185
+ return;
186
+ }
187
+ if (segments[0] === "latest") {
188
+ const snapshot = core.getSnapshot(1);
189
+ const reqs = snapshot.requests;
190
+ if (reqs.length === 0) {
191
+ sendJson(res, { error: "No requests found" }, 404);
192
+ return;
193
+ }
194
+ const latest = core.getRequest(reqs[0].id);
195
+ sendJson(res, latest ?? {});
196
+ return;
197
+ }
198
+ const id = segments[0];
199
+ const request = core.getRequest(id);
200
+ if (!request) {
201
+ sendJson(res, { error: "Request not found" }, 404);
202
+ return;
203
+ }
204
+ sendJson(res, request);
205
+ };
206
+ const middleware = (req, res, next) => {
207
+ const pathname = getPathname(req);
208
+ if (isClockworkPath(pathname)) {
209
+ dataHandler(req, res);
210
+ return;
211
+ }
212
+ if (shouldIgnore(pathname)) {
213
+ next();
214
+ return;
215
+ }
216
+ const headers = sanitizeHeaders(
217
+ req.headers,
218
+ { redactKeys, maxValueLength: 500 }
219
+ );
220
+ const getData = req.query ?? {};
221
+ const postData = captureRequestBody && req.body !== void 0 ? sanitizeBody(req.body, sanitizeOpts) : void 0;
222
+ const cookies = req.cookies !== void 0 ? sanitizeHeaders(req.cookies, { redactKeys }) : void 0;
223
+ const requestId = core.captureRequest({
224
+ method: getMethod(req),
225
+ uri: getUri(req),
226
+ headers,
227
+ getData: sanitizeBody(getData, sanitizeOpts),
228
+ postData,
229
+ cookies,
230
+ controller: req.route?.path
231
+ });
232
+ const startTimeMs = Date.now();
233
+ let capturedResponseBody = void 0;
234
+ const setHeader = res.setHeader.bind(res);
235
+ res.setHeader = function(name, value) {
236
+ if (!res.headersSent) {
237
+ if (name.toLowerCase() === "x-clockwork-id") {
238
+ setHeader("X-Clockwork-Id", String(value));
239
+ } else if (name.toLowerCase() === "x-clockwork-version") {
240
+ setHeader("X-Clockwork-Version", "2.0");
241
+ } else if (name.toLowerCase() === "x-clockwork-path") {
242
+ setHeader("X-Clockwork-Path", `${pathPrefix}/${value}`);
243
+ }
244
+ }
245
+ return setHeader(name, value);
246
+ };
247
+ const originalSend = res.send;
248
+ const originalJson = res.json;
249
+ if (originalSend) {
250
+ res.send = function(body) {
251
+ if (!res.headersSent) {
252
+ res.setHeader("X-Clockwork-Id", requestId);
253
+ res.setHeader("X-Clockwork-Version", "2.0");
254
+ res.setHeader("X-Clockwork-Path", `${pathPrefix}/${requestId}`);
255
+ }
256
+ if (captureResponseBody && body !== void 0) {
257
+ try {
258
+ const str = typeof body === "string" ? body : JSON.stringify(body);
259
+ capturedResponseBody = str.length <= maxBodySize ? typeof body === "string" ? body : body : str.slice(0, maxBodySize) + "...[truncated]";
260
+ } catch {
261
+ capturedResponseBody = "[unserializable]";
262
+ }
263
+ }
264
+ return originalSend.call(this, body);
265
+ };
266
+ }
267
+ if (originalJson) {
268
+ res.json = function(body) {
269
+ if (!res.headersSent) {
270
+ res.setHeader("X-Clockwork-Id", requestId);
271
+ res.setHeader("X-Clockwork-Version", "2.0");
272
+ res.setHeader("X-Clockwork-Path", `${pathPrefix}/${requestId}`);
273
+ }
274
+ if (captureResponseBody && body !== void 0) {
275
+ try {
276
+ const str = JSON.stringify(body);
277
+ capturedResponseBody = str.length <= maxBodySize ? body : str.slice(0, maxBodySize) + "...[truncated]";
278
+ } catch {
279
+ capturedResponseBody = "[unserializable]";
280
+ }
281
+ }
282
+ return originalJson.call(this, body);
283
+ };
284
+ }
285
+ res.on("finish", () => {
286
+ const statusCode = typeof res.statusCode === "number" ? res.statusCode : 200;
287
+ const duration = Date.now() - startTimeMs;
288
+ core.finalizeRequest(requestId, {
289
+ responseStatus: statusCode,
290
+ responseDuration: duration,
291
+ responseData: capturedResponseBody !== void 0 ? sanitizeBody(capturedResponseBody, sanitizeOpts) : void 0
292
+ });
293
+ });
294
+ req.clockworkId = requestId;
295
+ if (contextRunner) {
296
+ contextRunner(requestId, next);
297
+ } else {
298
+ next();
299
+ }
300
+ };
301
+ return { middleware, dataHandler };
302
+ }
303
+ // Annotate the CommonJS export names for ESM import in node:
304
+ 0 && (module.exports = {
305
+ createHttpAdapter
306
+ });
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@adjedaini/clockwork-transport-http",
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-core": "*",
12
+ "@adjedaini/clockwork-shared": "*"
13
+ },
14
+ "devDependencies": {
15
+ "tsup": "^8.0.0",
16
+ "typescript": "^5.5.0"
17
+ }
18
+ }