@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,163 @@
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
+ defaultDbPlugins: () => defaultDbPlugins,
24
+ mysql2Plugin: () => mysql2Plugin,
25
+ patchMysql2: () => patchMysql2,
26
+ patchPg: () => patchPg,
27
+ pgPlugin: () => pgPlugin
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/pg.ts
32
+ var restored = false;
33
+ function patchPg(core, getRequestId) {
34
+ let pg = null;
35
+ try {
36
+ pg = require("pg");
37
+ } catch {
38
+ return () => {
39
+ };
40
+ }
41
+ if (!pg?.Client?.prototype?.query) return () => {
42
+ };
43
+ if (restored) return () => {
44
+ };
45
+ const Client = pg.Client;
46
+ const originalQuery = Client.prototype.query;
47
+ Client.prototype.query = function(...args) {
48
+ const start = performance.now();
49
+ const firstArg = args[0];
50
+ const queryText = typeof firstArg === "string" ? firstArg : firstArg?.text ?? String(firstArg);
51
+ const bindings = typeof firstArg === "object" && firstArg !== null && "values" in firstArg ? firstArg.values : void 0;
52
+ const result = originalQuery.apply(this, args);
53
+ const onDone = () => {
54
+ const duration = performance.now() - start;
55
+ const requestId = getRequestId();
56
+ if (requestId) {
57
+ core.addQuery(requestId, {
58
+ query: queryText,
59
+ bindings,
60
+ duration,
61
+ connection: "pg"
62
+ });
63
+ }
64
+ };
65
+ if (result && typeof result.then === "function") result.finally(onDone);
66
+ else setTimeout(onDone, 0);
67
+ return result;
68
+ };
69
+ return function restore() {
70
+ if (Client.prototype.query === originalQuery) return;
71
+ Client.prototype.query = originalQuery;
72
+ restored = true;
73
+ };
74
+ }
75
+
76
+ // src/mysql2.ts
77
+ function patchMysql2(core, getRequestId) {
78
+ let mysql2 = null;
79
+ try {
80
+ mysql2 = require("mysql2");
81
+ } catch {
82
+ return () => {
83
+ };
84
+ }
85
+ if (!mysql2?.createConnection) return () => {
86
+ };
87
+ const originalCreateConnection = mysql2.createConnection.bind(mysql2);
88
+ function wrapQuery(conn) {
89
+ const origQuery = conn.query;
90
+ const origExecute = conn.execute;
91
+ if (typeof origQuery === "function") {
92
+ conn.query = function(sql, ...args) {
93
+ const start = performance.now();
94
+ const queryText = typeof sql === "string" ? sql : String(sql);
95
+ const bindings = Array.isArray(args[0]) ? args[0] : void 0;
96
+ const result = origQuery.apply(this, [sql, ...args]);
97
+ const onDone = () => {
98
+ const requestId = getRequestId();
99
+ if (requestId) {
100
+ core.addQuery(requestId, {
101
+ query: queryText,
102
+ bindings,
103
+ duration: performance.now() - start,
104
+ connection: "mysql2"
105
+ });
106
+ }
107
+ };
108
+ if (result?.then) result.finally(onDone);
109
+ else setTimeout(onDone, 0);
110
+ return result;
111
+ };
112
+ }
113
+ if (typeof origExecute === "function") {
114
+ conn.execute = function(sql, ...args) {
115
+ const start = performance.now();
116
+ const queryText = typeof sql === "string" ? sql : String(sql);
117
+ const bindings = Array.isArray(args[0]) ? args[0] : void 0;
118
+ const result = origExecute.apply(this, [sql, ...args]);
119
+ const onDone = () => {
120
+ const requestId = getRequestId();
121
+ if (requestId) {
122
+ core.addQuery(requestId, {
123
+ query: queryText,
124
+ bindings,
125
+ duration: performance.now() - start,
126
+ connection: "mysql2"
127
+ });
128
+ }
129
+ };
130
+ if (result?.then) result.finally(onDone);
131
+ else setTimeout(onDone, 0);
132
+ return result;
133
+ };
134
+ }
135
+ }
136
+ mysql2.createConnection = function(opts) {
137
+ const conn = originalCreateConnection(opts);
138
+ wrapQuery(conn);
139
+ return conn;
140
+ };
141
+ return function restore() {
142
+ mysql2.createConnection = originalCreateConnection;
143
+ };
144
+ }
145
+
146
+ // src/index.ts
147
+ var pgPlugin = {
148
+ name: "pg",
149
+ install: (ctx) => patchPg(ctx.core, ctx.getRequestId)
150
+ };
151
+ var mysql2Plugin = {
152
+ name: "mysql2",
153
+ install: (ctx) => patchMysql2(ctx.core, ctx.getRequestId)
154
+ };
155
+ var defaultDbPlugins = [pgPlugin, mysql2Plugin];
156
+ // Annotate the CommonJS export names for ESM import in node:
157
+ 0 && (module.exports = {
158
+ defaultDbPlugins,
159
+ mysql2Plugin,
160
+ patchMysql2,
161
+ patchPg,
162
+ pgPlugin
163
+ });
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@adjedaini/clockwork-db-interceptor",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsup"
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
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @adjedaini/clockwork-db-interceptor
3
+ * Optional DB query instrumentation as pluggable plugins (pg, mysql2).
4
+ * Implements generic ClockworkPlugin from core (IPluginContext).
5
+ */
6
+
7
+ import type { ClockworkPlugin, IPluginContext } from '@adjedaini/clockwork-core';
8
+ import { patchPg } from './pg';
9
+ import { patchMysql2 } from './mysql2';
10
+
11
+ export type GetRequestId = () => string | undefined;
12
+
13
+ /** DB plugins conform to generic ClockworkPlugin. */
14
+ export const pgPlugin: ClockworkPlugin = {
15
+ name: 'pg',
16
+ install: (ctx: IPluginContext) => patchPg(ctx.core, ctx.getRequestId),
17
+ };
18
+
19
+ export const mysql2Plugin: ClockworkPlugin = {
20
+ name: 'mysql2',
21
+ install: (ctx: IPluginContext) => patchMysql2(ctx.core, ctx.getRequestId),
22
+ };
23
+
24
+ /** Default set of DB plugins (pg + mysql2). */
25
+ export const defaultDbPlugins: ClockworkPlugin[] = [pgPlugin, mysql2Plugin];
26
+
27
+ export { patchPg, patchMysql2 };
28
+ export type { ClockworkPlugin, IPluginContext } from '@adjedaini/clockwork-core';
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Patch mysql2 so Connection.query/execute are tracked. Only applied if 'mysql2' is installed.
3
+ * Wraps createConnection to patch the returned connection.
4
+ */
5
+
6
+ import type { MonitorCore } from '@adjedaini/clockwork-core';
7
+
8
+ export type GetRequestId = () => string | undefined;
9
+
10
+ export function patchMysql2(core: MonitorCore, getRequestId: GetRequestId): () => void {
11
+ let mysql2: { createConnection: (opts?: unknown) => Connection } | null = null;
12
+ try {
13
+ mysql2 = require('mysql2');
14
+ } catch {
15
+ return () => {};
16
+ }
17
+ if (!mysql2?.createConnection) return () => {};
18
+
19
+ interface Connection {
20
+ query: (sql: unknown, ...args: unknown[]) => unknown;
21
+ execute?: (sql: unknown, ...args: unknown[]) => unknown;
22
+ }
23
+
24
+ const originalCreateConnection = mysql2.createConnection.bind(mysql2);
25
+
26
+ function wrapQuery(conn: Connection): void {
27
+ const origQuery = conn.query;
28
+ const origExecute = conn.execute;
29
+ if (typeof origQuery === 'function') {
30
+ conn.query = function (this: Connection, sql: unknown, ...args: unknown[]) {
31
+ const start = performance.now();
32
+ const queryText = typeof sql === 'string' ? sql : String(sql);
33
+ const bindings = Array.isArray(args[0]) ? args[0] : undefined;
34
+ const result = (origQuery as Function).apply(this, [sql, ...args]);
35
+ const onDone = () => {
36
+ const requestId = getRequestId();
37
+ if (requestId) {
38
+ core.addQuery(requestId, {
39
+ query: queryText,
40
+ bindings,
41
+ duration: performance.now() - start,
42
+ connection: 'mysql2',
43
+ });
44
+ }
45
+ };
46
+ if (result?.then) (result as Promise<unknown>).finally(onDone);
47
+ else setTimeout(onDone, 0);
48
+ return result;
49
+ };
50
+ }
51
+ if (typeof origExecute === 'function') {
52
+ conn.execute = function (this: Connection, sql: unknown, ...args: unknown[]) {
53
+ const start = performance.now();
54
+ const queryText = typeof sql === 'string' ? sql : String(sql);
55
+ const bindings = Array.isArray(args[0]) ? args[0] : undefined;
56
+ const result = (origExecute as Function).apply(this, [sql, ...args]);
57
+ const onDone = () => {
58
+ const requestId = getRequestId();
59
+ if (requestId) {
60
+ core.addQuery(requestId, {
61
+ query: queryText,
62
+ bindings,
63
+ duration: performance.now() - start,
64
+ connection: 'mysql2',
65
+ });
66
+ }
67
+ };
68
+ if (result?.then) (result as Promise<unknown>).finally(onDone);
69
+ else setTimeout(onDone, 0);
70
+ return result;
71
+ };
72
+ }
73
+ }
74
+
75
+ (mysql2 as { createConnection: (opts?: unknown) => Connection }).createConnection = function (opts?: unknown) {
76
+ const conn = originalCreateConnection(opts) as Connection;
77
+ wrapQuery(conn);
78
+ return conn;
79
+ };
80
+
81
+ return function restore() {
82
+ (mysql2 as { createConnection: (opts?: unknown) => Connection }).createConnection = originalCreateConnection;
83
+ };
84
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Patch pg Client.query so queries are attached to the current request (when in context).
3
+ * Only applied if the 'pg' module is installed.
4
+ */
5
+
6
+ import type { MonitorCore } from '@adjedaini/clockwork-core';
7
+
8
+ export type GetRequestId = () => string | undefined;
9
+
10
+ let restored = false;
11
+
12
+ export function patchPg(core: MonitorCore, getRequestId: GetRequestId): () => void {
13
+ let pg: { Client?: { prototype: { query: (...args: unknown[]) => unknown } } } | null = null;
14
+ try {
15
+ pg = require('pg');
16
+ } catch {
17
+ return () => {};
18
+ }
19
+ if (!pg?.Client?.prototype?.query) return () => {};
20
+ if (restored) return () => {};
21
+
22
+ const Client = pg.Client!;
23
+ const originalQuery = Client.prototype.query;
24
+
25
+ Client.prototype.query = function (this: unknown, ...args: unknown[]) {
26
+ const start = performance.now();
27
+ const firstArg = args[0];
28
+ const queryText = typeof firstArg === 'string' ? firstArg : (firstArg as { text?: string })?.text ?? String(firstArg);
29
+ const bindings = typeof firstArg === 'object' && firstArg !== null && 'values' in firstArg
30
+ ? (firstArg as { values?: unknown[] }).values
31
+ : undefined;
32
+
33
+ const result = originalQuery.apply(this, args);
34
+ const onDone = () => {
35
+ const duration = performance.now() - start;
36
+ const requestId = getRequestId();
37
+ if (requestId) {
38
+ core.addQuery(requestId, {
39
+ query: queryText,
40
+ bindings,
41
+ duration,
42
+ connection: 'pg',
43
+ });
44
+ }
45
+ };
46
+ if (result && typeof (result as { then?: unknown }).then === 'function') (result as Promise<unknown>).finally(onDone);
47
+ else setTimeout(onDone, 0);
48
+ return result;
49
+ };
50
+
51
+ return function restore() {
52
+ if (Client.prototype.query === originalQuery) return;
53
+ Client.prototype.query = originalQuery;
54
+ restored = true;
55
+ };
56
+ }
@@ -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": "../core" }, { "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,25 @@
1
+ import { ClockworkPlugin } from '@adjedaini/clockwork-core';
2
+ export { ClockworkPlugin, IPluginContext } from '@adjedaini/clockwork-core';
3
+
4
+ /**
5
+ * Pino plugin: intercepts pino logger output and attaches to current request.
6
+ * Only applied if the 'pino' module is installed.
7
+ */
8
+
9
+ declare const pinoPlugin: ClockworkPlugin;
10
+
11
+ /**
12
+ * Winston plugin: intercepts winston logger output and attaches to current request.
13
+ * Only applied if the 'winston' module is installed.
14
+ */
15
+
16
+ declare const winstonPlugin: ClockworkPlugin;
17
+
18
+ /**
19
+ * @adjedaini/clockwork-log-interceptor
20
+ * Optional log library instrumentation (pino, winston). Implements ClockworkPlugin.
21
+ */
22
+
23
+ declare const defaultLogPlugins: ClockworkPlugin[];
24
+
25
+ export { defaultLogPlugins, pinoPlugin, winstonPlugin };
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ defaultLogPlugins: () => defaultLogPlugins,
34
+ pinoPlugin: () => pinoPlugin,
35
+ winstonPlugin: () => winstonPlugin
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+
39
+ // src/pino.ts
40
+ var LEVEL_MAP = {
41
+ trace: "debug",
42
+ debug: "debug",
43
+ info: "info",
44
+ warn: "warning",
45
+ warning: "warning",
46
+ error: "error",
47
+ fatal: "error"
48
+ };
49
+ function wrapPino(ctx) {
50
+ let pinoId;
51
+ try {
52
+ pinoId = require.resolve("pino");
53
+ } catch {
54
+ return () => {
55
+ };
56
+ }
57
+ const mod = require.cache[pinoId];
58
+ if (!mod?.exports || typeof mod.exports !== "function") return () => {
59
+ };
60
+ const original = mod.exports;
61
+ function wrapLogger(logger) {
62
+ const levels = ["trace", "debug", "info", "warn", "error", "fatal"];
63
+ const wrapped = { ...logger };
64
+ for (const level of levels) {
65
+ const orig = logger[level];
66
+ if (typeof orig !== "function") continue;
67
+ wrapped[level] = function(...args) {
68
+ const requestId = ctx.getRequestId();
69
+ if (requestId) {
70
+ const msg = typeof args[0] === "string" ? args[0] : JSON.stringify(args[0] ?? "");
71
+ const levelMapped = LEVEL_MAP[level] ?? "info";
72
+ ctx.core.captureNativeLog(requestId, levelMapped, msg, void 0);
73
+ }
74
+ return orig.apply(this, args);
75
+ };
76
+ }
77
+ if (typeof logger.child === "function") {
78
+ const origChild = logger.child.bind(logger);
79
+ wrapped.child = function(bindings) {
80
+ return wrapLogger(origChild(bindings));
81
+ };
82
+ }
83
+ return wrapped;
84
+ }
85
+ mod.exports = function(opts) {
86
+ return wrapLogger(original(opts));
87
+ };
88
+ return function restore() {
89
+ mod.exports = original;
90
+ };
91
+ }
92
+ var pinoPlugin = {
93
+ name: "pino",
94
+ install: wrapPino
95
+ };
96
+
97
+ // src/winston.ts
98
+ var LEVEL_MAP2 = {
99
+ error: "error",
100
+ warn: "warning",
101
+ warning: "warning",
102
+ info: "info",
103
+ http: "info",
104
+ verbose: "debug",
105
+ debug: "debug",
106
+ silly: "debug"
107
+ };
108
+ function wrapWinston(ctx) {
109
+ let winstonId;
110
+ try {
111
+ winstonId = require.resolve("winston");
112
+ } catch {
113
+ return () => {
114
+ };
115
+ }
116
+ const mod = require.cache[winstonId];
117
+ if (!mod?.exports?.createLogger) return () => {
118
+ };
119
+ const winston = mod.exports;
120
+ const originalCreateLogger = winston.createLogger.bind(winston);
121
+ winston.createLogger = function(opts) {
122
+ const logger = originalCreateLogger(opts);
123
+ const origLog = logger.log?.bind(logger);
124
+ if (typeof origLog !== "function") return logger;
125
+ logger.log = function(levelOrMeta, msg, ...args) {
126
+ const requestId = ctx.getRequestId();
127
+ if (requestId) {
128
+ const level = typeof levelOrMeta === "string" ? levelOrMeta : "info";
129
+ const message = typeof msg === "string" ? msg : typeof levelOrMeta === "object" && levelOrMeta !== null && "message" in levelOrMeta ? String(levelOrMeta.message) : String(msg ?? levelOrMeta);
130
+ const levelMapped = LEVEL_MAP2[level] ?? "info";
131
+ ctx.core.captureNativeLog(requestId, levelMapped, message, void 0);
132
+ }
133
+ return origLog(levelOrMeta, msg, ...args);
134
+ };
135
+ return logger;
136
+ };
137
+ return function restore() {
138
+ winston.createLogger = originalCreateLogger;
139
+ };
140
+ }
141
+ var winstonPlugin = {
142
+ name: "winston",
143
+ install: wrapWinston
144
+ };
145
+
146
+ // src/index.ts
147
+ var defaultLogPlugins = [pinoPlugin, winstonPlugin];
148
+ // Annotate the CommonJS export names for ESM import in node:
149
+ 0 && (module.exports = {
150
+ defaultLogPlugins,
151
+ pinoPlugin,
152
+ winstonPlugin
153
+ });
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@adjedaini/clockwork-log-interceptor",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": { "build": "tsup" },
8
+ "dependencies": {
9
+ "@adjedaini/clockwork-core": "*",
10
+ "@adjedaini/clockwork-shared": "*"
11
+ },
12
+ "devDependencies": {
13
+ "tsup": "^8.0.0",
14
+ "typescript": "^5.5.0"
15
+ }
16
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @adjedaini/clockwork-log-interceptor
3
+ * Optional log library instrumentation (pino, winston). Implements ClockworkPlugin.
4
+ */
5
+
6
+ import type { ClockworkPlugin } from '@adjedaini/clockwork-core';
7
+ import { pinoPlugin } from './pino';
8
+ import { winstonPlugin } from './winston';
9
+
10
+ export { pinoPlugin, winstonPlugin };
11
+
12
+ export const defaultLogPlugins: ClockworkPlugin[] = [pinoPlugin, winstonPlugin];
13
+
14
+ export type { ClockworkPlugin, IPluginContext } from '@adjedaini/clockwork-core';
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Pino plugin: intercepts pino logger output and attaches to current request.
3
+ * Only applied if the 'pino' module is installed.
4
+ */
5
+
6
+ import type { ClockworkPlugin, IPluginContext } from '@adjedaini/clockwork-core';
7
+ import type { LogData } from '@adjedaini/clockwork-shared';
8
+
9
+ const LEVEL_MAP: Record<string, LogData['level']> = {
10
+ trace: 'debug',
11
+ debug: 'debug',
12
+ info: 'info',
13
+ warn: 'warning',
14
+ warning: 'warning',
15
+ error: 'error',
16
+ fatal: 'error',
17
+ };
18
+
19
+ function wrapPino(ctx: IPluginContext): () => void {
20
+ let pinoId: string;
21
+ try {
22
+ pinoId = require.resolve('pino');
23
+ } catch {
24
+ return () => {};
25
+ }
26
+ const mod = require.cache[pinoId] as { exports: (opts?: unknown) => PinoLogger } | undefined;
27
+ if (!mod?.exports || typeof mod.exports !== 'function') return () => {};
28
+
29
+ const original = mod.exports;
30
+
31
+ function wrapLogger(logger: PinoLogger): PinoLogger {
32
+ const levels = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'] as const;
33
+ const wrapped = { ...logger };
34
+ for (const level of levels) {
35
+ const orig = logger[level];
36
+ if (typeof orig !== 'function') continue;
37
+ (wrapped as Record<string, unknown>)[level] = function (this: PinoLogger, ...args: unknown[]) {
38
+ const requestId = ctx.getRequestId();
39
+ if (requestId) {
40
+ const msg = typeof args[0] === 'string' ? args[0] : JSON.stringify(args[0] ?? '');
41
+ const levelMapped = LEVEL_MAP[level] ?? 'info';
42
+ ctx.core.captureNativeLog(requestId, levelMapped, msg, undefined);
43
+ }
44
+ return (orig as (...a: unknown[]) => unknown).apply(this, args);
45
+ };
46
+ }
47
+ if (typeof logger.child === 'function') {
48
+ const origChild = logger.child.bind(logger);
49
+ wrapped.child = function (bindings: unknown) {
50
+ return wrapLogger(origChild(bindings));
51
+ };
52
+ }
53
+ return wrapped as PinoLogger;
54
+ }
55
+
56
+ mod.exports = function (opts?: unknown) {
57
+ return wrapLogger(original(opts));
58
+ };
59
+
60
+ return function restore() {
61
+ mod.exports = original;
62
+ };
63
+ }
64
+
65
+ interface PinoLogger {
66
+ trace?(...args: unknown[]): void;
67
+ debug?(...args: unknown[]): void;
68
+ info?(...args: unknown[]): void;
69
+ warn?(...args: unknown[]): void;
70
+ error?(...args: unknown[]): void;
71
+ fatal?(...args: unknown[]): void;
72
+ child?(bindings: unknown): PinoLogger;
73
+ }
74
+
75
+ export const pinoPlugin: ClockworkPlugin = {
76
+ name: 'pino',
77
+ install: wrapPino,
78
+ };