@loggerjs/node 0.5.0 → 0.5.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 (102) hide show
  1. package/README.md +5 -1
  2. package/dist/bullmq-integration.cjs +169 -0
  3. package/dist/bullmq-integration.cjs.map +1 -0
  4. package/dist/bullmq-integration.js +168 -0
  5. package/dist/bullmq-integration.js.map +1 -0
  6. package/dist/cli-integration.cjs +116 -0
  7. package/dist/cli-integration.cjs.map +1 -0
  8. package/dist/cli-integration.js +115 -0
  9. package/dist/cli-integration.js.map +1 -0
  10. package/dist/context.cjs +37 -0
  11. package/dist/context.cjs.map +1 -0
  12. package/dist/context.js +35 -0
  13. package/dist/context.js.map +1 -0
  14. package/dist/database-integration.cjs +128 -0
  15. package/dist/database-integration.cjs.map +1 -0
  16. package/dist/database-integration.js +127 -0
  17. package/dist/database-integration.js.map +1 -0
  18. package/dist/diagnostics-channel-integration.cjs +66 -0
  19. package/dist/diagnostics-channel-integration.cjs.map +1 -0
  20. package/dist/diagnostics-channel-integration.js +65 -0
  21. package/dist/diagnostics-channel-integration.js.map +1 -0
  22. package/dist/express-integration.cjs +130 -0
  23. package/dist/express-integration.cjs.map +1 -0
  24. package/dist/express-integration.js +129 -0
  25. package/dist/express-integration.js.map +1 -0
  26. package/dist/fastify-integration.cjs +120 -0
  27. package/dist/fastify-integration.cjs.map +1 -0
  28. package/dist/fastify-integration.js +119 -0
  29. package/dist/fastify-integration.js.map +1 -0
  30. package/dist/file-transport.cjs +260 -0
  31. package/dist/file-transport.cjs.map +1 -0
  32. package/dist/file-transport.js +259 -0
  33. package/dist/file-transport.js.map +1 -0
  34. package/dist/hapi-integration.cjs +61 -0
  35. package/dist/hapi-integration.cjs.map +1 -0
  36. package/dist/hapi-integration.js +60 -0
  37. package/dist/hapi-integration.js.map +1 -0
  38. package/dist/http-transport.cjs +55 -0
  39. package/dist/http-transport.cjs.map +1 -0
  40. package/dist/http-transport.js +54 -0
  41. package/dist/http-transport.js.map +1 -0
  42. package/dist/koa-integration.cjs +57 -0
  43. package/dist/koa-integration.cjs.map +1 -0
  44. package/dist/koa-integration.js +56 -0
  45. package/dist/koa-integration.js.map +1 -0
  46. package/dist/logger-diagnostics.cjs +46 -0
  47. package/dist/logger-diagnostics.cjs.map +1 -0
  48. package/dist/logger-diagnostics.js +45 -0
  49. package/dist/logger-diagnostics.js.map +1 -0
  50. package/dist/nest-integration.cjs +138 -0
  51. package/dist/nest-integration.cjs.map +1 -0
  52. package/dist/nest-integration.js +137 -0
  53. package/dist/nest-integration.js.map +1 -0
  54. package/dist/node-fetch-integration.cjs +113 -0
  55. package/dist/node-fetch-integration.cjs.map +1 -0
  56. package/dist/node-fetch-integration.js +112 -0
  57. package/dist/node-fetch-integration.js.map +1 -0
  58. package/dist/node-http-client-integration.cjs +192 -0
  59. package/dist/node-http-client-integration.cjs.map +1 -0
  60. package/dist/node-http-client-integration.js +192 -0
  61. package/dist/node-http-client-integration.js.map +1 -0
  62. package/dist/payload-transforms.cjs +29 -0
  63. package/dist/payload-transforms.cjs.map +1 -0
  64. package/dist/payload-transforms.js +28 -0
  65. package/dist/payload-transforms.js.map +1 -0
  66. package/dist/prisma-integration.cjs +150 -0
  67. package/dist/prisma-integration.cjs.map +1 -0
  68. package/dist/prisma-integration.js +149 -0
  69. package/dist/prisma-integration.js.map +1 -0
  70. package/dist/process-integration.cjs +134 -0
  71. package/dist/process-integration.cjs.map +1 -0
  72. package/dist/process-integration.js +133 -0
  73. package/dist/process-integration.js.map +1 -0
  74. package/dist/queue-integration.cjs +148 -0
  75. package/dist/queue-integration.cjs.map +1 -0
  76. package/dist/queue-integration.js +147 -0
  77. package/dist/queue-integration.js.map +1 -0
  78. package/dist/redis-integration.cjs +154 -0
  79. package/dist/redis-integration.cjs.map +1 -0
  80. package/dist/redis-integration.js +153 -0
  81. package/dist/redis-integration.js.map +1 -0
  82. package/dist/rotating-file-transport.cjs +318 -0
  83. package/dist/rotating-file-transport.cjs.map +1 -0
  84. package/dist/rotating-file-transport.js +317 -0
  85. package/dist/rotating-file-transport.js.map +1 -0
  86. package/dist/serverless-integration.cjs +104 -0
  87. package/dist/serverless-integration.cjs.map +1 -0
  88. package/dist/serverless-integration.js +103 -0
  89. package/dist/serverless-integration.js.map +1 -0
  90. package/dist/stdout-transport.cjs +197 -0
  91. package/dist/stdout-transport.cjs.map +1 -0
  92. package/dist/stdout-transport.js +195 -0
  93. package/dist/stdout-transport.js.map +1 -0
  94. package/dist/syslog-transport.cjs +135 -0
  95. package/dist/syslog-transport.cjs.map +1 -0
  96. package/dist/syslog-transport.js +133 -0
  97. package/dist/syslog-transport.js.map +1 -0
  98. package/dist/worker-transport.cjs +285 -0
  99. package/dist/worker-transport.cjs.map +1 -0
  100. package/dist/worker-transport.js +284 -0
  101. package/dist/worker-transport.js.map +1 -0
  102. package/package.json +104 -77
package/README.md CHANGED
@@ -4,10 +4,14 @@
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/@loggerjs/node.svg)](https://www.npmjs.com/package/@loggerjs/node)
6
6
  [![license](https://img.shields.io/npm/l/@loggerjs/node)](../../LICENSE)
7
- [![Node](https://img.shields.io/badge/Node-%E2%89%A522.13-339933?logo=node.js&logoColor=white)](package.json)
7
+ [![Node runtime](https://img.shields.io/badge/runtime_Node-%E2%89%A520.19-339933?logo=node.js&logoColor=white)](../../.github/workflows/ci.yml)
8
8
 
9
9
  The Node platform package for [LoggerJS](../../README.md). It re-exports the entire `@loggerjs/core` API and adds stdout/stderr/file/HTTP/syslog/worker transports, an AsyncLocalStorage context bridge, and integrations that turn process crashes, HTTP frameworks, clients, and queues into structured logs — all opt-in.
10
10
 
11
+ `@loggerjs/node` is smoke-tested from packed packages on Node 20.19.0, 22, and
12
+ 24. The repository development toolchain uses Node >=22.13.0; that root
13
+ requirement does not raise the published package runtime floor.
14
+
11
15
  ## Install
12
16
 
13
17
  ```bash
@@ -0,0 +1,169 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _loggerjs_core = require("@loggerjs/core");
3
+ //#region src/queue-integration.ts
4
+ const defaultMethods = [
5
+ "add",
6
+ "ack",
7
+ "consume",
8
+ "dequeue",
9
+ "nack",
10
+ "process",
11
+ "publish",
12
+ "receive",
13
+ "send",
14
+ "sendToQueue"
15
+ ];
16
+ const defaultRandom = () => Math.random();
17
+ function defaultLevel(_durationMs, error) {
18
+ return error ? "error" : "debug";
19
+ }
20
+ function isPromiseLike(value) {
21
+ return typeof value === "object" && value !== null && typeof value.then === "function";
22
+ }
23
+ function defaultOperation(method) {
24
+ switch (method) {
25
+ case "add":
26
+ case "publish":
27
+ case "send":
28
+ case "sendToQueue": return "publish";
29
+ case "consume":
30
+ case "dequeue":
31
+ case "process":
32
+ case "receive": return "consume";
33
+ case "ack": return "ack";
34
+ case "nack": return "nack";
35
+ default: return "other";
36
+ }
37
+ }
38
+ function defaultPayload(args) {
39
+ return typeof args[0] === "string" && args.length > 1 ? args[1] : args[0];
40
+ }
41
+ function defaultMessageId(args) {
42
+ const payload = defaultPayload(args);
43
+ if (typeof payload !== "object" || payload === null) return void 0;
44
+ const value = payload.messageId ?? payload.id;
45
+ return value === void 0 ? void 0 : String(value);
46
+ }
47
+ function payloadFor(args, method, options) {
48
+ if (!options.capturePayload) return void 0;
49
+ const payload = options.getPayload?.(args, method) ?? defaultPayload(args);
50
+ return payload === void 0 ? void 0 : (0, _loggerjs_core.normalizeValue)(payload, {
51
+ maxDepth: 4,
52
+ maxObjectKeys: 80
53
+ });
54
+ }
55
+ function queueIntegration(options = {}) {
56
+ const targets = options.targets ?? (options.client ? [{
57
+ client: options.client,
58
+ name: options.name,
59
+ system: options.system,
60
+ queueName: options.queueName,
61
+ methods: options.methods
62
+ }] : []);
63
+ const captureAll = options.captureAll ?? options.captureSuccessful ?? false;
64
+ const sampleRate = options.sampleRate ?? 1;
65
+ const random = options.random ?? defaultRandom;
66
+ const levelFor = options.level ?? defaultLevel;
67
+ const shouldCapture = (durationMs, error) => {
68
+ if (error) return true;
69
+ if (options.minDurationMs !== void 0 && durationMs >= options.minDurationMs) return true;
70
+ if (!captureAll) return false;
71
+ return sampleRate >= 1 || random() < sampleRate;
72
+ };
73
+ return {
74
+ name: "queue",
75
+ setup(api) {
76
+ const capture = api.guard((input) => api.capture(input));
77
+ const disposers = [];
78
+ let disposed = false;
79
+ const captureResult = (info, started, args, error) => {
80
+ const durationMs = Date.now() - started;
81
+ if (disposed || !shouldCapture(durationMs, error)) return;
82
+ capture({
83
+ level: levelFor(durationMs, error, info),
84
+ message: error ? `Queue error ${info.operation} ${info.queueName ?? info.method}` : `Queue ${info.operation} ${info.queueName ?? info.method}`,
85
+ error,
86
+ props: { queue: {
87
+ kind: info.target,
88
+ system: info.system,
89
+ queueName: info.queueName,
90
+ method: info.method,
91
+ operation: info.operation,
92
+ durationMs,
93
+ messageId: options.getMessageId?.(args, info.method) ?? defaultMessageId(args),
94
+ payload: payloadFor(args, info.method, options)
95
+ } }
96
+ });
97
+ };
98
+ for (const target of targets) {
99
+ const methods = target.methods ?? options.methods ?? defaultMethods;
100
+ for (const method of methods) {
101
+ const original = target.client[method];
102
+ if (typeof original !== "function") continue;
103
+ const originalMethod = original;
104
+ const targetName = target.name ?? options.name ?? "queue";
105
+ const system = target.system ?? options.system;
106
+ target.client[method] = function wrappedQueueMethod(...args) {
107
+ const started = Date.now();
108
+ const operation = options.getOperation?.(method, args) ?? defaultOperation(method);
109
+ const info = {
110
+ target: targetName,
111
+ system,
112
+ queueName: options.getQueueName?.(args, method) ?? target.queueName ?? options.queueName ?? (typeof args[0] === "string" ? args[0] : void 0),
113
+ method,
114
+ operation
115
+ };
116
+ try {
117
+ const result = originalMethod.apply(this, args);
118
+ if (isPromiseLike(result)) return result.then((value) => {
119
+ captureResult(info, started, args, void 0);
120
+ return value;
121
+ }, (error) => {
122
+ captureResult(info, started, args, error);
123
+ throw error;
124
+ });
125
+ captureResult(info, started, args, void 0);
126
+ return result;
127
+ } catch (error) {
128
+ captureResult(info, started, args, error);
129
+ throw error;
130
+ }
131
+ };
132
+ disposers.push(() => {
133
+ target.client[method] = originalMethod;
134
+ });
135
+ }
136
+ }
137
+ return () => {
138
+ if (disposed) return;
139
+ disposed = true;
140
+ for (const dispose of disposers) dispose();
141
+ };
142
+ }
143
+ };
144
+ }
145
+ //#endregion
146
+ //#region src/bullmq-integration.ts
147
+ const bullMqMethods = [
148
+ "add",
149
+ "addBulk",
150
+ "process"
151
+ ];
152
+ function queueName(args, fallback) {
153
+ const first = args[0];
154
+ return typeof first === "string" ? first : fallback;
155
+ }
156
+ function bullMqIntegration(options) {
157
+ return queueIntegration({
158
+ ...options,
159
+ name: options.name ?? "bullmq",
160
+ system: "bullmq",
161
+ methods: options.methods ?? bullMqMethods,
162
+ queueName: options.queueName ?? options.client.name,
163
+ getQueueName: (args) => queueName(args, options.queueName ?? options.client.name)
164
+ });
165
+ }
166
+ //#endregion
167
+ exports.bullMqIntegration = bullMqIntegration;
168
+
169
+ //# sourceMappingURL=bullmq-integration.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bullmq-integration.cjs","names":[],"sources":["../src/queue-integration.ts","../src/bullmq-integration.ts"],"sourcesContent":["import {\n normalizeValue,\n type CaptureInput,\n type Integration,\n type IntegrationSetupContext,\n type LoggerLevel,\n} from \"@loggerjs/core\";\n\nexport type QueueOperation = \"publish\" | \"consume\" | \"ack\" | \"nack\" | \"other\";\n\nexport interface QueueClientLike {\n [method: string]: unknown;\n}\n\nexport interface QueueIntegrationTarget {\n client: QueueClientLike;\n name?: string;\n system?: string;\n queueName?: string;\n methods?: readonly string[];\n}\n\nexport interface QueueOperationInfo {\n target: string;\n system?: string;\n queueName?: string;\n method: string;\n operation: QueueOperation;\n}\n\nexport interface QueueIntegrationOptions {\n client?: QueueClientLike;\n targets?: readonly QueueIntegrationTarget[];\n name?: string;\n system?: string;\n queueName?: string;\n methods?: readonly string[];\n captureAll?: boolean;\n captureSuccessful?: boolean;\n minDurationMs?: number;\n sampleRate?: number;\n random?: () => number;\n capturePayload?: boolean;\n getOperation?: (method: string, args: readonly unknown[]) => QueueOperation;\n getQueueName?: (args: readonly unknown[], method: string) => string | undefined;\n getMessageId?: (args: readonly unknown[], method: string) => string | undefined;\n getPayload?: (args: readonly unknown[], method: string) => unknown;\n level?: (durationMs: number, error: unknown, info: QueueOperationInfo) => LoggerLevel;\n}\n\ntype QueueMethod = (this: unknown, ...args: unknown[]) => unknown;\n\nconst defaultMethods = [\n \"add\",\n \"ack\",\n \"consume\",\n \"dequeue\",\n \"nack\",\n \"process\",\n \"publish\",\n \"receive\",\n \"send\",\n \"sendToQueue\",\n] as const;\nconst defaultRandom = () => Math.random();\n\nfunction defaultLevel(_durationMs: number, error: unknown): LoggerLevel {\n return error ? \"error\" : \"debug\";\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\nfunction defaultOperation(method: string): QueueOperation {\n switch (method) {\n case \"add\":\n case \"publish\":\n case \"send\":\n case \"sendToQueue\":\n return \"publish\";\n case \"consume\":\n case \"dequeue\":\n case \"process\":\n case \"receive\":\n return \"consume\";\n case \"ack\":\n return \"ack\";\n case \"nack\":\n return \"nack\";\n default:\n return \"other\";\n }\n}\n\nfunction defaultPayload(args: readonly unknown[]) {\n return typeof args[0] === \"string\" && args.length > 1 ? args[1] : args[0];\n}\n\nfunction defaultMessageId(args: readonly unknown[]) {\n const payload = defaultPayload(args);\n if (typeof payload !== \"object\" || payload === null) return undefined;\n const value =\n (payload as { id?: unknown; messageId?: unknown }).messageId ??\n (payload as { id?: unknown }).id;\n return value === undefined ? undefined : String(value);\n}\n\nfunction payloadFor(args: readonly unknown[], method: string, options: QueueIntegrationOptions) {\n if (!options.capturePayload) return undefined;\n const payload = options.getPayload?.(args, method) ?? defaultPayload(args);\n return payload === undefined\n ? undefined\n : normalizeValue(payload, { maxDepth: 4, maxObjectKeys: 80 });\n}\n\nexport function queueIntegration(options: QueueIntegrationOptions = {}): Integration {\n const targets =\n options.targets ??\n (options.client\n ? [\n {\n client: options.client,\n name: options.name,\n system: options.system,\n queueName: options.queueName,\n methods: options.methods,\n },\n ]\n : []);\n const captureAll = options.captureAll ?? options.captureSuccessful ?? false;\n const sampleRate = options.sampleRate ?? 1;\n const random = options.random ?? defaultRandom;\n const levelFor = options.level ?? defaultLevel;\n\n const shouldCapture = (durationMs: number, error: unknown) => {\n if (error) return true;\n if (options.minDurationMs !== undefined && durationMs >= options.minDurationMs) return true;\n if (!captureAll) return false;\n return sampleRate >= 1 || random() < sampleRate;\n };\n\n return {\n name: \"queue\",\n setup(api: IntegrationSetupContext) {\n const capture = api.guard((input: CaptureInput) => api.capture(input));\n const disposers: Array<() => void> = [];\n let disposed = false;\n\n const captureResult = (\n info: QueueOperationInfo,\n started: number,\n args: readonly unknown[],\n error: unknown,\n ) => {\n const durationMs = Date.now() - started;\n if (disposed || !shouldCapture(durationMs, error)) return;\n capture({\n level: levelFor(durationMs, error, info),\n message: error\n ? `Queue error ${info.operation} ${info.queueName ?? info.method}`\n : `Queue ${info.operation} ${info.queueName ?? info.method}`,\n error,\n props: {\n queue: {\n kind: info.target,\n system: info.system,\n queueName: info.queueName,\n method: info.method,\n operation: info.operation,\n durationMs,\n messageId: options.getMessageId?.(args, info.method) ?? defaultMessageId(args),\n payload: payloadFor(args, info.method, options),\n },\n },\n });\n };\n\n for (const target of targets) {\n const methods = target.methods ?? options.methods ?? defaultMethods;\n for (const method of methods) {\n const original = target.client[method];\n if (typeof original !== \"function\") continue;\n const originalMethod = original as QueueMethod;\n const targetName = target.name ?? options.name ?? \"queue\";\n const system = target.system ?? options.system;\n\n target.client[method] = function wrappedQueueMethod(this: unknown, ...args: unknown[]) {\n const started = Date.now();\n const operation = options.getOperation?.(method, args) ?? defaultOperation(method);\n const info: QueueOperationInfo = {\n target: targetName,\n system,\n queueName:\n options.getQueueName?.(args, method) ??\n target.queueName ??\n options.queueName ??\n (typeof args[0] === \"string\" ? args[0] : undefined),\n method,\n operation,\n };\n try {\n const result = originalMethod.apply(this, args);\n if (isPromiseLike(result)) {\n return result.then(\n (value) => {\n captureResult(info, started, args, undefined);\n return value;\n },\n (error) => {\n captureResult(info, started, args, error);\n throw error;\n },\n );\n }\n captureResult(info, started, args, undefined);\n return result;\n } catch (error) {\n captureResult(info, started, args, error);\n throw error;\n }\n };\n\n disposers.push(() => {\n target.client[method] = originalMethod;\n });\n }\n }\n\n return () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers) dispose();\n };\n },\n };\n}\n","import {\n queueIntegration,\n type QueueClientLike,\n type QueueIntegrationOptions,\n} from \"./queue-integration\";\n\nexport interface BullMqIntegrationOptions extends Omit<\n QueueIntegrationOptions,\n \"client\" | \"system\" | \"methods\" | \"getQueueName\"\n> {\n client: QueueClientLike & { name?: string };\n methods?: readonly string[];\n}\n\nconst bullMqMethods = [\"add\", \"addBulk\", \"process\"] as const;\n\nfunction queueName(args: readonly unknown[], fallback: string | undefined) {\n const first = args[0];\n return typeof first === \"string\" ? first : fallback;\n}\n\nexport function bullMqIntegration(options: BullMqIntegrationOptions) {\n return queueIntegration({\n ...options,\n name: options.name ?? \"bullmq\",\n system: \"bullmq\",\n methods: options.methods ?? bullMqMethods,\n queueName: options.queueName ?? options.client.name,\n getQueueName: (args) => queueName(args, options.queueName ?? options.client.name),\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ import { normalizeValue } from "@loggerjs/core";
2
+ //#region src/queue-integration.ts
3
+ const defaultMethods = [
4
+ "add",
5
+ "ack",
6
+ "consume",
7
+ "dequeue",
8
+ "nack",
9
+ "process",
10
+ "publish",
11
+ "receive",
12
+ "send",
13
+ "sendToQueue"
14
+ ];
15
+ const defaultRandom = () => Math.random();
16
+ function defaultLevel(_durationMs, error) {
17
+ return error ? "error" : "debug";
18
+ }
19
+ function isPromiseLike(value) {
20
+ return typeof value === "object" && value !== null && typeof value.then === "function";
21
+ }
22
+ function defaultOperation(method) {
23
+ switch (method) {
24
+ case "add":
25
+ case "publish":
26
+ case "send":
27
+ case "sendToQueue": return "publish";
28
+ case "consume":
29
+ case "dequeue":
30
+ case "process":
31
+ case "receive": return "consume";
32
+ case "ack": return "ack";
33
+ case "nack": return "nack";
34
+ default: return "other";
35
+ }
36
+ }
37
+ function defaultPayload(args) {
38
+ return typeof args[0] === "string" && args.length > 1 ? args[1] : args[0];
39
+ }
40
+ function defaultMessageId(args) {
41
+ const payload = defaultPayload(args);
42
+ if (typeof payload !== "object" || payload === null) return void 0;
43
+ const value = payload.messageId ?? payload.id;
44
+ return value === void 0 ? void 0 : String(value);
45
+ }
46
+ function payloadFor(args, method, options) {
47
+ if (!options.capturePayload) return void 0;
48
+ const payload = options.getPayload?.(args, method) ?? defaultPayload(args);
49
+ return payload === void 0 ? void 0 : normalizeValue(payload, {
50
+ maxDepth: 4,
51
+ maxObjectKeys: 80
52
+ });
53
+ }
54
+ function queueIntegration(options = {}) {
55
+ const targets = options.targets ?? (options.client ? [{
56
+ client: options.client,
57
+ name: options.name,
58
+ system: options.system,
59
+ queueName: options.queueName,
60
+ methods: options.methods
61
+ }] : []);
62
+ const captureAll = options.captureAll ?? options.captureSuccessful ?? false;
63
+ const sampleRate = options.sampleRate ?? 1;
64
+ const random = options.random ?? defaultRandom;
65
+ const levelFor = options.level ?? defaultLevel;
66
+ const shouldCapture = (durationMs, error) => {
67
+ if (error) return true;
68
+ if (options.minDurationMs !== void 0 && durationMs >= options.minDurationMs) return true;
69
+ if (!captureAll) return false;
70
+ return sampleRate >= 1 || random() < sampleRate;
71
+ };
72
+ return {
73
+ name: "queue",
74
+ setup(api) {
75
+ const capture = api.guard((input) => api.capture(input));
76
+ const disposers = [];
77
+ let disposed = false;
78
+ const captureResult = (info, started, args, error) => {
79
+ const durationMs = Date.now() - started;
80
+ if (disposed || !shouldCapture(durationMs, error)) return;
81
+ capture({
82
+ level: levelFor(durationMs, error, info),
83
+ message: error ? `Queue error ${info.operation} ${info.queueName ?? info.method}` : `Queue ${info.operation} ${info.queueName ?? info.method}`,
84
+ error,
85
+ props: { queue: {
86
+ kind: info.target,
87
+ system: info.system,
88
+ queueName: info.queueName,
89
+ method: info.method,
90
+ operation: info.operation,
91
+ durationMs,
92
+ messageId: options.getMessageId?.(args, info.method) ?? defaultMessageId(args),
93
+ payload: payloadFor(args, info.method, options)
94
+ } }
95
+ });
96
+ };
97
+ for (const target of targets) {
98
+ const methods = target.methods ?? options.methods ?? defaultMethods;
99
+ for (const method of methods) {
100
+ const original = target.client[method];
101
+ if (typeof original !== "function") continue;
102
+ const originalMethod = original;
103
+ const targetName = target.name ?? options.name ?? "queue";
104
+ const system = target.system ?? options.system;
105
+ target.client[method] = function wrappedQueueMethod(...args) {
106
+ const started = Date.now();
107
+ const operation = options.getOperation?.(method, args) ?? defaultOperation(method);
108
+ const info = {
109
+ target: targetName,
110
+ system,
111
+ queueName: options.getQueueName?.(args, method) ?? target.queueName ?? options.queueName ?? (typeof args[0] === "string" ? args[0] : void 0),
112
+ method,
113
+ operation
114
+ };
115
+ try {
116
+ const result = originalMethod.apply(this, args);
117
+ if (isPromiseLike(result)) return result.then((value) => {
118
+ captureResult(info, started, args, void 0);
119
+ return value;
120
+ }, (error) => {
121
+ captureResult(info, started, args, error);
122
+ throw error;
123
+ });
124
+ captureResult(info, started, args, void 0);
125
+ return result;
126
+ } catch (error) {
127
+ captureResult(info, started, args, error);
128
+ throw error;
129
+ }
130
+ };
131
+ disposers.push(() => {
132
+ target.client[method] = originalMethod;
133
+ });
134
+ }
135
+ }
136
+ return () => {
137
+ if (disposed) return;
138
+ disposed = true;
139
+ for (const dispose of disposers) dispose();
140
+ };
141
+ }
142
+ };
143
+ }
144
+ //#endregion
145
+ //#region src/bullmq-integration.ts
146
+ const bullMqMethods = [
147
+ "add",
148
+ "addBulk",
149
+ "process"
150
+ ];
151
+ function queueName(args, fallback) {
152
+ const first = args[0];
153
+ return typeof first === "string" ? first : fallback;
154
+ }
155
+ function bullMqIntegration(options) {
156
+ return queueIntegration({
157
+ ...options,
158
+ name: options.name ?? "bullmq",
159
+ system: "bullmq",
160
+ methods: options.methods ?? bullMqMethods,
161
+ queueName: options.queueName ?? options.client.name,
162
+ getQueueName: (args) => queueName(args, options.queueName ?? options.client.name)
163
+ });
164
+ }
165
+ //#endregion
166
+ export { bullMqIntegration };
167
+
168
+ //# sourceMappingURL=bullmq-integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bullmq-integration.js","names":[],"sources":["../src/queue-integration.ts","../src/bullmq-integration.ts"],"sourcesContent":["import {\n normalizeValue,\n type CaptureInput,\n type Integration,\n type IntegrationSetupContext,\n type LoggerLevel,\n} from \"@loggerjs/core\";\n\nexport type QueueOperation = \"publish\" | \"consume\" | \"ack\" | \"nack\" | \"other\";\n\nexport interface QueueClientLike {\n [method: string]: unknown;\n}\n\nexport interface QueueIntegrationTarget {\n client: QueueClientLike;\n name?: string;\n system?: string;\n queueName?: string;\n methods?: readonly string[];\n}\n\nexport interface QueueOperationInfo {\n target: string;\n system?: string;\n queueName?: string;\n method: string;\n operation: QueueOperation;\n}\n\nexport interface QueueIntegrationOptions {\n client?: QueueClientLike;\n targets?: readonly QueueIntegrationTarget[];\n name?: string;\n system?: string;\n queueName?: string;\n methods?: readonly string[];\n captureAll?: boolean;\n captureSuccessful?: boolean;\n minDurationMs?: number;\n sampleRate?: number;\n random?: () => number;\n capturePayload?: boolean;\n getOperation?: (method: string, args: readonly unknown[]) => QueueOperation;\n getQueueName?: (args: readonly unknown[], method: string) => string | undefined;\n getMessageId?: (args: readonly unknown[], method: string) => string | undefined;\n getPayload?: (args: readonly unknown[], method: string) => unknown;\n level?: (durationMs: number, error: unknown, info: QueueOperationInfo) => LoggerLevel;\n}\n\ntype QueueMethod = (this: unknown, ...args: unknown[]) => unknown;\n\nconst defaultMethods = [\n \"add\",\n \"ack\",\n \"consume\",\n \"dequeue\",\n \"nack\",\n \"process\",\n \"publish\",\n \"receive\",\n \"send\",\n \"sendToQueue\",\n] as const;\nconst defaultRandom = () => Math.random();\n\nfunction defaultLevel(_durationMs: number, error: unknown): LoggerLevel {\n return error ? \"error\" : \"debug\";\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\nfunction defaultOperation(method: string): QueueOperation {\n switch (method) {\n case \"add\":\n case \"publish\":\n case \"send\":\n case \"sendToQueue\":\n return \"publish\";\n case \"consume\":\n case \"dequeue\":\n case \"process\":\n case \"receive\":\n return \"consume\";\n case \"ack\":\n return \"ack\";\n case \"nack\":\n return \"nack\";\n default:\n return \"other\";\n }\n}\n\nfunction defaultPayload(args: readonly unknown[]) {\n return typeof args[0] === \"string\" && args.length > 1 ? args[1] : args[0];\n}\n\nfunction defaultMessageId(args: readonly unknown[]) {\n const payload = defaultPayload(args);\n if (typeof payload !== \"object\" || payload === null) return undefined;\n const value =\n (payload as { id?: unknown; messageId?: unknown }).messageId ??\n (payload as { id?: unknown }).id;\n return value === undefined ? undefined : String(value);\n}\n\nfunction payloadFor(args: readonly unknown[], method: string, options: QueueIntegrationOptions) {\n if (!options.capturePayload) return undefined;\n const payload = options.getPayload?.(args, method) ?? defaultPayload(args);\n return payload === undefined\n ? undefined\n : normalizeValue(payload, { maxDepth: 4, maxObjectKeys: 80 });\n}\n\nexport function queueIntegration(options: QueueIntegrationOptions = {}): Integration {\n const targets =\n options.targets ??\n (options.client\n ? [\n {\n client: options.client,\n name: options.name,\n system: options.system,\n queueName: options.queueName,\n methods: options.methods,\n },\n ]\n : []);\n const captureAll = options.captureAll ?? options.captureSuccessful ?? false;\n const sampleRate = options.sampleRate ?? 1;\n const random = options.random ?? defaultRandom;\n const levelFor = options.level ?? defaultLevel;\n\n const shouldCapture = (durationMs: number, error: unknown) => {\n if (error) return true;\n if (options.minDurationMs !== undefined && durationMs >= options.minDurationMs) return true;\n if (!captureAll) return false;\n return sampleRate >= 1 || random() < sampleRate;\n };\n\n return {\n name: \"queue\",\n setup(api: IntegrationSetupContext) {\n const capture = api.guard((input: CaptureInput) => api.capture(input));\n const disposers: Array<() => void> = [];\n let disposed = false;\n\n const captureResult = (\n info: QueueOperationInfo,\n started: number,\n args: readonly unknown[],\n error: unknown,\n ) => {\n const durationMs = Date.now() - started;\n if (disposed || !shouldCapture(durationMs, error)) return;\n capture({\n level: levelFor(durationMs, error, info),\n message: error\n ? `Queue error ${info.operation} ${info.queueName ?? info.method}`\n : `Queue ${info.operation} ${info.queueName ?? info.method}`,\n error,\n props: {\n queue: {\n kind: info.target,\n system: info.system,\n queueName: info.queueName,\n method: info.method,\n operation: info.operation,\n durationMs,\n messageId: options.getMessageId?.(args, info.method) ?? defaultMessageId(args),\n payload: payloadFor(args, info.method, options),\n },\n },\n });\n };\n\n for (const target of targets) {\n const methods = target.methods ?? options.methods ?? defaultMethods;\n for (const method of methods) {\n const original = target.client[method];\n if (typeof original !== \"function\") continue;\n const originalMethod = original as QueueMethod;\n const targetName = target.name ?? options.name ?? \"queue\";\n const system = target.system ?? options.system;\n\n target.client[method] = function wrappedQueueMethod(this: unknown, ...args: unknown[]) {\n const started = Date.now();\n const operation = options.getOperation?.(method, args) ?? defaultOperation(method);\n const info: QueueOperationInfo = {\n target: targetName,\n system,\n queueName:\n options.getQueueName?.(args, method) ??\n target.queueName ??\n options.queueName ??\n (typeof args[0] === \"string\" ? args[0] : undefined),\n method,\n operation,\n };\n try {\n const result = originalMethod.apply(this, args);\n if (isPromiseLike(result)) {\n return result.then(\n (value) => {\n captureResult(info, started, args, undefined);\n return value;\n },\n (error) => {\n captureResult(info, started, args, error);\n throw error;\n },\n );\n }\n captureResult(info, started, args, undefined);\n return result;\n } catch (error) {\n captureResult(info, started, args, error);\n throw error;\n }\n };\n\n disposers.push(() => {\n target.client[method] = originalMethod;\n });\n }\n }\n\n return () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers) dispose();\n };\n },\n };\n}\n","import {\n queueIntegration,\n type QueueClientLike,\n type QueueIntegrationOptions,\n} from \"./queue-integration\";\n\nexport interface BullMqIntegrationOptions extends Omit<\n QueueIntegrationOptions,\n \"client\" | \"system\" | \"methods\" | \"getQueueName\"\n> {\n client: QueueClientLike & { name?: string };\n methods?: readonly string[];\n}\n\nconst bullMqMethods = [\"add\", \"addBulk\", \"process\"] as const;\n\nfunction queueName(args: readonly unknown[], fallback: string | undefined) {\n const first = args[0];\n return typeof first === \"string\" ? first : fallback;\n}\n\nexport function bullMqIntegration(options: BullMqIntegrationOptions) {\n return queueIntegration({\n ...options,\n name: options.name ?? \"bullmq\",\n system: \"bullmq\",\n methods: options.methods ?? bullMqMethods,\n queueName: options.queueName ?? options.client.name,\n getQueueName: (args) => queueName(args, options.queueName ?? options.client.name),\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/cli-integration.ts
3
+ const defaultSignals = ["SIGINT", "SIGTERM"];
4
+ function defaultProcess() {
5
+ return globalThis.process;
6
+ }
7
+ function defaultSanitizeArg(arg) {
8
+ if (/^(--?[^=\s]*(token|password|passwd|secret|key)[^=\s]*=)/i.test(arg)) return arg.replace(/=.*/, "=[redacted]");
9
+ return arg;
10
+ }
11
+ function defaultCommand(argv) {
12
+ return argv[1] ?? argv[0];
13
+ }
14
+ function levelFor(level, event, code) {
15
+ if (typeof level === "function") return level(event, code);
16
+ if (level) return level;
17
+ if (event === "signal") return "warn";
18
+ if (event === "exit" && Number(code ?? 0) !== 0) return "error";
19
+ return "info";
20
+ }
21
+ function pickEnv(env, names) {
22
+ if (!env || !names || names.length === 0) return void 0;
23
+ const out = {};
24
+ for (const name of names) {
25
+ const value = env[name];
26
+ if (value !== void 0) out[name] = value;
27
+ }
28
+ return Object.keys(out).length > 0 ? out : void 0;
29
+ }
30
+ function removeListener(processLike, event, listener) {
31
+ if (processLike.off) {
32
+ processLike.off(event, listener);
33
+ return;
34
+ }
35
+ processLike.removeListener?.(event, listener);
36
+ }
37
+ function captureCliIntegration(options = {}) {
38
+ const name = options.name ?? "cli";
39
+ const captureStart = options.captureStart ?? true;
40
+ const captureExit = options.captureExit ?? true;
41
+ const captureSignals = options.captureSignals ?? true;
42
+ const captureCwd = options.captureCwd ?? true;
43
+ const signals = options.signals ?? defaultSignals;
44
+ const sanitizeArg = options.sanitizeArg ?? defaultSanitizeArg;
45
+ const commandFor = options.getCommand ?? defaultCommand;
46
+ return {
47
+ name: "capture-cli",
48
+ setup(api) {
49
+ const processLike = options.process ?? defaultProcess();
50
+ if (!processLike) return;
51
+ const argv = processLike.argv ?? [];
52
+ const command = commandFor(argv);
53
+ const sanitizedArgv = argv.map((arg, index) => sanitizeArg(arg, index, argv));
54
+ const disposers = [];
55
+ let disposed = false;
56
+ const capture = api.guard((input) => {
57
+ if (!disposed) api.capture(input);
58
+ });
59
+ const cliBase = {
60
+ kind: name,
61
+ command,
62
+ argv: sanitizedArgv,
63
+ cwd: captureCwd ? processLike.cwd?.() : void 0,
64
+ env: pickEnv(processLike.env, options.captureEnv)
65
+ };
66
+ if (captureStart) capture({
67
+ level: levelFor(options.level, "start"),
68
+ message: `CLI start${command ? ` ${command}` : ""}`,
69
+ props: { cli: {
70
+ ...cliBase,
71
+ lifecycle: "start"
72
+ } }
73
+ });
74
+ if (captureExit && processLike.on) {
75
+ const onExit = (code) => {
76
+ const exitCode = code ?? processLike.exitCode ?? 0;
77
+ capture({
78
+ level: levelFor(options.level, "exit", exitCode),
79
+ message: `CLI exit ${String(exitCode)}`,
80
+ props: { cli: {
81
+ ...cliBase,
82
+ lifecycle: "exit",
83
+ exitCode
84
+ } }
85
+ });
86
+ };
87
+ processLike.on("exit", onExit);
88
+ disposers.push(() => removeListener(processLike, "exit", onExit));
89
+ }
90
+ if (captureSignals && processLike.on) for (const signal of signals) {
91
+ const onSignal = () => {
92
+ capture({
93
+ level: levelFor(options.level, "signal", signal),
94
+ message: `CLI signal ${signal}`,
95
+ props: { cli: {
96
+ ...cliBase,
97
+ lifecycle: "signal",
98
+ signal
99
+ } }
100
+ });
101
+ };
102
+ processLike.on(signal, onSignal);
103
+ disposers.push(() => removeListener(processLike, signal, onSignal));
104
+ }
105
+ return () => {
106
+ if (disposed) return;
107
+ disposed = true;
108
+ for (const dispose of disposers) dispose();
109
+ };
110
+ }
111
+ };
112
+ }
113
+ //#endregion
114
+ exports.captureCliIntegration = captureCliIntegration;
115
+
116
+ //# sourceMappingURL=cli-integration.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-integration.cjs","names":[],"sources":["../src/cli-integration.ts"],"sourcesContent":["import {\n type CaptureInput,\n type Integration,\n type IntegrationSetupContext,\n type LoggerLevel,\n} from \"@loggerjs/core\";\n\nexport interface CliProcessLike {\n argv?: readonly string[];\n env?: Record<string, string | undefined>;\n exitCode?: number | string | null;\n cwd?: () => string;\n on?: (event: string, listener: (...args: unknown[]) => void) => unknown;\n off?: (event: string, listener: (...args: unknown[]) => void) => unknown;\n removeListener?: (event: string, listener: (...args: unknown[]) => void) => unknown;\n}\n\nexport interface CaptureCliOptions {\n name?: string;\n process?: CliProcessLike;\n captureStart?: boolean;\n captureExit?: boolean;\n captureSignals?: boolean;\n captureCwd?: boolean;\n captureEnv?: readonly string[];\n signals?: readonly string[];\n level?:\n | LoggerLevel\n | ((event: \"start\" | \"exit\" | \"signal\", code?: number | string) => LoggerLevel);\n getCommand?: (argv: readonly string[]) => string | undefined;\n sanitizeArg?: (arg: string, index: number, argv: readonly string[]) => string;\n}\n\nconst defaultSignals = [\"SIGINT\", \"SIGTERM\"] as const;\n\nfunction defaultProcess(): CliProcessLike | undefined {\n return (globalThis as unknown as { process?: CliProcessLike }).process;\n}\n\nfunction defaultSanitizeArg(arg: string) {\n if (/^(--?[^=\\s]*(token|password|passwd|secret|key)[^=\\s]*=)/i.test(arg)) {\n return arg.replace(/=.*/, \"=[redacted]\");\n }\n return arg;\n}\n\nfunction defaultCommand(argv: readonly string[]): string | undefined {\n return argv[1] ?? argv[0];\n}\n\nfunction levelFor(\n level: CaptureCliOptions[\"level\"],\n event: \"start\" | \"exit\" | \"signal\",\n code?: number | string,\n): LoggerLevel {\n if (typeof level === \"function\") return level(event, code);\n if (level) return level;\n if (event === \"signal\") return \"warn\";\n if (event === \"exit\" && Number(code ?? 0) !== 0) return \"error\";\n return \"info\";\n}\n\nfunction pickEnv(\n env: Record<string, string | undefined> | undefined,\n names: readonly string[] | undefined,\n) {\n if (!env || !names || names.length === 0) return undefined;\n const out: Record<string, string> = {};\n for (const name of names) {\n const value = env[name];\n if (value !== undefined) out[name] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction removeListener(\n processLike: CliProcessLike,\n event: string,\n listener: (...args: unknown[]) => void,\n) {\n if (processLike.off) {\n processLike.off(event, listener);\n return;\n }\n processLike.removeListener?.(event, listener);\n}\n\nexport function captureCliIntegration(options: CaptureCliOptions = {}): Integration {\n const name = options.name ?? \"cli\";\n const captureStart = options.captureStart ?? true;\n const captureExit = options.captureExit ?? true;\n const captureSignals = options.captureSignals ?? true;\n const captureCwd = options.captureCwd ?? true;\n const signals = options.signals ?? defaultSignals;\n const sanitizeArg = options.sanitizeArg ?? defaultSanitizeArg;\n const commandFor = options.getCommand ?? defaultCommand;\n\n return {\n name: \"capture-cli\",\n setup(api: IntegrationSetupContext) {\n const processLike = options.process ?? defaultProcess();\n if (!processLike) return;\n const argv = processLike.argv ?? [];\n const command = commandFor(argv);\n const sanitizedArgv = argv.map((arg, index) => sanitizeArg(arg, index, argv));\n const disposers: Array<() => void> = [];\n let disposed = false;\n\n const capture = api.guard((input: CaptureInput) => {\n if (!disposed) api.capture(input);\n });\n const cliBase = {\n kind: name,\n command,\n argv: sanitizedArgv,\n cwd: captureCwd ? processLike.cwd?.() : undefined,\n env: pickEnv(processLike.env, options.captureEnv),\n };\n\n if (captureStart) {\n capture({\n level: levelFor(options.level, \"start\"),\n message: `CLI start${command ? ` ${command}` : \"\"}`,\n props: {\n cli: {\n ...cliBase,\n lifecycle: \"start\",\n },\n },\n });\n }\n\n if (captureExit && processLike.on) {\n const onExit = (code: unknown) => {\n const exitCode = code ?? processLike.exitCode ?? 0;\n capture({\n level: levelFor(options.level, \"exit\", exitCode as number | string),\n message: `CLI exit ${String(exitCode)}`,\n props: {\n cli: {\n ...cliBase,\n lifecycle: \"exit\",\n exitCode,\n },\n },\n });\n };\n processLike.on(\"exit\", onExit);\n disposers.push(() => removeListener(processLike, \"exit\", onExit));\n }\n\n if (captureSignals && processLike.on) {\n for (const signal of signals) {\n const onSignal = () => {\n capture({\n level: levelFor(options.level, \"signal\", signal),\n message: `CLI signal ${signal}`,\n props: {\n cli: {\n ...cliBase,\n lifecycle: \"signal\",\n signal,\n },\n },\n });\n };\n processLike.on(signal, onSignal);\n disposers.push(() => removeListener(processLike, signal, onSignal));\n }\n }\n\n return () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers) dispose();\n };\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ //#region src/cli-integration.ts
2
+ const defaultSignals = ["SIGINT", "SIGTERM"];
3
+ function defaultProcess() {
4
+ return globalThis.process;
5
+ }
6
+ function defaultSanitizeArg(arg) {
7
+ if (/^(--?[^=\s]*(token|password|passwd|secret|key)[^=\s]*=)/i.test(arg)) return arg.replace(/=.*/, "=[redacted]");
8
+ return arg;
9
+ }
10
+ function defaultCommand(argv) {
11
+ return argv[1] ?? argv[0];
12
+ }
13
+ function levelFor(level, event, code) {
14
+ if (typeof level === "function") return level(event, code);
15
+ if (level) return level;
16
+ if (event === "signal") return "warn";
17
+ if (event === "exit" && Number(code ?? 0) !== 0) return "error";
18
+ return "info";
19
+ }
20
+ function pickEnv(env, names) {
21
+ if (!env || !names || names.length === 0) return void 0;
22
+ const out = {};
23
+ for (const name of names) {
24
+ const value = env[name];
25
+ if (value !== void 0) out[name] = value;
26
+ }
27
+ return Object.keys(out).length > 0 ? out : void 0;
28
+ }
29
+ function removeListener(processLike, event, listener) {
30
+ if (processLike.off) {
31
+ processLike.off(event, listener);
32
+ return;
33
+ }
34
+ processLike.removeListener?.(event, listener);
35
+ }
36
+ function captureCliIntegration(options = {}) {
37
+ const name = options.name ?? "cli";
38
+ const captureStart = options.captureStart ?? true;
39
+ const captureExit = options.captureExit ?? true;
40
+ const captureSignals = options.captureSignals ?? true;
41
+ const captureCwd = options.captureCwd ?? true;
42
+ const signals = options.signals ?? defaultSignals;
43
+ const sanitizeArg = options.sanitizeArg ?? defaultSanitizeArg;
44
+ const commandFor = options.getCommand ?? defaultCommand;
45
+ return {
46
+ name: "capture-cli",
47
+ setup(api) {
48
+ const processLike = options.process ?? defaultProcess();
49
+ if (!processLike) return;
50
+ const argv = processLike.argv ?? [];
51
+ const command = commandFor(argv);
52
+ const sanitizedArgv = argv.map((arg, index) => sanitizeArg(arg, index, argv));
53
+ const disposers = [];
54
+ let disposed = false;
55
+ const capture = api.guard((input) => {
56
+ if (!disposed) api.capture(input);
57
+ });
58
+ const cliBase = {
59
+ kind: name,
60
+ command,
61
+ argv: sanitizedArgv,
62
+ cwd: captureCwd ? processLike.cwd?.() : void 0,
63
+ env: pickEnv(processLike.env, options.captureEnv)
64
+ };
65
+ if (captureStart) capture({
66
+ level: levelFor(options.level, "start"),
67
+ message: `CLI start${command ? ` ${command}` : ""}`,
68
+ props: { cli: {
69
+ ...cliBase,
70
+ lifecycle: "start"
71
+ } }
72
+ });
73
+ if (captureExit && processLike.on) {
74
+ const onExit = (code) => {
75
+ const exitCode = code ?? processLike.exitCode ?? 0;
76
+ capture({
77
+ level: levelFor(options.level, "exit", exitCode),
78
+ message: `CLI exit ${String(exitCode)}`,
79
+ props: { cli: {
80
+ ...cliBase,
81
+ lifecycle: "exit",
82
+ exitCode
83
+ } }
84
+ });
85
+ };
86
+ processLike.on("exit", onExit);
87
+ disposers.push(() => removeListener(processLike, "exit", onExit));
88
+ }
89
+ if (captureSignals && processLike.on) for (const signal of signals) {
90
+ const onSignal = () => {
91
+ capture({
92
+ level: levelFor(options.level, "signal", signal),
93
+ message: `CLI signal ${signal}`,
94
+ props: { cli: {
95
+ ...cliBase,
96
+ lifecycle: "signal",
97
+ signal
98
+ } }
99
+ });
100
+ };
101
+ processLike.on(signal, onSignal);
102
+ disposers.push(() => removeListener(processLike, signal, onSignal));
103
+ }
104
+ return () => {
105
+ if (disposed) return;
106
+ disposed = true;
107
+ for (const dispose of disposers) dispose();
108
+ };
109
+ }
110
+ };
111
+ }
112
+ //#endregion
113
+ export { captureCliIntegration };
114
+
115
+ //# sourceMappingURL=cli-integration.js.map