@loggerjs/node 0.6.0 → 0.7.0

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 (71) hide show
  1. package/README.md +5 -4
  2. package/dist/bullmq-integration.cjs +2 -145
  3. package/dist/bullmq-integration.cjs.map +1 -1
  4. package/dist/bullmq-integration.js +1 -144
  5. package/dist/bullmq-integration.js.map +1 -1
  6. package/dist/chunks/node-destination-DvP8jBvm.cjs +254 -0
  7. package/dist/chunks/node-destination-DvP8jBvm.cjs.map +1 -0
  8. package/dist/chunks/node-destination-YnpYbctz.js +243 -0
  9. package/dist/chunks/node-destination-YnpYbctz.js.map +1 -0
  10. package/dist/context.cjs +1 -1
  11. package/dist/context.js +1 -1
  12. package/dist/diagnostics-channel-integration.cjs +1 -1
  13. package/dist/file-transport.cjs +3 -232
  14. package/dist/file-transport.cjs.map +1 -1
  15. package/dist/file-transport.js +3 -232
  16. package/dist/file-transport.js.map +1 -1
  17. package/dist/http-transport.cjs +25 -4
  18. package/dist/http-transport.cjs.map +1 -1
  19. package/dist/http-transport.d.ts +15 -0
  20. package/dist/http-transport.d.ts.map +1 -1
  21. package/dist/http-transport.js +25 -4
  22. package/dist/http-transport.js.map +1 -1
  23. package/dist/index.cjs +54 -2375
  24. package/dist/index.d.ts +211 -19
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +25 -2347
  27. package/dist/internal-types.d.ts +1 -0
  28. package/dist/internal-types.d.ts.map +1 -1
  29. package/dist/logger-diagnostics.cjs +4 -5
  30. package/dist/logger-diagnostics.cjs.map +1 -1
  31. package/dist/logger-diagnostics.d.ts +1 -1
  32. package/dist/logger-diagnostics.d.ts.map +1 -1
  33. package/dist/logger-diagnostics.js +1 -1
  34. package/dist/logger-diagnostics.js.map +1 -1
  35. package/dist/nest-integration.cjs +2 -127
  36. package/dist/nest-integration.cjs.map +1 -1
  37. package/dist/nest-integration.js +1 -126
  38. package/dist/nest-integration.js.map +1 -1
  39. package/dist/node-destination.d.ts.map +1 -1
  40. package/dist/payload-transforms.cjs +2 -2
  41. package/dist/payload-transforms.cjs.map +1 -1
  42. package/dist/payload-transforms.d.ts.map +1 -1
  43. package/dist/payload-transforms.js +1 -1
  44. package/dist/payload-transforms.js.map +1 -1
  45. package/dist/prisma-integration.cjs +2 -125
  46. package/dist/prisma-integration.cjs.map +1 -1
  47. package/dist/prisma-integration.js +1 -124
  48. package/dist/prisma-integration.js.map +1 -1
  49. package/dist/redis-integration.cjs +2 -125
  50. package/dist/redis-integration.cjs.map +1 -1
  51. package/dist/redis-integration.js +1 -124
  52. package/dist/redis-integration.js.map +1 -1
  53. package/dist/rotating-file-transport.cjs +24 -239
  54. package/dist/rotating-file-transport.cjs.map +1 -1
  55. package/dist/rotating-file-transport.d.ts.map +1 -1
  56. package/dist/rotating-file-transport.js +24 -239
  57. package/dist/rotating-file-transport.js.map +1 -1
  58. package/dist/stdout-transport.cjs +3 -162
  59. package/dist/stdout-transport.cjs.map +1 -1
  60. package/dist/stdout-transport.js +3 -162
  61. package/dist/stdout-transport.js.map +1 -1
  62. package/dist/syslog-transport.cjs +1 -1
  63. package/dist/syslog-transport.js +1 -1
  64. package/dist/worker-transport.cjs +5 -4
  65. package/dist/worker-transport.cjs.map +1 -1
  66. package/dist/worker-transport.d.ts.map +1 -1
  67. package/dist/worker-transport.js +3 -2
  68. package/dist/worker-transport.js.map +1 -1
  69. package/package.json +5 -2
  70. package/dist/index.cjs.map +0 -1
  71. package/dist/index.js.map +0 -1
@@ -1,235 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- let fs = require("fs");
2
+ const require_node_destination = require("./chunks/node-destination-DvP8jBvm.cjs");
3
3
  let _loggerjs_core = require("@loggerjs/core");
4
- let path = require("path");
5
- //#region src/node-destination.ts
6
- const encoder = new TextEncoder();
7
- const normalizeError = (error) => error instanceof Error ? error : new Error(String(error));
8
- function byteLength(payload) {
9
- return typeof payload === "string" ? encoder.encode(payload).byteLength : payload.byteLength;
10
- }
11
- function coalescePayloads(payloads) {
12
- if (payloads.every((payload) => typeof payload === "string")) return payloads.join("");
13
- const buffers = payloads.map((payload) => typeof payload === "string" ? Buffer.from(payload) : Buffer.from(payload));
14
- return Buffer.concat(buffers);
15
- }
16
- function isEpipe(error) {
17
- return Boolean(error) && typeof error === "object" && error.code === "EPIPE";
18
- }
19
- function normalizeMinLength(value) {
20
- if (value === void 0 || !Number.isFinite(value) || value <= 0) return 0;
21
- return Math.floor(value);
22
- }
23
- function createNodeStreamDestination(options) {
24
- const minLength = normalizeMinLength(options.minLength);
25
- const ignoreEpipe = options.ignoreEpipe ?? false;
26
- const waiters = [];
27
- const buffer = [];
28
- const pendingPayloads = [];
29
- let bufferedBytes = 0;
30
- let pendingWrites = 0;
31
- let pendingDrains = 0;
32
- let lastError;
33
- let lastContext;
34
- let closed = false;
35
- const reportInternalError = (error, operation) => {
36
- if (ignoreEpipe && isEpipe(error)) return;
37
- lastContext?.reportInternalError(error, {
38
- phase: "transport",
39
- transport: options.name,
40
- operation
41
- });
42
- };
43
- const settleWaitersIfIdle = () => {
44
- if (pendingWrites + pendingDrains > 0) return;
45
- if (waiters.length === 0) return;
46
- const error = lastError;
47
- lastError = void 0;
48
- for (const waiter of waiters.splice(0)) if (error) waiter.reject(error);
49
- else waiter.resolve();
50
- };
51
- const recordError = (error, operation) => {
52
- if (ignoreEpipe && isEpipe(error)) {
53
- closed = true;
54
- return;
55
- }
56
- lastError = normalizeError(error);
57
- reportInternalError(lastError, operation);
58
- };
59
- const onStreamError = (error) => {
60
- recordError(error, "stream-error");
61
- settleWaitersIfIdle();
62
- };
63
- const offError = () => options.stream.off?.("error", onStreamError);
64
- options.stream.on?.("error", onStreamError);
65
- const waitForDrain = () => {
66
- if (!options.stream.once) return;
67
- pendingDrains += 1;
68
- options.stream.once("drain", () => {
69
- pendingDrains -= 1;
70
- settleWaitersIfIdle();
71
- });
72
- };
73
- const removePending = (payload) => {
74
- const index = pendingPayloads.indexOf(payload);
75
- if (index >= 0) pendingPayloads.splice(index, 1);
76
- };
77
- const writeNow = (payload) => {
78
- if (closed) return;
79
- pendingPayloads.push(payload);
80
- pendingWrites += 1;
81
- try {
82
- if (options.stream.write(payload, (error) => {
83
- removePending(payload);
84
- pendingWrites -= 1;
85
- if (error) recordError(error, options.reportOperation ?? "write");
86
- settleWaitersIfIdle();
87
- }) === false) waitForDrain();
88
- } catch (error) {
89
- removePending(payload);
90
- pendingWrites -= 1;
91
- recordError(error, options.reportOperation ?? "write");
92
- settleWaitersIfIdle();
93
- }
94
- };
95
- const flushBuffered = () => {
96
- if (buffer.length === 0) return;
97
- const payload = coalescePayloads(buffer.splice(0));
98
- bufferedBytes = 0;
99
- writeNow(payload);
100
- };
101
- const destination = {
102
- write(payload, context) {
103
- if (closed) return;
104
- lastContext = context;
105
- if (minLength > 0) {
106
- buffer.push(payload);
107
- bufferedBytes += byteLength(payload);
108
- if (bufferedBytes >= minLength) flushBuffered();
109
- return;
110
- }
111
- writeNow(payload);
112
- },
113
- flush() {
114
- flushBuffered();
115
- if (pendingWrites + pendingDrains === 0) {
116
- const error = lastError;
117
- lastError = void 0;
118
- if (error) return Promise.reject(error);
119
- return Promise.resolve();
120
- }
121
- return new Promise((resolve, reject) => {
122
- waiters.push({
123
- resolve,
124
- reject
125
- });
126
- });
127
- },
128
- flushSync() {
129
- if (!options.syncWrite) {
130
- flushBuffered();
131
- return;
132
- }
133
- for (const payload of buffer.splice(0)) options.syncWrite(payload);
134
- bufferedBytes = 0;
135
- for (const payload of pendingPayloads.splice(0)) options.syncWrite(payload);
136
- },
137
- close() {
138
- return destination.flush().then(() => new Promise((resolve, reject) => {
139
- if (!options.stream.end) {
140
- closed = true;
141
- offError();
142
- resolve();
143
- return;
144
- }
145
- options.stream.end((error) => {
146
- closed = true;
147
- offError();
148
- if (error && !(ignoreEpipe && isEpipe(error))) reject(error);
149
- else resolve();
150
- });
151
- }), (error) => {
152
- offError();
153
- return Promise.reject(error);
154
- });
155
- },
156
- closeSync() {
157
- destination.flushSync();
158
- closed = true;
159
- offError();
160
- }
161
- };
162
- return destination;
163
- }
164
- function createNodeFileDestination(options) {
165
- const flags = options.flags ?? (options.append === false ? "w" : "a");
166
- if (options.mkdir) (0, fs.mkdirSync)((0, path.dirname)(options.path), { recursive: true });
167
- let fd;
168
- const syncFlags = options.sync ? flags : "a";
169
- const getFd = () => {
170
- fd ??= (0, fs.openSync)(options.path, syncFlags);
171
- return fd;
172
- };
173
- const syncWrite = (payload) => {
174
- if (typeof payload === "string") (0, fs.writeSync)(getFd(), payload);
175
- else (0, fs.writeSync)(getFd(), payload);
176
- };
177
- if (options.sync) {
178
- let closed = false;
179
- const releaseSync = () => {
180
- if (fd !== void 0) {
181
- (0, fs.closeSync)(fd);
182
- fd = void 0;
183
- }
184
- };
185
- return {
186
- write(payload) {
187
- if (closed) return;
188
- syncWrite(payload);
189
- },
190
- flush() {
191
- return Promise.resolve();
192
- },
193
- flushSync() {},
194
- close() {
195
- releaseSync();
196
- closed = true;
197
- return Promise.resolve();
198
- },
199
- closeSync() {
200
- releaseSync();
201
- closed = true;
202
- },
203
- releaseSync
204
- };
205
- }
206
- const stream = (0, fs.createWriteStream)(options.path, { flags });
207
- const destination = createNodeStreamDestination({
208
- name: options.name,
209
- stream,
210
- minLength: options.minLength,
211
- syncWrite
212
- });
213
- const releaseSync = () => {
214
- if (fd !== void 0) {
215
- (0, fs.closeSync)(fd);
216
- fd = void 0;
217
- }
218
- };
219
- return {
220
- ...destination,
221
- stream,
222
- close() {
223
- return destination.close().finally(releaseSync);
224
- },
225
- closeSync() {
226
- destination.closeSync();
227
- releaseSync();
228
- },
229
- releaseSync
230
- };
231
- }
232
- //#endregion
4
+ let fs = require("fs");
233
5
  //#region src/rotating-file-transport.ts
234
6
  const textEncoder = new TextEncoder();
235
7
  function payloadBytes(payload) {
@@ -254,11 +26,11 @@ function fileSize(path) {
254
26
  }
255
27
  }
256
28
  function rotatingFileTransport(options) {
257
- const codec = options.codec ?? (0, _loggerjs_core.ndjsonCodec)();
29
+ const codec = options.codec ?? (0, _loggerjs_core.ndjsonEncoder)();
258
30
  const maxBytes = normalizePositiveInteger(options.maxBytes, 10 * 1024 * 1024);
259
31
  const maxFiles = normalizeNonNegativeInteger(options.maxFiles, 5);
260
32
  const archivePath = options.archivePath ?? defaultArchivePath;
261
- const destination = createNodeFileDestination({
33
+ const destination = require_node_destination.createNodeFileDestination({
262
34
  name: options.name ?? "rotating-file",
263
35
  path: options.path,
264
36
  flags: options.flags,
@@ -267,11 +39,13 @@ function rotatingFileTransport(options) {
267
39
  sync: true
268
40
  });
269
41
  let bytes = fileSize(options.path);
42
+ let rotateAt = maxBytes;
270
43
  const rotate = () => {
271
44
  destination.releaseSync?.();
272
45
  if (maxFiles === 0) {
273
46
  if ((0, fs.existsSync)(options.path)) (0, fs.unlinkSync)(options.path);
274
47
  bytes = 0;
48
+ rotateAt = maxBytes;
275
49
  return;
276
50
  }
277
51
  const oldest = archivePath(options.path, maxFiles);
@@ -282,24 +56,34 @@ function rotatingFileTransport(options) {
282
56
  }
283
57
  if ((0, fs.existsSync)(options.path)) (0, fs.renameSync)(options.path, archivePath(options.path, 1));
284
58
  bytes = 0;
59
+ rotateAt = maxBytes;
285
60
  };
286
- const writePayload = (payload) => {
61
+ const writePayload = (payload, context) => {
287
62
  const size = payloadBytes(payload);
288
- if (bytes > 0 && bytes + size > maxBytes) rotate();
63
+ if (bytes > 0 && bytes + size > rotateAt) try {
64
+ rotate();
65
+ } catch (error) {
66
+ rotateAt = bytes + size + maxBytes;
67
+ context?.reportInternalError(error, {
68
+ phase: "transport",
69
+ transport: transport.name,
70
+ operation: "rotate"
71
+ });
72
+ }
289
73
  destination.write(payload);
290
74
  bytes += size;
291
75
  };
292
- return {
76
+ const transport = {
293
77
  name: options.name ?? "rotating-file",
294
78
  minLevel: options.minLevel,
295
- log(event) {
79
+ log(event, context) {
296
80
  if (options.minLevel !== void 0 && event.level < (0, _loggerjs_core.toLevelValue)(options.minLevel)) return;
297
- writePayload(codec.encode(event));
81
+ writePayload(codec.encode(event), context);
298
82
  },
299
- logBatch(events) {
83
+ logBatch(events, context) {
300
84
  for (const event of events) {
301
85
  if (options.minLevel !== void 0 && event.level < (0, _loggerjs_core.toLevelValue)(options.minLevel)) continue;
302
- writePayload(codec.encode(event));
86
+ writePayload(codec.encode(event), context);
303
87
  }
304
88
  },
305
89
  flush() {
@@ -312,6 +96,7 @@ function rotatingFileTransport(options) {
312
96
  rotate,
313
97
  currentBytes: () => bytes
314
98
  };
99
+ return transport;
315
100
  }
316
101
  //#endregion
317
102
  exports.rotatingFileTransport = rotatingFileTransport;
@@ -1 +1 @@
1
- {"version":3,"file":"rotating-file-transport.cjs","names":[],"sources":["../src/node-destination.ts","../src/rotating-file-transport.ts"],"sourcesContent":["import { closeSync, createWriteStream, mkdirSync, openSync, writeSync, type WriteStream } from \"fs\";\nimport { dirname } from \"path\";\nimport type { TransportContext } from \"@loggerjs/core\";\nimport type { WritableLike } from \"./internal-types\";\n\nexport interface NodeDestination {\n stream?: WriteStream;\n write: (payload: string | Uint8Array, context?: TransportContext) => void;\n flush: () => Promise<void>;\n flushSync: () => void;\n close: () => Promise<void>;\n closeSync: () => void;\n releaseSync?: () => void;\n}\n\nexport interface NodeStreamDestinationOptions {\n name: string;\n stream: WritableLike;\n minLength?: number;\n ignoreEpipe?: boolean;\n reportOperation?: string;\n syncWrite?: (payload: string | Uint8Array) => void;\n}\n\nexport interface NodeFileDestinationOptions {\n name: string;\n path: string;\n flags?: string;\n append?: boolean;\n mkdir?: boolean;\n sync?: boolean;\n minLength?: number;\n}\n\ninterface FlushWaiter {\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\nconst encoder = new TextEncoder();\n\nconst normalizeError = (error: unknown): Error =>\n error instanceof Error ? error : new Error(String(error));\n\nfunction byteLength(payload: string | Uint8Array): number {\n return typeof payload === \"string\" ? encoder.encode(payload).byteLength : payload.byteLength;\n}\n\nfunction coalescePayloads(payloads: Array<string | Uint8Array>): string | Uint8Array {\n if (payloads.every((payload) => typeof payload === \"string\")) {\n return payloads.join(\"\");\n }\n const buffers = payloads.map((payload) =>\n typeof payload === \"string\" ? Buffer.from(payload) : Buffer.from(payload),\n );\n return Buffer.concat(buffers);\n}\n\nfunction isEpipe(error: unknown): boolean {\n return (\n Boolean(error) && typeof error === \"object\" && (error as { code?: unknown }).code === \"EPIPE\"\n );\n}\n\nfunction normalizeMinLength(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value) || value <= 0) return 0;\n return Math.floor(value);\n}\n\nexport function createNodeStreamDestination(\n options: NodeStreamDestinationOptions,\n): NodeDestination {\n const minLength = normalizeMinLength(options.minLength);\n const ignoreEpipe = options.ignoreEpipe ?? false;\n const waiters: FlushWaiter[] = [];\n const buffer: Array<string | Uint8Array> = [];\n const pendingPayloads: Array<string | Uint8Array> = [];\n let bufferedBytes = 0;\n let pendingWrites = 0;\n let pendingDrains = 0;\n let lastError: Error | undefined;\n let lastContext: TransportContext | undefined;\n let closed = false;\n\n const reportInternalError = (error: unknown, operation: string) => {\n if (ignoreEpipe && isEpipe(error)) return;\n lastContext?.reportInternalError(error, {\n phase: \"transport\",\n transport: options.name,\n operation,\n });\n };\n\n const settleWaitersIfIdle = () => {\n if (pendingWrites + pendingDrains > 0) return;\n if (waiters.length === 0) return;\n const error = lastError;\n lastError = undefined;\n for (const waiter of waiters.splice(0)) {\n if (error) waiter.reject(error);\n else waiter.resolve();\n }\n };\n\n const recordError = (error: unknown, operation: string) => {\n if (ignoreEpipe && isEpipe(error)) {\n closed = true;\n return;\n }\n lastError = normalizeError(error);\n reportInternalError(lastError, operation);\n };\n\n const onStreamError = (error: Error) => {\n recordError(error, \"stream-error\");\n settleWaitersIfIdle();\n };\n const offError = () => options.stream.off?.(\"error\", onStreamError);\n options.stream.on?.(\"error\", onStreamError);\n\n const waitForDrain = () => {\n if (!options.stream.once) return;\n pendingDrains += 1;\n options.stream.once(\"drain\", () => {\n pendingDrains -= 1;\n settleWaitersIfIdle();\n });\n };\n\n const removePending = (payload: string | Uint8Array) => {\n const index = pendingPayloads.indexOf(payload);\n if (index >= 0) pendingPayloads.splice(index, 1);\n };\n\n const writeNow = (payload: string | Uint8Array) => {\n if (closed) return;\n pendingPayloads.push(payload);\n pendingWrites += 1;\n try {\n const result = options.stream.write(payload, (error?: Error | null) => {\n removePending(payload);\n pendingWrites -= 1;\n if (error) recordError(error, options.reportOperation ?? \"write\");\n settleWaitersIfIdle();\n });\n if (result === false) waitForDrain();\n } catch (error) {\n removePending(payload);\n pendingWrites -= 1;\n recordError(error, options.reportOperation ?? \"write\");\n settleWaitersIfIdle();\n }\n };\n\n const flushBuffered = () => {\n if (buffer.length === 0) return;\n const payload = coalescePayloads(buffer.splice(0));\n bufferedBytes = 0;\n writeNow(payload);\n };\n\n const destination: NodeDestination = {\n write(payload, context) {\n if (closed) return;\n lastContext = context;\n if (minLength > 0) {\n buffer.push(payload);\n bufferedBytes += byteLength(payload);\n if (bufferedBytes >= minLength) flushBuffered();\n return;\n }\n writeNow(payload);\n },\n flush() {\n flushBuffered();\n if (pendingWrites + pendingDrains === 0) {\n const error = lastError;\n lastError = undefined;\n if (error) return Promise.reject(error);\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n waiters.push({ resolve, reject });\n });\n },\n flushSync() {\n if (!options.syncWrite) {\n flushBuffered();\n return;\n }\n for (const payload of buffer.splice(0)) options.syncWrite(payload);\n bufferedBytes = 0;\n for (const payload of pendingPayloads.splice(0)) options.syncWrite(payload);\n },\n close() {\n return destination.flush().then(\n () =>\n new Promise<void>((resolve, reject) => {\n if (!options.stream.end) {\n closed = true;\n offError();\n resolve();\n return;\n }\n options.stream.end((error?: Error | null) => {\n closed = true;\n offError();\n if (error && !(ignoreEpipe && isEpipe(error))) reject(error);\n else resolve();\n });\n }),\n (error: unknown) => {\n offError();\n return Promise.reject(error);\n },\n );\n },\n closeSync() {\n destination.flushSync();\n closed = true;\n offError();\n },\n };\n return destination;\n}\n\nexport function createNodeFileDestination(options: NodeFileDestinationOptions): NodeDestination {\n const flags = options.flags ?? (options.append === false ? \"w\" : \"a\");\n if (options.mkdir) mkdirSync(dirname(options.path), { recursive: true });\n\n let fd: number | undefined;\n // In sync mode this fd is the only writer, so it honors the configured flags.\n // In async stream mode the stream already opened (and, for \"w\", truncated)\n // the file; the crash-path fd must append or it would erase earlier logs.\n const syncFlags = options.sync ? flags : \"a\";\n const getFd = () => {\n fd ??= openSync(options.path, syncFlags);\n return fd;\n };\n const syncWrite = (payload: string | Uint8Array) => {\n if (typeof payload === \"string\") writeSync(getFd(), payload);\n else writeSync(getFd(), payload);\n };\n\n if (options.sync) {\n let closed = false;\n const releaseSync = () => {\n if (fd !== undefined) {\n closeSync(fd);\n fd = undefined;\n }\n };\n return {\n write(payload) {\n if (closed) return;\n syncWrite(payload);\n },\n flush() {\n return Promise.resolve();\n },\n flushSync() {},\n close() {\n releaseSync();\n closed = true;\n return Promise.resolve();\n },\n closeSync() {\n releaseSync();\n closed = true;\n },\n releaseSync,\n };\n }\n\n const stream = createWriteStream(options.path, { flags });\n const destination = createNodeStreamDestination({\n name: options.name,\n stream,\n minLength: options.minLength,\n syncWrite,\n });\n const releaseSync = () => {\n if (fd !== undefined) {\n closeSync(fd);\n fd = undefined;\n }\n };\n return {\n ...destination,\n stream,\n close() {\n return destination.close().finally(releaseSync);\n },\n closeSync() {\n destination.closeSync();\n releaseSync();\n },\n releaseSync,\n };\n}\n","import { existsSync, renameSync, statSync, unlinkSync } from \"fs\";\nimport {\n ndjsonCodec,\n toLevelValue,\n type Codec,\n type LogEvent,\n type LoggerLevel,\n type Transport,\n} from \"@loggerjs/core\";\nimport { createNodeFileDestination } from \"./node-destination\";\n\nexport interface RotatingFileTransportOptions {\n path: string;\n name?: string;\n codec?: Codec<string | Uint8Array>;\n minLevel?: LoggerLevel;\n flags?: string;\n append?: boolean;\n mkdir?: boolean;\n maxBytes?: number;\n maxFiles?: number;\n archivePath?: (path: string, index: number) => string;\n}\n\nexport interface RotatingFileTransport extends Transport {\n rotate: () => void;\n flushSync: () => void;\n currentBytes: () => number;\n}\n\nconst textEncoder = new TextEncoder();\n\nfunction payloadBytes(payload: string | Uint8Array): number {\n return typeof payload === \"string\" ? textEncoder.encode(payload).byteLength : payload.byteLength;\n}\n\nfunction normalizePositiveInteger(value: number | undefined, fallback: number): number {\n if (value === undefined || !Number.isFinite(value) || value <= 0) return fallback;\n return Math.floor(value);\n}\n\nfunction normalizeNonNegativeInteger(value: number | undefined, fallback: number): number {\n if (value === undefined || !Number.isFinite(value) || value < 0) return fallback;\n return Math.floor(value);\n}\n\nfunction defaultArchivePath(path: string, index: number): string {\n return `${path}.${index}`;\n}\n\nfunction fileSize(path: string): number {\n try {\n return statSync(path).size;\n } catch {\n return 0;\n }\n}\n\nexport function rotatingFileTransport(\n options: RotatingFileTransportOptions,\n): RotatingFileTransport {\n const codec = options.codec ?? ndjsonCodec();\n const maxBytes = normalizePositiveInteger(options.maxBytes, 10 * 1024 * 1024);\n const maxFiles = normalizeNonNegativeInteger(options.maxFiles, 5);\n const archivePath = options.archivePath ?? defaultArchivePath;\n const destination = createNodeFileDestination({\n name: options.name ?? \"rotating-file\",\n path: options.path,\n flags: options.flags,\n append: options.append,\n mkdir: options.mkdir,\n sync: true,\n });\n let bytes = fileSize(options.path);\n\n const rotate = () => {\n destination.releaseSync?.();\n\n if (maxFiles === 0) {\n if (existsSync(options.path)) unlinkSync(options.path);\n bytes = 0;\n return;\n }\n\n const oldest = archivePath(options.path, maxFiles);\n if (existsSync(oldest)) unlinkSync(oldest);\n\n for (let index = maxFiles - 1; index >= 1; index -= 1) {\n const source = archivePath(options.path, index);\n if (existsSync(source)) renameSync(source, archivePath(options.path, index + 1));\n }\n\n if (existsSync(options.path)) renameSync(options.path, archivePath(options.path, 1));\n bytes = 0;\n };\n\n const writePayload = (payload: string | Uint8Array) => {\n const size = payloadBytes(payload);\n if (bytes > 0 && bytes + size > maxBytes) rotate();\n destination.write(payload);\n bytes += size;\n };\n\n const transport: RotatingFileTransport = {\n name: options.name ?? \"rotating-file\",\n minLevel: options.minLevel,\n log(event: LogEvent) {\n if (options.minLevel !== undefined && event.level < toLevelValue(options.minLevel)) return;\n writePayload(codec.encode(event));\n },\n logBatch(events: LogEvent[]) {\n for (const event of events) {\n if (options.minLevel !== undefined && event.level < toLevelValue(options.minLevel))\n continue;\n writePayload(codec.encode(event));\n }\n },\n flush() {\n return destination.flush();\n },\n flushSync: destination.flushSync,\n close() {\n return destination.close();\n },\n rotate,\n currentBytes: () => bytes,\n };\n\n return transport;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"rotating-file-transport.cjs","names":["createNodeFileDestination"],"sources":["../src/rotating-file-transport.ts"],"sourcesContent":["import { existsSync, renameSync, statSync, unlinkSync } from \"fs\";\nimport {\n ndjsonEncoder,\n toLevelValue,\n type Codec,\n type LogEvent,\n type LoggerLevel,\n type Transport,\n type TransportContext,\n} from \"@loggerjs/core\";\nimport { createNodeFileDestination } from \"./node-destination\";\n\nexport interface RotatingFileTransportOptions {\n path: string;\n name?: string;\n codec?: Codec<string | Uint8Array>;\n minLevel?: LoggerLevel;\n flags?: string;\n append?: boolean;\n mkdir?: boolean;\n maxBytes?: number;\n maxFiles?: number;\n archivePath?: (path: string, index: number) => string;\n}\n\nexport interface RotatingFileTransport extends Transport {\n rotate: () => void;\n flushSync: () => void;\n currentBytes: () => number;\n}\n\nconst textEncoder = new TextEncoder();\n\nfunction payloadBytes(payload: string | Uint8Array): number {\n return typeof payload === \"string\" ? textEncoder.encode(payload).byteLength : payload.byteLength;\n}\n\nfunction normalizePositiveInteger(value: number | undefined, fallback: number): number {\n if (value === undefined || !Number.isFinite(value) || value <= 0) return fallback;\n return Math.floor(value);\n}\n\nfunction normalizeNonNegativeInteger(value: number | undefined, fallback: number): number {\n if (value === undefined || !Number.isFinite(value) || value < 0) return fallback;\n return Math.floor(value);\n}\n\nfunction defaultArchivePath(path: string, index: number): string {\n return `${path}.${index}`;\n}\n\nfunction fileSize(path: string): number {\n try {\n return statSync(path).size;\n } catch {\n return 0;\n }\n}\n\nexport function rotatingFileTransport(\n options: RotatingFileTransportOptions,\n): RotatingFileTransport {\n const codec = options.codec ?? ndjsonEncoder();\n const maxBytes = normalizePositiveInteger(options.maxBytes, 10 * 1024 * 1024);\n const maxFiles = normalizeNonNegativeInteger(options.maxFiles, 5);\n const archivePath = options.archivePath ?? defaultArchivePath;\n const destination = createNodeFileDestination({\n name: options.name ?? \"rotating-file\",\n path: options.path,\n flags: options.flags,\n append: options.append,\n mkdir: options.mkdir,\n sync: true,\n });\n let bytes = fileSize(options.path);\n let rotateAt = maxBytes;\n\n const rotate = () => {\n destination.releaseSync?.();\n\n if (maxFiles === 0) {\n if (existsSync(options.path)) unlinkSync(options.path);\n bytes = 0;\n rotateAt = maxBytes;\n return;\n }\n\n const oldest = archivePath(options.path, maxFiles);\n if (existsSync(oldest)) unlinkSync(oldest);\n\n for (let index = maxFiles - 1; index >= 1; index -= 1) {\n const source = archivePath(options.path, index);\n if (existsSync(source)) renameSync(source, archivePath(options.path, index + 1));\n }\n\n if (existsSync(options.path)) renameSync(options.path, archivePath(options.path, 1));\n bytes = 0;\n rotateAt = maxBytes;\n };\n\n const writePayload = (payload: string | Uint8Array, context: TransportContext | undefined) => {\n const size = payloadBytes(payload);\n if (bytes > 0 && bytes + size > rotateAt) {\n try {\n rotate();\n } catch (error) {\n // Renames fail while another process holds the file open (EBUSY or\n // EPERM on Windows) or the archive location is unwritable. Keep\n // appending to the current file and retry after another maxBytes\n // instead of dropping this and every later event.\n rotateAt = bytes + size + maxBytes;\n context?.reportInternalError(error, {\n phase: \"transport\",\n transport: transport.name,\n operation: \"rotate\",\n });\n }\n }\n destination.write(payload);\n bytes += size;\n };\n\n const transport: RotatingFileTransport = {\n name: options.name ?? \"rotating-file\",\n minLevel: options.minLevel,\n log(event: LogEvent, context?: TransportContext) {\n if (options.minLevel !== undefined && event.level < toLevelValue(options.minLevel)) return;\n writePayload(codec.encode(event), context);\n },\n logBatch(events: LogEvent[], context?: TransportContext) {\n for (const event of events) {\n if (options.minLevel !== undefined && event.level < toLevelValue(options.minLevel))\n continue;\n writePayload(codec.encode(event), context);\n }\n },\n flush() {\n return destination.flush();\n },\n flushSync: destination.flushSync,\n close() {\n return destination.close();\n },\n rotate,\n currentBytes: () => bytes,\n };\n\n return transport;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"rotating-file-transport.d.ts","sourceRoot":"","sources":["../src/rotating-file-transport.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,KAAK,EAEV,KAAK,WAAW,EAChB,KAAK,SAAS,EACf,MAAM,gBAAgB,CAAC;AAGxB,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACvD;AAED,MAAM,WAAW,qBAAsB,SAAQ,SAAS;IACtD,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,MAAM,CAAC;CAC5B;AA8BD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,4BAA4B,GACpC,qBAAqB,CAqEvB"}
1
+ {"version":3,"file":"rotating-file-transport.d.ts","sourceRoot":"","sources":["../src/rotating-file-transport.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,KAAK,EAEV,KAAK,WAAW,EAChB,KAAK,SAAS,EAEf,MAAM,gBAAgB,CAAC;AAGxB,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACvD;AAED,MAAM,WAAW,qBAAsB,SAAQ,SAAS;IACtD,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,MAAM,CAAC;CAC5B;AA8BD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,4BAA4B,GACpC,qBAAqB,CAuFvB"}
@@ -1,234 +1,6 @@
1
- import { closeSync, createWriteStream, existsSync, mkdirSync, openSync, renameSync, statSync, unlinkSync, writeSync } from "fs";
2
- import { ndjsonCodec, toLevelValue } from "@loggerjs/core";
3
- import { dirname } from "path";
4
- //#region src/node-destination.ts
5
- const encoder = new TextEncoder();
6
- const normalizeError = (error) => error instanceof Error ? error : new Error(String(error));
7
- function byteLength(payload) {
8
- return typeof payload === "string" ? encoder.encode(payload).byteLength : payload.byteLength;
9
- }
10
- function coalescePayloads(payloads) {
11
- if (payloads.every((payload) => typeof payload === "string")) return payloads.join("");
12
- const buffers = payloads.map((payload) => typeof payload === "string" ? Buffer.from(payload) : Buffer.from(payload));
13
- return Buffer.concat(buffers);
14
- }
15
- function isEpipe(error) {
16
- return Boolean(error) && typeof error === "object" && error.code === "EPIPE";
17
- }
18
- function normalizeMinLength(value) {
19
- if (value === void 0 || !Number.isFinite(value) || value <= 0) return 0;
20
- return Math.floor(value);
21
- }
22
- function createNodeStreamDestination(options) {
23
- const minLength = normalizeMinLength(options.minLength);
24
- const ignoreEpipe = options.ignoreEpipe ?? false;
25
- const waiters = [];
26
- const buffer = [];
27
- const pendingPayloads = [];
28
- let bufferedBytes = 0;
29
- let pendingWrites = 0;
30
- let pendingDrains = 0;
31
- let lastError;
32
- let lastContext;
33
- let closed = false;
34
- const reportInternalError = (error, operation) => {
35
- if (ignoreEpipe && isEpipe(error)) return;
36
- lastContext?.reportInternalError(error, {
37
- phase: "transport",
38
- transport: options.name,
39
- operation
40
- });
41
- };
42
- const settleWaitersIfIdle = () => {
43
- if (pendingWrites + pendingDrains > 0) return;
44
- if (waiters.length === 0) return;
45
- const error = lastError;
46
- lastError = void 0;
47
- for (const waiter of waiters.splice(0)) if (error) waiter.reject(error);
48
- else waiter.resolve();
49
- };
50
- const recordError = (error, operation) => {
51
- if (ignoreEpipe && isEpipe(error)) {
52
- closed = true;
53
- return;
54
- }
55
- lastError = normalizeError(error);
56
- reportInternalError(lastError, operation);
57
- };
58
- const onStreamError = (error) => {
59
- recordError(error, "stream-error");
60
- settleWaitersIfIdle();
61
- };
62
- const offError = () => options.stream.off?.("error", onStreamError);
63
- options.stream.on?.("error", onStreamError);
64
- const waitForDrain = () => {
65
- if (!options.stream.once) return;
66
- pendingDrains += 1;
67
- options.stream.once("drain", () => {
68
- pendingDrains -= 1;
69
- settleWaitersIfIdle();
70
- });
71
- };
72
- const removePending = (payload) => {
73
- const index = pendingPayloads.indexOf(payload);
74
- if (index >= 0) pendingPayloads.splice(index, 1);
75
- };
76
- const writeNow = (payload) => {
77
- if (closed) return;
78
- pendingPayloads.push(payload);
79
- pendingWrites += 1;
80
- try {
81
- if (options.stream.write(payload, (error) => {
82
- removePending(payload);
83
- pendingWrites -= 1;
84
- if (error) recordError(error, options.reportOperation ?? "write");
85
- settleWaitersIfIdle();
86
- }) === false) waitForDrain();
87
- } catch (error) {
88
- removePending(payload);
89
- pendingWrites -= 1;
90
- recordError(error, options.reportOperation ?? "write");
91
- settleWaitersIfIdle();
92
- }
93
- };
94
- const flushBuffered = () => {
95
- if (buffer.length === 0) return;
96
- const payload = coalescePayloads(buffer.splice(0));
97
- bufferedBytes = 0;
98
- writeNow(payload);
99
- };
100
- const destination = {
101
- write(payload, context) {
102
- if (closed) return;
103
- lastContext = context;
104
- if (minLength > 0) {
105
- buffer.push(payload);
106
- bufferedBytes += byteLength(payload);
107
- if (bufferedBytes >= minLength) flushBuffered();
108
- return;
109
- }
110
- writeNow(payload);
111
- },
112
- flush() {
113
- flushBuffered();
114
- if (pendingWrites + pendingDrains === 0) {
115
- const error = lastError;
116
- lastError = void 0;
117
- if (error) return Promise.reject(error);
118
- return Promise.resolve();
119
- }
120
- return new Promise((resolve, reject) => {
121
- waiters.push({
122
- resolve,
123
- reject
124
- });
125
- });
126
- },
127
- flushSync() {
128
- if (!options.syncWrite) {
129
- flushBuffered();
130
- return;
131
- }
132
- for (const payload of buffer.splice(0)) options.syncWrite(payload);
133
- bufferedBytes = 0;
134
- for (const payload of pendingPayloads.splice(0)) options.syncWrite(payload);
135
- },
136
- close() {
137
- return destination.flush().then(() => new Promise((resolve, reject) => {
138
- if (!options.stream.end) {
139
- closed = true;
140
- offError();
141
- resolve();
142
- return;
143
- }
144
- options.stream.end((error) => {
145
- closed = true;
146
- offError();
147
- if (error && !(ignoreEpipe && isEpipe(error))) reject(error);
148
- else resolve();
149
- });
150
- }), (error) => {
151
- offError();
152
- return Promise.reject(error);
153
- });
154
- },
155
- closeSync() {
156
- destination.flushSync();
157
- closed = true;
158
- offError();
159
- }
160
- };
161
- return destination;
162
- }
163
- function createNodeFileDestination(options) {
164
- const flags = options.flags ?? (options.append === false ? "w" : "a");
165
- if (options.mkdir) mkdirSync(dirname(options.path), { recursive: true });
166
- let fd;
167
- const syncFlags = options.sync ? flags : "a";
168
- const getFd = () => {
169
- fd ??= openSync(options.path, syncFlags);
170
- return fd;
171
- };
172
- const syncWrite = (payload) => {
173
- if (typeof payload === "string") writeSync(getFd(), payload);
174
- else writeSync(getFd(), payload);
175
- };
176
- if (options.sync) {
177
- let closed = false;
178
- const releaseSync = () => {
179
- if (fd !== void 0) {
180
- closeSync(fd);
181
- fd = void 0;
182
- }
183
- };
184
- return {
185
- write(payload) {
186
- if (closed) return;
187
- syncWrite(payload);
188
- },
189
- flush() {
190
- return Promise.resolve();
191
- },
192
- flushSync() {},
193
- close() {
194
- releaseSync();
195
- closed = true;
196
- return Promise.resolve();
197
- },
198
- closeSync() {
199
- releaseSync();
200
- closed = true;
201
- },
202
- releaseSync
203
- };
204
- }
205
- const stream = createWriteStream(options.path, { flags });
206
- const destination = createNodeStreamDestination({
207
- name: options.name,
208
- stream,
209
- minLength: options.minLength,
210
- syncWrite
211
- });
212
- const releaseSync = () => {
213
- if (fd !== void 0) {
214
- closeSync(fd);
215
- fd = void 0;
216
- }
217
- };
218
- return {
219
- ...destination,
220
- stream,
221
- close() {
222
- return destination.close().finally(releaseSync);
223
- },
224
- closeSync() {
225
- destination.closeSync();
226
- releaseSync();
227
- },
228
- releaseSync
229
- };
230
- }
231
- //#endregion
1
+ import { t as createNodeFileDestination } from "./chunks/node-destination-YnpYbctz.js";
2
+ import { ndjsonEncoder, toLevelValue } from "@loggerjs/core";
3
+ import { existsSync, renameSync, statSync, unlinkSync } from "fs";
232
4
  //#region src/rotating-file-transport.ts
233
5
  const textEncoder = new TextEncoder();
234
6
  function payloadBytes(payload) {
@@ -253,7 +25,7 @@ function fileSize(path) {
253
25
  }
254
26
  }
255
27
  function rotatingFileTransport(options) {
256
- const codec = options.codec ?? ndjsonCodec();
28
+ const codec = options.codec ?? ndjsonEncoder();
257
29
  const maxBytes = normalizePositiveInteger(options.maxBytes, 10 * 1024 * 1024);
258
30
  const maxFiles = normalizeNonNegativeInteger(options.maxFiles, 5);
259
31
  const archivePath = options.archivePath ?? defaultArchivePath;
@@ -266,11 +38,13 @@ function rotatingFileTransport(options) {
266
38
  sync: true
267
39
  });
268
40
  let bytes = fileSize(options.path);
41
+ let rotateAt = maxBytes;
269
42
  const rotate = () => {
270
43
  destination.releaseSync?.();
271
44
  if (maxFiles === 0) {
272
45
  if (existsSync(options.path)) unlinkSync(options.path);
273
46
  bytes = 0;
47
+ rotateAt = maxBytes;
274
48
  return;
275
49
  }
276
50
  const oldest = archivePath(options.path, maxFiles);
@@ -281,24 +55,34 @@ function rotatingFileTransport(options) {
281
55
  }
282
56
  if (existsSync(options.path)) renameSync(options.path, archivePath(options.path, 1));
283
57
  bytes = 0;
58
+ rotateAt = maxBytes;
284
59
  };
285
- const writePayload = (payload) => {
60
+ const writePayload = (payload, context) => {
286
61
  const size = payloadBytes(payload);
287
- if (bytes > 0 && bytes + size > maxBytes) rotate();
62
+ if (bytes > 0 && bytes + size > rotateAt) try {
63
+ rotate();
64
+ } catch (error) {
65
+ rotateAt = bytes + size + maxBytes;
66
+ context?.reportInternalError(error, {
67
+ phase: "transport",
68
+ transport: transport.name,
69
+ operation: "rotate"
70
+ });
71
+ }
288
72
  destination.write(payload);
289
73
  bytes += size;
290
74
  };
291
- return {
75
+ const transport = {
292
76
  name: options.name ?? "rotating-file",
293
77
  minLevel: options.minLevel,
294
- log(event) {
78
+ log(event, context) {
295
79
  if (options.minLevel !== void 0 && event.level < toLevelValue(options.minLevel)) return;
296
- writePayload(codec.encode(event));
80
+ writePayload(codec.encode(event), context);
297
81
  },
298
- logBatch(events) {
82
+ logBatch(events, context) {
299
83
  for (const event of events) {
300
84
  if (options.minLevel !== void 0 && event.level < toLevelValue(options.minLevel)) continue;
301
- writePayload(codec.encode(event));
85
+ writePayload(codec.encode(event), context);
302
86
  }
303
87
  },
304
88
  flush() {
@@ -311,6 +95,7 @@ function rotatingFileTransport(options) {
311
95
  rotate,
312
96
  currentBytes: () => bytes
313
97
  };
98
+ return transport;
314
99
  }
315
100
  //#endregion
316
101
  export { rotatingFileTransport };