logixia 1.13.0 → 2.0.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 (176) hide show
  1. package/README.md +81 -16
  2. package/dist/{async-context-CwBNMm2E.mjs → async-context-BzJrbfQs.mjs} +8 -4
  3. package/dist/async-context-BzJrbfQs.mjs.map +1 -0
  4. package/dist/{async-context-CSHWoHMB.js → async-context-DyQQYq3I.js} +8 -4
  5. package/dist/async-context-DyQQYq3I.js.map +1 -0
  6. package/dist/{azure-monitor.transport-CG7ClkYj.d.ts → azure-monitor.transport-Cn_3Usvu.d.ts} +2 -2
  7. package/dist/{azure-monitor.transport-CG7ClkYj.d.ts.map → azure-monitor.transport-Cn_3Usvu.d.ts.map} +1 -1
  8. package/dist/{azure-monitor.transport-Cm74kXZS.d.mts → azure-monitor.transport-D7Da4RAb.d.mts} +2 -2
  9. package/dist/{azure-monitor.transport-Cm74kXZS.d.mts.map → azure-monitor.transport-D7Da4RAb.d.mts.map} +1 -1
  10. package/dist/azure.d.mts +2 -2
  11. package/dist/azure.d.ts +2 -2
  12. package/dist/browser.d.mts +9 -0
  13. package/dist/browser.d.mts.map +1 -1
  14. package/dist/browser.d.ts +9 -0
  15. package/dist/browser.d.ts.map +1 -1
  16. package/dist/browser.js +43 -12
  17. package/dist/browser.js.map +1 -1
  18. package/dist/browser.mjs +43 -12
  19. package/dist/browser.mjs.map +1 -1
  20. package/dist/{logitron-logger.module-Bs3XYZgF.mjs → builder-0gEzRopq.mjs} +383 -1021
  21. package/dist/builder-0gEzRopq.mjs.map +1 -0
  22. package/dist/{logitron-logger.module-BsDZR5BH.js → builder-D44QktIo.js} +411 -1155
  23. package/dist/builder-D44QktIo.js.map +1 -0
  24. package/dist/cli/index.js +130 -65
  25. package/dist/cloudwatch.d.mts +2 -2
  26. package/dist/cloudwatch.d.ts +2 -2
  27. package/dist/cloudwatch.js +2 -1
  28. package/dist/cloudwatch.mjs +2 -1
  29. package/dist/{cloudwatch.transport-pNBNWJLt.js → cloudwatch.transport-BO1ahxw-.js} +26 -19
  30. package/dist/cloudwatch.transport-BO1ahxw-.js.map +1 -0
  31. package/dist/{cloudwatch.transport-yBwm4OeO.mjs → cloudwatch.transport-DZ6ies7g.mjs} +26 -19
  32. package/dist/cloudwatch.transport-DZ6ies7g.mjs.map +1 -0
  33. package/dist/{cloudwatch.transport-CGHY4buE.d.mts → cloudwatch.transport-DsEq633o.d.ts} +9 -2
  34. package/dist/cloudwatch.transport-DsEq633o.d.ts.map +1 -0
  35. package/dist/{cloudwatch.transport-DK_8cKd3.d.ts → cloudwatch.transport-UlyZFWMn.d.mts} +9 -2
  36. package/dist/cloudwatch.transport-UlyZFWMn.d.mts.map +1 -0
  37. package/dist/{coerce.utils-BN980Y9V.js → coerce.utils-B-LilukN.js} +1 -1
  38. package/dist/{coerce.utils-BN980Y9V.js.map → coerce.utils-B-LilukN.js.map} +1 -1
  39. package/dist/{coerce.utils-Dxv4_ikC.mjs → coerce.utils-Cu6IUTgX.mjs} +1 -1
  40. package/dist/{coerce.utils-Dxv4_ikC.mjs.map → coerce.utils-Cu6IUTgX.mjs.map} +1 -1
  41. package/dist/correlation.d.mts +24 -6
  42. package/dist/correlation.d.mts.map +1 -1
  43. package/dist/correlation.d.ts +24 -6
  44. package/dist/correlation.d.ts.map +1 -1
  45. package/dist/correlation.js +41 -16
  46. package/dist/correlation.js.map +1 -1
  47. package/dist/correlation.mjs +41 -16
  48. package/dist/correlation.mjs.map +1 -1
  49. package/dist/entry-fields-BJkuPnIg.mjs +30 -0
  50. package/dist/entry-fields-BJkuPnIg.mjs.map +1 -0
  51. package/dist/entry-fields-BvOLFlJ4.js +36 -0
  52. package/dist/entry-fields-BvOLFlJ4.js.map +1 -0
  53. package/dist/gcp.d.mts +2 -2
  54. package/dist/gcp.d.ts +2 -2
  55. package/dist/gcp.js +2 -1
  56. package/dist/gcp.mjs +2 -1
  57. package/dist/{gcp.transport-BOhkVKlI.d.ts → gcp.transport-B7oc97sG.d.ts} +2 -2
  58. package/dist/gcp.transport-B7oc97sG.d.ts.map +1 -0
  59. package/dist/{gcp.transport-SHdtc1n0.js → gcp.transport-CHV8MGgz.js} +5 -5
  60. package/dist/gcp.transport-CHV8MGgz.js.map +1 -0
  61. package/dist/{gcp.transport-BJuNRFe_.mjs → gcp.transport-DBX5TPIy.mjs} +5 -5
  62. package/dist/gcp.transport-DBX5TPIy.mjs.map +1 -0
  63. package/dist/{gcp.transport-Bi6CUqZR.d.mts → gcp.transport-GrJurKo8.d.mts} +2 -2
  64. package/dist/gcp.transport-GrJurKo8.d.mts.map +1 -0
  65. package/dist/{index-BPKwwERo.d.mts → index-3mw5gaCw.d.mts} +2 -2
  66. package/dist/{index-BPKwwERo.d.mts.map → index-3mw5gaCw.d.mts.map} +1 -1
  67. package/dist/{index-C1X-TE5I.d.ts → index-DhIoploR.d.ts} +2 -2
  68. package/dist/{index-C1X-TE5I.d.ts.map → index-DhIoploR.d.ts.map} +1 -1
  69. package/dist/index.d.mts +99 -137
  70. package/dist/index.d.mts.map +1 -1
  71. package/dist/index.d.ts +99 -137
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +146 -510
  74. package/dist/index.js.map +1 -1
  75. package/dist/index.mjs +99 -431
  76. package/dist/index.mjs.map +1 -1
  77. package/dist/logitron-logger-BFDSO8Io.d.mts +257 -0
  78. package/dist/logitron-logger-BFDSO8Io.d.mts.map +1 -0
  79. package/dist/logitron-logger-UVeN-mQm.d.ts +257 -0
  80. package/dist/logitron-logger-UVeN-mQm.d.ts.map +1 -0
  81. package/dist/middleware.d.mts +11 -4
  82. package/dist/middleware.d.mts.map +1 -1
  83. package/dist/middleware.d.ts +11 -4
  84. package/dist/middleware.d.ts.map +1 -1
  85. package/dist/middleware.js +148 -24
  86. package/dist/middleware.js.map +1 -1
  87. package/dist/middleware.mjs +148 -24
  88. package/dist/middleware.mjs.map +1 -1
  89. package/dist/nest.d.mts +481 -6
  90. package/dist/nest.d.mts.map +1 -1
  91. package/dist/nest.d.ts +481 -6
  92. package/dist/nest.d.ts.map +1 -1
  93. package/dist/nest.js +884 -13
  94. package/dist/nest.js.map +1 -0
  95. package/dist/nest.mjs +863 -6
  96. package/dist/nest.mjs.map +1 -0
  97. package/dist/{search-CFQRISUv.mjs → search-BFbu_oVn.mjs} +35 -12
  98. package/dist/search-BFbu_oVn.mjs.map +1 -0
  99. package/dist/{search-njTI2hdo.js → search-C4V0OMEn.js} +35 -12
  100. package/dist/search-C4V0OMEn.js.map +1 -0
  101. package/dist/{search-DujhR94O.d.ts → search-CNh9uVwR.d.ts} +2 -3
  102. package/dist/search-CNh9uVwR.d.ts.map +1 -0
  103. package/dist/{search-CQOo-Iq6.d.mts → search-DXANsQ2n.d.mts} +2 -3
  104. package/dist/search-DXANsQ2n.d.mts.map +1 -0
  105. package/dist/search.d.mts +3 -3
  106. package/dist/search.d.ts +3 -3
  107. package/dist/search.js +2 -2
  108. package/dist/search.mjs +2 -2
  109. package/dist/slack.transport-BZzoXDPn.d.mts +112 -0
  110. package/dist/slack.transport-BZzoXDPn.d.mts.map +1 -0
  111. package/dist/slack.transport-BfJRouB2.js +654 -0
  112. package/dist/slack.transport-BfJRouB2.js.map +1 -0
  113. package/dist/slack.transport-Bzw7sucI.mjs +643 -0
  114. package/dist/slack.transport-Bzw7sucI.mjs.map +1 -0
  115. package/dist/slack.transport-CXjQYOes.d.ts +112 -0
  116. package/dist/slack.transport-CXjQYOes.d.ts.map +1 -0
  117. package/dist/testing.d.mts +2 -2
  118. package/dist/testing.d.ts +2 -2
  119. package/dist/trace.utils-CvXgaiQT.mjs +278 -0
  120. package/dist/trace.utils-CvXgaiQT.mjs.map +1 -0
  121. package/dist/trace.utils-DpBOLDtq.js +358 -0
  122. package/dist/trace.utils-DpBOLDtq.js.map +1 -0
  123. package/dist/{transport.manager-D6KL3t9V.mjs → transport.manager-BiuCAJd2.mjs} +526 -160
  124. package/dist/transport.manager-BiuCAJd2.mjs.map +1 -0
  125. package/dist/{transport.manager-BivyUTtU.js → transport.manager-CXbKKdVE.js} +537 -159
  126. package/dist/transport.manager-CXbKKdVE.js.map +1 -0
  127. package/dist/{transport.types-B5vcyv2k.d.mts → transport.types-BMnurPcc.d.mts} +23 -3
  128. package/dist/transport.types-BMnurPcc.d.mts.map +1 -0
  129. package/dist/{transport.types-BuY84TwO.d.ts → transport.types-CGoHpWQR.d.ts} +23 -3
  130. package/dist/transport.types-CGoHpWQR.d.ts.map +1 -0
  131. package/dist/transports.d.mts +50 -20
  132. package/dist/transports.d.mts.map +1 -1
  133. package/dist/transports.d.ts +50 -20
  134. package/dist/transports.d.ts.map +1 -1
  135. package/dist/transports.js +9 -5
  136. package/dist/transports.mjs +8 -6
  137. package/dist/worker-entry.js +307 -55
  138. package/dist/worker.d.mts +2 -2
  139. package/dist/worker.d.ts +2 -2
  140. package/dist/worker.js +1 -1
  141. package/dist/worker.mjs +1 -1
  142. package/dist/{worker.transport-CfH6z37Z.js → worker.transport-BdPxu3PN.js} +1 -1
  143. package/dist/{worker.transport-CfH6z37Z.js.map → worker.transport-BdPxu3PN.js.map} +1 -1
  144. package/dist/{worker.transport-mKXgNK0L.d.ts → worker.transport-CdzSZJmw.d.ts} +2 -2
  145. package/dist/{worker.transport-mKXgNK0L.d.ts.map → worker.transport-CdzSZJmw.d.ts.map} +1 -1
  146. package/dist/{worker.transport-BP8Q28Z2.d.mts → worker.transport-JvGPog3C.d.mts} +2 -2
  147. package/dist/{worker.transport-BP8Q28Z2.d.mts.map → worker.transport-JvGPog3C.d.mts.map} +1 -1
  148. package/dist/{worker.transport-BhMyvqQ2.mjs → worker.transport-lPxO2MVL.mjs} +1 -1
  149. package/dist/{worker.transport-BhMyvqQ2.mjs.map → worker.transport-lPxO2MVL.mjs.map} +1 -1
  150. package/package.json +27 -14
  151. package/dist/.tsbuildinfo +0 -1
  152. package/dist/async-context-CSHWoHMB.js.map +0 -1
  153. package/dist/async-context-CwBNMm2E.mjs.map +0 -1
  154. package/dist/cloudwatch.transport-CGHY4buE.d.mts.map +0 -1
  155. package/dist/cloudwatch.transport-DK_8cKd3.d.ts.map +0 -1
  156. package/dist/cloudwatch.transport-pNBNWJLt.js.map +0 -1
  157. package/dist/cloudwatch.transport-yBwm4OeO.mjs.map +0 -1
  158. package/dist/gcp.transport-BJuNRFe_.mjs.map +0 -1
  159. package/dist/gcp.transport-BOhkVKlI.d.ts.map +0 -1
  160. package/dist/gcp.transport-Bi6CUqZR.d.mts.map +0 -1
  161. package/dist/gcp.transport-SHdtc1n0.js.map +0 -1
  162. package/dist/logitron-logger.module-BdG1Jnpk.d.mts +0 -618
  163. package/dist/logitron-logger.module-BdG1Jnpk.d.mts.map +0 -1
  164. package/dist/logitron-logger.module-Bs3XYZgF.mjs.map +0 -1
  165. package/dist/logitron-logger.module-BsDZR5BH.js.map +0 -1
  166. package/dist/logitron-logger.module-CbXy2gfW.d.ts +0 -618
  167. package/dist/logitron-logger.module-CbXy2gfW.d.ts.map +0 -1
  168. package/dist/search-CFQRISUv.mjs.map +0 -1
  169. package/dist/search-CQOo-Iq6.d.mts.map +0 -1
  170. package/dist/search-DujhR94O.d.ts.map +0 -1
  171. package/dist/search-njTI2hdo.js.map +0 -1
  172. package/dist/transport.manager-BivyUTtU.js.map +0 -1
  173. package/dist/transport.manager-D6KL3t9V.mjs.map +0 -1
  174. package/dist/transport.types-B5vcyv2k.d.mts.map +0 -1
  175. package/dist/transport.types-BuY84TwO.d.ts.map +0 -1
  176. package/scripts/postinstall.js +0 -61
@@ -155,6 +155,52 @@ function stringifyForLog(value) {
155
155
  }
156
156
  }
157
157
 
158
+ //#endregion
159
+ //#region src/utils/sanitize.utils.ts
160
+ /**
161
+ * Control-character stripping for text-mode log output.
162
+ *
163
+ * Line breaks become the visible escapes `\\n` / `\\r`; other C0 characters
164
+ * (except tab), DEL and C1 characters are removed, so user-supplied text cannot
165
+ * inject ANSI escapes, overwrite lines, or forge extra log entries.
166
+ */
167
+ const CONTROL_CHARS_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]/g;
168
+ const VISIBLE_ESCAPES = {
169
+ "\n": "\\n",
170
+ "\r": "\\r"
171
+ };
172
+ function stripControlChars(value) {
173
+ return value.replace(CONTROL_CHARS_RE, (ch) => VISIBLE_ESCAPES[ch] ?? "");
174
+ }
175
+
176
+ //#endregion
177
+ //#region src/transports/entry-fields.ts
178
+ const PAYLOAD_PREFIX = "data_";
179
+ const UNSAFE_KEYS = new Set(["__proto__"]);
180
+ /**
181
+ * Copies `core` and then the user payload into one object. The core fields stay
182
+ * authoritative: a payload key that matches a core key (even one whose value is
183
+ * undefined) or a reserved name is kept under a `data_` prefix instead. The
184
+ * prefix is repeated until the name is free of core keys and of every other
185
+ * payload key, so the result does not depend on key order and a payload's own
186
+ * `data_level` stays where it is.
187
+ */
188
+ function mergeCoreFields(core, data, extraReserved = []) {
189
+ const merged = { ...core };
190
+ if (!data) return merged;
191
+ const reserved = new Set([...Object.keys(core), ...extraReserved]);
192
+ const payloadKeys = new Set(Object.keys(data));
193
+ for (const key of payloadKeys) {
194
+ if (UNSAFE_KEYS.has(key)) continue;
195
+ let target = key;
196
+ if (reserved.has(target)) do
197
+ target = `${PAYLOAD_PREFIX}${target}`;
198
+ while (reserved.has(target) || payloadKeys.has(target));
199
+ merged[target] = data[key];
200
+ }
201
+ return merged;
202
+ }
203
+
158
204
  //#endregion
159
205
  //#region src/transports/console.transport.ts
160
206
  /**
@@ -186,9 +232,8 @@ var ConsoleTransport = class ConsoleTransport {
186
232
  ["brightwhite", "\x1B[97m"],
187
233
  ["reset", "\x1B[0m"]
188
234
  ]);
189
- static #_2 = this.CONTROL_CHARS_RE = /[\x00-\x08\x0B-\x1F\x7F-\x9F]/g;
190
235
  static sanitize(value) {
191
- return safeToString(value).replace(ConsoleTransport.CONTROL_CHARS_RE, "");
236
+ return stripControlChars(safeToString(value));
192
237
  }
193
238
  constructor(config = {}) {
194
239
  this.config = config;
@@ -201,16 +246,15 @@ var ConsoleTransport = class ConsoleTransport {
201
246
  (lvl === "error" || lvl === "warn" ? process.stderr : process.stdout).write(formatted);
202
247
  }
203
248
  formatEntry(entry) {
204
- if (this.config.format === "json") return stringifyForLog({
249
+ if (this.config.format === "json") return stringifyForLog(mergeCoreFields({
205
250
  timestamp: this.config.timestamp !== false ? entry.timestamp.toISOString() : void 0,
206
251
  level: entry.level,
207
252
  message: entry.message,
208
- ...entry.data || {},
209
253
  context: entry.context,
210
254
  traceId: entry.traceId,
211
255
  appName: entry.appName,
212
256
  environment: entry.environment
213
- });
257
+ }, entry.data));
214
258
  const parts = [];
215
259
  if (this.config.timestamp !== false) {
216
260
  const timestamp = entry.timestamp.toISOString();
@@ -300,6 +344,47 @@ function internalError(message, error) {
300
344
  }
301
345
  }
302
346
 
347
+ //#endregion
348
+ //#region src/transports/buffer-cap.ts
349
+ const DEFAULT_BUFFER_CAP = 1e4;
350
+ const DROP_WARN_INTERVAL_MS$1 = 5e3;
351
+ /**
352
+ * Keeps an in-memory retry buffer bounded. Past `max` the oldest items are
353
+ * dropped, counted, and reported through internalWarn at most every few seconds.
354
+ *
355
+ * `requested` must be an integer of at least 1, otherwise the default is used.
356
+ * A cap below `batchSize` is raised to `batchSize` so one batch always fits.
357
+ */
358
+ var BufferCap = class {
359
+ constructor(name, requested, batchSize, fallback = DEFAULT_BUFFER_CAP) {
360
+ this.name = name;
361
+ this.dropped = 0;
362
+ this.lastWarning = 0;
363
+ let max = fallback;
364
+ if (requested !== void 0) if (Number.isInteger(requested) && requested >= 1) max = requested;
365
+ else internalWarn(`${name}: maxBufferSize ${String(requested)} is not a positive integer; using ${fallback}`);
366
+ this.max = Math.max(max, batchSize);
367
+ }
368
+ /** Drops the oldest items beyond the cap, in place. */
369
+ enforce(items) {
370
+ const excess = items.length - this.max;
371
+ if (excess <= 0) return;
372
+ items.splice(0, excess);
373
+ this.note(excess);
374
+ }
375
+ note(count) {
376
+ this.dropped += count;
377
+ this.report(DROP_WARN_INTERVAL_MS$1);
378
+ }
379
+ report(minGapMs) {
380
+ const now = Date.now();
381
+ if (this.dropped === 0 || now - this.lastWarning < minGapMs) return;
382
+ internalWarn(`${this.name}: buffer full (${this.max}), dropped ${this.dropped} oldest entr${this.dropped === 1 ? "y" : "ies"}`);
383
+ this.dropped = 0;
384
+ this.lastWarning = now;
385
+ }
386
+ };
387
+
303
388
  //#endregion
304
389
  //#region src/transports/database.transport.ts
305
390
  /**
@@ -310,6 +395,80 @@ const POSTGRES_MAX_PARAMS = 65535;
310
395
  const POSTGRES_COLUMNS = 8;
311
396
  const POSTGRES_ROWS_PER_INSERT = Math.floor(POSTGRES_MAX_PARAMS / POSTGRES_COLUMNS);
312
397
  const MYSQL_ROWS_PER_INSERT = 5e3;
398
+ /** Postgres rejects NUL in TEXT and JSONB. */
399
+ function stripNul(value) {
400
+ return typeof value === "string" ? value.split("\0").join("") : value;
401
+ }
402
+ /** JSONB also rejects the \u0000 escape, which JSON.stringify writes for a NUL. */
403
+ function stripJsonNulEscape(value) {
404
+ if (typeof value !== "string") return value;
405
+ return value.replace(/(?<!\\)((?:\\\\)*)\\u0000/g, "$1");
406
+ }
407
+ const PG_DATA_CLASSES = [
408
+ "22",
409
+ "23",
410
+ "54"
411
+ ];
412
+ const MYSQL_DATA_CODES = new Set([
413
+ "ER_DATA_TOO_LONG",
414
+ "ER_TRUNCATED_WRONG_VALUE",
415
+ "ER_TRUNCATED_WRONG_VALUE_FOR_FIELD",
416
+ "ER_BAD_NULL_ERROR",
417
+ "ER_WARN_DATA_OUT_OF_RANGE",
418
+ "ER_DUP_ENTRY",
419
+ "ER_INVALID_JSON_TEXT",
420
+ "ER_INVALID_CHARACTER_STRING"
421
+ ]);
422
+ const MYSQL_DATA_ERRNOS = new Set([
423
+ 1048,
424
+ 1062,
425
+ 1264,
426
+ 1292,
427
+ 1366,
428
+ 1406,
429
+ 3140
430
+ ]);
431
+ const SQLITE_DATA_CODES = new Set([
432
+ "SQLITE_CONSTRAINT",
433
+ "SQLITE_TOOBIG",
434
+ "SQLITE_MISMATCH"
435
+ ]);
436
+ const MONGO_DATA_CODES = new Set([
437
+ 2,
438
+ 121,
439
+ 10334,
440
+ 11e3
441
+ ]);
442
+ function isDataErrorLayer(type, e) {
443
+ const code = e.code;
444
+ switch (type) {
445
+ case "postgresql": return typeof code === "string" && PG_DATA_CLASSES.includes(code.slice(0, 2));
446
+ case "mysql": return typeof code === "string" && MYSQL_DATA_CODES.has(code) || typeof e.errno === "number" && MYSQL_DATA_ERRNOS.has(e.errno);
447
+ case "sqlite": return typeof code === "string" && (SQLITE_DATA_CODES.has(code) || code.startsWith("SQLITE_CONSTRAINT_"));
448
+ case "mongodb": return e.name === "BSONObjectTooLarge" || typeof code === "number" && MONGO_DATA_CODES.has(code);
449
+ default: return false;
450
+ }
451
+ }
452
+ /**
453
+ * True when the database refused the data itself (bad value, constraint, size),
454
+ * which retrying cannot fix. Connection, timeout, auth and unknown errors are
455
+ * not data errors and must be retried, never dropped.
456
+ */
457
+ function isDataError(type, error) {
458
+ let current = error;
459
+ for (let depth = 0; depth < 3 && current && typeof current === "object"; depth += 1) {
460
+ if (isDataErrorLayer(type, current)) return true;
461
+ current = current.cause;
462
+ }
463
+ return false;
464
+ }
465
+ /** A write that stored part of a batch: only `remaining` still needs to be written. */
466
+ var PartialWriteError = class extends Error {
467
+ constructor(message, remaining, cause) {
468
+ super(message, { cause });
469
+ this.remaining = remaining;
470
+ }
471
+ };
313
472
  function chunk(items, size) {
314
473
  const chunks = [];
315
474
  for (let i = 0; i < items.length; i += size) chunks.push(items.slice(i, i + size));
@@ -338,6 +497,7 @@ var DatabaseTransport = class {
338
497
  this.isConnected = false;
339
498
  this.batchSize = config.batchSize || 100;
340
499
  this.flushInterval = config.flushInterval || 5e3;
500
+ this.cap = new BufferCap("DatabaseTransport", config.maxBufferSize, this.batchSize);
341
501
  if (config.filter) this.filter = config.filter;
342
502
  if (config.table) validateSqlIdentifier(config.table, "table");
343
503
  this.setupFlushTimer();
@@ -349,6 +509,7 @@ var DatabaseTransport = class {
349
509
  }
350
510
  addToBatch(entry) {
351
511
  this.batch.push(entry);
512
+ this.cap.enforce(this.batch);
352
513
  }
353
514
  async flush() {
354
515
  if (!this.flushPromise) this.flushPromise = this.drain().finally(() => {
@@ -357,37 +518,97 @@ var DatabaseTransport = class {
357
518
  await this.flushPromise;
358
519
  }
359
520
  /**
360
- * Drains the batch to the database one snapshot at a time. The current batch
361
- * is detached SYNCHRONOUSLY before awaiting the write, so entries appended by
362
- * concurrent write() calls land in a fresh array and are never written twice.
363
- * On write failure the snapshot is restored to the front of the batch for the
364
- * next flush cycle and the loop stops, so a persistently failing DB does not
365
- * hot-spin retrying the same entries.
521
+ * Drains the buffer to the database one batch at a time. A batch is detached
522
+ * SYNCHRONOUSLY before awaiting the write, so entries appended by concurrent
523
+ * write() calls land in a fresh array and are never written twice.
524
+ *
525
+ * A failure that is not a data error (connection, timeout, auth, unknown) puts
526
+ * the batch back at the front of the buffer, bounded by `maxBufferSize`, and
527
+ * stops the loop so a down database is not hammered. A data error means the
528
+ * database refused some entry itself, so that batch alone is split to find and
529
+ * drop the refused entries; see isolate().
366
530
  */
367
531
  async drain() {
368
532
  while (this.batch.length > 0) {
369
- const entriesToFlush = this.batch;
370
- this.batch = [];
533
+ const entries = this.batch.splice(0, this.batchSize);
371
534
  try {
372
- switch (this.config.type) {
373
- case "mongodb":
374
- await this.flushToMongoDB(entriesToFlush);
375
- break;
376
- case "postgresql":
377
- await this.flushToPostgreSQL(entriesToFlush);
378
- break;
379
- case "mysql":
380
- await this.flushToMySQL(entriesToFlush);
381
- break;
382
- case "sqlite":
383
- await this.flushToSQLite(entriesToFlush);
384
- break;
385
- default: throw new Error(`Unsupported database type: ${this.config.type}`);
386
- }
535
+ await this.writeEntries(entries);
387
536
  } catch (error) {
388
537
  internalError("Database flush error", error);
389
- this.batch.unshift(...entriesToFlush);
390
- throw error;
538
+ if (error instanceof PartialWriteError) {
539
+ this.requeue(error.remaining);
540
+ throw error.cause;
541
+ }
542
+ if (!isDataError(this.config.type, error)) {
543
+ this.requeue(entries);
544
+ throw error;
545
+ }
546
+ const state = {
547
+ budget: 2 * this.batchSize,
548
+ rejected: 0,
549
+ requeue: [],
550
+ stopped: false
551
+ };
552
+ await this.isolate(entries, state);
553
+ if (state.rejected > 0) internalWarn(`DatabaseTransport: dropped ${state.rejected} log entr${state.rejected === 1 ? "y" : "ies"} the database rejected`);
554
+ this.requeue(state.requeue);
555
+ if (state.stopped) throw state.error;
556
+ }
557
+ }
558
+ }
559
+ requeue(entries) {
560
+ if (entries.length === 0) return;
561
+ this.batch = entries.concat(this.batch);
562
+ this.cap.enforce(this.batch);
563
+ }
564
+ async writeEntries(entries) {
565
+ switch (this.config.type) {
566
+ case "mongodb":
567
+ await this.flushToMongoDB(entries);
568
+ break;
569
+ case "postgresql":
570
+ await this.flushToPostgreSQL(entries);
571
+ break;
572
+ case "mysql":
573
+ await this.flushToMySQL(entries);
574
+ break;
575
+ case "sqlite":
576
+ await this.flushToSQLite(entries);
577
+ break;
578
+ default: throw new Error(`Unsupported database type: ${this.config.type}`);
579
+ }
580
+ }
581
+ /**
582
+ * `entries` failed with a data error. Splits them in half until the refused
583
+ * entries are alone and drops those. A write that fails with anything but a
584
+ * data error, or running out of the per-flush write budget, stops the search:
585
+ * the entries not yet written go back to the buffer.
586
+ */
587
+ async isolate(entries, state) {
588
+ if (entries.length === 1) {
589
+ state.rejected += 1;
590
+ return;
591
+ }
592
+ const mid = Math.ceil(entries.length / 2);
593
+ for (const half of [entries.slice(0, mid), entries.slice(mid)]) {
594
+ if (state.stopped || state.budget <= 0) {
595
+ state.requeue.push(...half);
596
+ continue;
597
+ }
598
+ state.budget -= 1;
599
+ try {
600
+ await this.writeEntries(half);
601
+ } catch (error) {
602
+ if (error instanceof PartialWriteError) {
603
+ state.requeue.push(...error.remaining);
604
+ state.stopped = true;
605
+ state.error = error.cause;
606
+ } else if (isDataError(this.config.type, error)) await this.isolate(half, state);
607
+ else {
608
+ state.requeue.push(...half);
609
+ state.stopped = true;
610
+ state.error = error;
611
+ }
391
612
  }
392
613
  }
393
614
  }
@@ -512,7 +733,26 @@ var DatabaseTransport = class {
512
733
  appName: entry.appName,
513
734
  environment: entry.environment
514
735
  }));
515
- await collection.insertMany(documents);
736
+ try {
737
+ await collection.insertMany(documents, { ordered: false });
738
+ } catch (error) {
739
+ const raw = error.writeErrors;
740
+ let list = [];
741
+ if (Array.isArray(raw)) list = raw;
742
+ else if (raw) list = [raw];
743
+ const writeErrors = list;
744
+ if (writeErrors.length === 0) throw error;
745
+ const remaining = [];
746
+ let rejected = 0;
747
+ for (const writeError of writeErrors) {
748
+ const entry = typeof writeError.index === "number" ? entries[writeError.index] : void 0;
749
+ if (!entry) throw error;
750
+ if (isDataError("mongodb", writeError)) rejected += 1;
751
+ else remaining.push(entry);
752
+ }
753
+ if (rejected > 0) internalWarn(`DatabaseTransport: dropped ${rejected} log entr${rejected === 1 ? "y" : "ies"} the database rejected`);
754
+ if (remaining.length > 0) throw new PartialWriteError("MongoDB insert partially failed", remaining, error);
755
+ }
516
756
  }
517
757
  async flushToPostgreSQL(entries) {
518
758
  const tableName = this.config.table || "logs";
@@ -525,7 +765,7 @@ var DatabaseTransport = class {
525
765
  entry.traceId,
526
766
  entry.appName,
527
767
  entry.environment
528
- ]), POSTGRES_ROWS_PER_INSERT);
768
+ ].map((value, column) => stripNul(column === 3 ? stripJsonNulEscape(value) : value))), POSTGRES_ROWS_PER_INSERT);
529
769
  const insertChunk = async (rows) => {
530
770
  const query = `
531
771
  INSERT INTO ${tableName}
@@ -685,6 +925,7 @@ var DatabaseTransport = class {
685
925
  internalError("Database flush during close failed; entries remain buffered", error);
686
926
  }
687
927
  if (this.batch.length > 0) internalError(`Database transport closing with ${this.batch.length} unflushed log entr${this.batch.length === 1 ? "y" : "ies"} after ${MAX_CLOSE_FLUSH_ATTEMPTS} attempts`);
928
+ this.cap.report(0);
688
929
  if (this.connection) switch (this.config.type) {
689
930
  case "mongodb":
690
931
  await this.connection.close();
@@ -747,6 +988,12 @@ const unlink = (0, node_util.promisify)(node_fs.unlink);
747
988
  const readdir = (0, node_util.promisify)(node_fs.readdir);
748
989
  const stat = (0, node_util.promisify)(node_fs.stat);
749
990
  const DROP_WARN_INTERVAL_MS = 5e3;
991
+ const DEFAULT_MAX_QUEUE = 1e4;
992
+ const DEFAULT_FILE_MODE = 384;
993
+ const DEFAULT_DIR_MODE = 448;
994
+ function csvField(value) {
995
+ return `"${stripControlChars(safeToString(value)).replace(/"/g, "\"\"")}"`;
996
+ }
750
997
  const SIZE_UNITS = {
751
998
  "": 1,
752
999
  k: 1024,
@@ -782,6 +1029,10 @@ function formatDatePattern(date, pattern) {
782
1029
  * rotated files are renamed beside it (`app-2026-10-22T09-30-00-000.log`).
783
1030
  * With a `rotation` block every file, the live one included, is timestamped.
784
1031
  *
1032
+ * Files are created with mode 0o600 and directories with 0o700; override with
1033
+ * `fileMode` and `dirMode`. At most `maxQueue` (default 10000) entries wait in
1034
+ * memory; the rest are dropped per `queuePolicy` and counted in a warning.
1035
+ *
785
1036
  * @example
786
1037
  * transports: { file: { filename: 'app.log', dirname: './logs', maxSize: '50MB' } }
787
1038
  */
@@ -816,8 +1067,10 @@ var FileTransport = class {
816
1067
  this.maxBytes = parseSize(rawMaxSize);
817
1068
  if (rawMaxSize !== void 0 && this.maxBytes === void 0) internalWarn(`FileTransport: maxSize ${JSON.stringify(rawMaxSize)} is not a valid size (try '50MB'); size rotation is off`);
818
1069
  const maxQueue = config.maxQueue;
819
- if (maxQueue !== void 0 && !(Number.isInteger(maxQueue) && maxQueue > 0)) internalWarn(`FileTransport: maxQueue ${String(maxQueue)} is not a positive integer; ignored`);
820
- else this.maxQueue = maxQueue;
1070
+ if (maxQueue !== void 0 && !(Number.isInteger(maxQueue) && maxQueue > 0)) internalWarn(`FileTransport: maxQueue ${String(maxQueue)} is not a positive integer; using ${DEFAULT_MAX_QUEUE}`);
1071
+ this.maxQueue = maxQueue !== void 0 && Number.isInteger(maxQueue) && maxQueue > 0 ? maxQueue : DEFAULT_MAX_QUEUE;
1072
+ this.fileMode = config.fileMode ?? DEFAULT_FILE_MODE;
1073
+ this.dirMode = config.dirMode ?? DEFAULT_DIR_MODE;
821
1074
  this.queuePolicy = config.queuePolicy ?? "drop-oldest";
822
1075
  this.maxFiles = (rotation === null || rotation === void 0 ? void 0 : rotation.maxFiles) ?? config.maxFiles;
823
1076
  this.compress = (rotation === null || rotation === void 0 ? void 0 : rotation.compress) ?? config.zippedArchive ?? false;
@@ -827,7 +1080,10 @@ var FileTransport = class {
827
1080
  this.ext = node_path.extname(config.filename);
828
1081
  this.base = node_path.basename(config.filename, this.ext);
829
1082
  try {
830
- node_fs.mkdirSync(this.dir, { recursive: true });
1083
+ node_fs.mkdirSync(this.dir, {
1084
+ recursive: true,
1085
+ mode: this.dirMode
1086
+ });
831
1087
  } catch (error) {
832
1088
  internalError(`FileTransport could not create ${this.dir}`, error);
833
1089
  }
@@ -895,7 +1151,7 @@ var FileTransport = class {
895
1151
  this.enqueued += 1;
896
1152
  }
897
1153
  queueFull() {
898
- return this.maxQueue !== void 0 && this.batch.length + this.inFlight >= this.maxQueue;
1154
+ return this.batch.length + this.inFlight >= this.maxQueue;
899
1155
  }
900
1156
  roomAvailable() {
901
1157
  const room = new Promise((resolve) => this.spaceWaiters.push(resolve));
@@ -975,30 +1231,26 @@ var FileTransport = class {
975
1231
  }
976
1232
  formatEntry(entry) {
977
1233
  switch (this.config.format) {
978
- case "json": return stringifyForLog({
1234
+ case "json": return stringifyForLog(mergeCoreFields({
979
1235
  timestamp: entry.timestamp.toISOString(),
980
1236
  level: entry.level,
981
- message: entry.message,
982
- ...entry.data || {}
983
- });
984
- case "csv": {
985
- const safeMessage = safeToString(entry.message);
986
- return [
987
- entry.timestamp.toISOString(),
988
- entry.level,
989
- `"${safeMessage.replace(/"/g, "\"\"")}"`,
990
- safeToString(entry.context),
991
- safeToString(entry.traceId),
992
- stringifyForLog(entry.data || {})
993
- ].join(",");
994
- }
1237
+ message: entry.message
1238
+ }, entry.data));
1239
+ case "csv": return [
1240
+ entry.timestamp.toISOString(),
1241
+ csvField(entry.level),
1242
+ csvField(entry.message),
1243
+ csvField(entry.context),
1244
+ csvField(entry.traceId),
1245
+ csvField(stringifyForLog(entry.data || {}))
1246
+ ].join(",");
995
1247
  case "text":
996
- default: return `${entry.timestamp.toISOString()} [${entry.level.toUpperCase()}] ${safeToString(entry.message)}${entry.data ? " " + stringifyForLog(entry.data) : ""}`;
1248
+ default: return `${entry.timestamp.toISOString()} [${stripControlChars(safeToString(entry.level)).toUpperCase()}] ${stripControlChars(safeToString(entry.message))}${entry.data ? " " + stringifyForLog(entry.data) : ""}`;
997
1249
  }
998
1250
  }
999
1251
  addToBatch(entry) {
1000
1252
  this.enqueue(entry);
1001
- const threshold = Math.min(this.config.batchSize || 100, this.maxQueue ?? Infinity);
1253
+ const threshold = Math.min(this.config.batchSize || 100, this.maxQueue);
1002
1254
  if (this.batch.length >= threshold && !this.draining) {
1003
1255
  if (this.batchTimer) {
1004
1256
  clearTimeout(this.batchTimer);
@@ -1036,7 +1288,7 @@ var FileTransport = class {
1036
1288
  if (chunk$1) await this.append(chunk$1, chunkBytes);
1037
1289
  }
1038
1290
  async append(content, bytes = Buffer.byteLength(content)) {
1039
- await appendFile(this.currentFilePath, content);
1291
+ await appendFile(this.currentFilePath, content, { mode: this.fileMode });
1040
1292
  this.bytesWritten += bytes;
1041
1293
  }
1042
1294
  timeToRotate() {
@@ -1130,7 +1382,7 @@ var FileTransport = class {
1130
1382
  async compressFile(filePath) {
1131
1383
  const gzPath = `${filePath}.gz`;
1132
1384
  try {
1133
- await (0, node_stream_promises.pipeline)(node_fs.createReadStream(filePath), (0, node_zlib.createGzip)(), node_fs.createWriteStream(gzPath));
1385
+ await (0, node_stream_promises.pipeline)(node_fs.createReadStream(filePath), (0, node_zlib.createGzip)(), node_fs.createWriteStream(gzPath, { mode: this.fileMode }));
1134
1386
  await unlink(filePath);
1135
1387
  } catch (error) {
1136
1388
  internalError("Failed to compress rotated log file", error);
package/dist/worker.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import "./transport.types-B5vcyv2k.mjs";
2
- import { n as WorkerTransportConfig, t as WorkerTransport } from "./worker.transport-BP8Q28Z2.mjs";
1
+ import "./transport.types-BMnurPcc.mjs";
2
+ import { n as WorkerTransportConfig, t as WorkerTransport } from "./worker.transport-JvGPog3C.mjs";
3
3
  export { WorkerTransport, WorkerTransportConfig };
package/dist/worker.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import "./transport.types-BuY84TwO.js";
2
- import { n as WorkerTransportConfig, t as WorkerTransport } from "./worker.transport-mKXgNK0L.js";
1
+ import "./transport.types-CGoHpWQR.js";
2
+ import { n as WorkerTransportConfig, t as WorkerTransport } from "./worker.transport-CdzSZJmw.js";
3
3
  export { WorkerTransport, WorkerTransportConfig };
package/dist/worker.js CHANGED
@@ -1,4 +1,4 @@
1
1
  require('./internal-log-BUJYMZbE.js');
2
- const require_worker_transport = require('./worker.transport-CfH6z37Z.js');
2
+ const require_worker_transport = require('./worker.transport-BdPxu3PN.js');
3
3
 
4
4
  exports.WorkerTransport = require_worker_transport.WorkerTransport;
package/dist/worker.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  import "./internal-log-Cm8SOWSV.mjs";
2
- import { t as WorkerTransport } from "./worker.transport-BhMyvqQ2.mjs";
2
+ import { t as WorkerTransport } from "./worker.transport-lPxO2MVL.mjs";
3
3
 
4
4
  export { WorkerTransport };
@@ -165,4 +165,4 @@ Object.defineProperty(exports, 'WorkerTransport', {
165
165
  return WorkerTransport;
166
166
  }
167
167
  });
168
- //# sourceMappingURL=worker.transport-CfH6z37Z.js.map
168
+ //# sourceMappingURL=worker.transport-BdPxu3PN.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.transport-CfH6z37Z.js","names":["Worker","path"],"sources":["../src/transports/worker.transport.ts"],"sourcesContent":["/**\n * logixia — Worker Thread Transport\n *\n * Offloads JSON serialization and all I/O to a Node.js worker thread,\n * completely eliminating any event-loop impact from logging. The main thread\n * only posts a raw message to the worker — it never calls JSON.stringify or\n * any I/O syscalls on the hot path.\n *\n * Architecture:\n * Main thread → MessageChannel → Worker thread → Wrapped transport\n *\n * The worker runs an ordinary logixia transport (file, database, console…)\n * inside its own event loop. If the worker crashes it is restarted automatically\n * (up to `maxRestarts` times) and buffered messages are replayed.\n *\n * @example\n * ```ts\n * import { WorkerTransport } from 'logixia/worker';\n *\n * const logger = createLogger({\n * transports: {\n * // Run file transport inside a worker thread — zero event-loop impact\n * worker: new WorkerTransport({\n * transportType: 'file',\n * transportConfig: { filename: 'app.log', dirname: './logs' },\n * bufferSize: 500,\n * maxRestarts: 3,\n * }),\n * },\n * });\n * ```\n */\n\nimport path from 'node:path';\nimport { Worker } from 'node:worker_threads';\n\nimport type { ITransport, TransportLogEntry } from '../types/transport.types';\nimport { internalError, internalWarn } from '../utils/internal-log';\n\nexport interface WorkerTransportConfig {\n /**\n * Which built-in logixia transport to run inside the worker thread.\n * The worker resolves the correct module automatically.\n */\n transportType: 'file' | 'database' | 'console';\n /** Config forwarded verbatim to the wrapped transport constructor. */\n transportConfig: Record<string, unknown>;\n /**\n * Max log entries to buffer in the main thread while the worker is starting\n * or restarting. Entries beyond this limit are dropped with a warning.\n * @default 1000\n */\n bufferSize?: number;\n /**\n * How many times to restart the worker if it crashes unexpectedly.\n * @default 3\n */\n maxRestarts?: number;\n /**\n * Log level filter — only entries at or above this level are forwarded.\n * Useful for routing only errors to an expensive transport in a worker.\n */\n level?: string;\n}\n\n/**\n * Transport that runs a wrapped transport inside a dedicated Node.js worker\n * thread, completely removing JSON serialization and I/O from the main event loop.\n */\nexport class WorkerTransport implements ITransport {\n public readonly name = 'worker';\n public readonly level: string | undefined;\n public readonly batchSize = 1;\n public readonly flushInterval = 0;\n\n private worker: Worker | null = null;\n private ready = false;\n private readonly buffer: TransportLogEntry[] = [];\n private readonly bufferSize: number;\n private restarts = 0;\n private readonly maxRestarts: number;\n private readonly config: WorkerTransportConfig;\n /** Pending restart-backoff timer, so close() can cancel a queued restart. */\n private restartTimer: NodeJS.Timeout | null = null;\n /** Set once close() begins, so a worker 'exit' no longer triggers a restart. */\n private closing = false;\n /** Max time to wait for the worker's 'flushed' ack before giving up. */\n private readonly FLUSH_TIMEOUT_MS = 5000;\n /** Max time to wait for a graceful worker exit before force-terminating. */\n private readonly SHUTDOWN_TIMEOUT_MS = 5000;\n\n constructor(config: WorkerTransportConfig) {\n this.config = config;\n this.bufferSize = config.bufferSize ?? 1000;\n this.maxRestarts = config.maxRestarts ?? 3;\n this.level = config.level;\n this.startWorker();\n }\n\n private startWorker(): void {\n try {\n this.worker = new Worker(this.workerFile(), {\n workerData: {\n transportType: this.config.transportType,\n transportConfig: this.config.transportConfig,\n },\n });\n\n this.worker.on('message', (msg: { type: string; error?: string }) => {\n if (msg.type === 'ready') {\n this.ready = true;\n this.drainBuffer();\n } else if (msg.type === 'error' || msg.type === 'write-error') {\n internalError(\n `WorkerTransport [${this.config.transportType}]: ${msg.error ?? 'unknown'}`\n );\n }\n });\n\n this.worker.on('error', (err) => {\n internalError('WorkerTransport worker error', err);\n this.handleWorkerExit();\n });\n\n this.worker.on('exit', (code) => {\n if (code !== 0) {\n internalWarn(`WorkerTransport worker exited with code ${code}`);\n this.handleWorkerExit();\n }\n });\n } catch (err) {\n internalError('WorkerTransport failed to start', err);\n }\n }\n\n /** The worker entry is always built as CommonJS, next to this module's output. */\n protected workerFile(): string {\n return path.join(__dirname, 'worker-entry.js');\n }\n\n private handleWorkerExit(): void {\n this.ready = false;\n // Don't resurrect a worker we're intentionally shutting down — close() sets\n // `closing` and nulls the worker, so a late 'exit'/'error' event must not\n // queue a restart (which would spawn a fresh leaked thread post-shutdown).\n if (this.closing) return;\n if (this.restarts < this.maxRestarts) {\n this.restarts++;\n internalWarn(`WorkerTransport restarting (attempt ${this.restarts}/${this.maxRestarts})`);\n // Small backoff before restart. unref() so a perpetually-failing worker's\n // pending restart never keeps the process alive on its own.\n this.restartTimer = setTimeout(() => {\n this.restartTimer = null;\n this.startWorker();\n }, 500 * this.restarts);\n if (this.restartTimer.unref) this.restartTimer.unref();\n } else {\n internalError(\n `WorkerTransport exhausted ${this.maxRestarts} restart attempts — transport disabled`\n );\n }\n }\n\n private drainBuffer(): void {\n while (this.buffer.length > 0 && this.ready && this.worker) {\n const entry = this.buffer.shift();\n if (entry) {\n this.worker.postMessage({ type: 'write', entry });\n }\n }\n }\n\n write(entry: TransportLogEntry): void {\n if (this.ready && this.worker) {\n this.worker.postMessage({ type: 'write', entry });\n } else {\n if (this.buffer.length >= this.bufferSize) {\n internalWarn('WorkerTransport buffer full — dropping oldest entry');\n this.buffer.shift();\n }\n this.buffer.push(entry);\n }\n }\n\n async flush(): Promise<void> {\n if (!this.ready || !this.worker) return;\n const worker = this.worker;\n return new Promise<void>((resolve) => {\n // Time-box the flush: if the worker dies or restarts before answering,\n // the 'flushed' message would never arrive and this promise would hang\n // forever, blocking shutdown until the force-exit timer kills the process\n // (losing everything). Resolve on timeout so close() can still terminate.\n const timer = setTimeout(() => {\n worker.off('message', handler);\n resolve();\n }, this.FLUSH_TIMEOUT_MS);\n if (timer.unref) timer.unref();\n\n const handler = (msg: { type: string }) => {\n if (msg.type === 'flushed') {\n clearTimeout(timer);\n worker.off('message', handler);\n resolve();\n }\n };\n worker.on('message', handler);\n worker.postMessage({ type: 'flush' });\n });\n }\n\n /**\n * Flush the worker's buffer and terminate the thread on shutdown.\n *\n * This MUST be named close() — TransportManager.close() invokes\n * transport.close(), so a method named only shutdown() was never called on\n * graceful exit, leaking the worker thread and dropping its buffered logs.\n */\n async close(): Promise<void> {\n // Stop the restart loop first: cancel any queued backoff restart and flag\n // that further worker exits are expected (so handleWorkerExit no-ops).\n this.closing = true;\n if (this.restartTimer) {\n clearTimeout(this.restartTimer);\n this.restartTimer = null;\n }\n\n if (!this.worker) return;\n const worker = this.worker;\n this.worker = null;\n\n // Push any locally-buffered (pre-ready) entries first: the worker's port\n // queues them until its listener attaches, so they are handled before the\n // shutdown message, which flushes the wrapped transport and exits.\n this.drainBufferTo(worker);\n worker.postMessage({ type: 'shutdown' });\n\n await new Promise<void>((resolve) => {\n // Don't wait forever for a wedged worker — terminate() it after a timeout.\n const timer = setTimeout(() => {\n worker.terminate().finally(() => resolve());\n }, this.SHUTDOWN_TIMEOUT_MS);\n if (timer.unref) timer.unref();\n\n worker.once('exit', () => {\n clearTimeout(timer);\n resolve();\n });\n });\n }\n\n /** Back-compat alias — prefer close(). */\n async shutdown(): Promise<void> {\n await this.close();\n }\n\n private drainBufferTo(worker: Worker): void {\n while (this.buffer.length > 0) {\n const entry = this.buffer.shift();\n if (entry) worker.postMessage({ type: 'write', entry });\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"worker.transport-BdPxu3PN.js","names":["Worker","path"],"sources":["../src/transports/worker.transport.ts"],"sourcesContent":["/**\n * logixia — Worker Thread Transport\n *\n * Offloads JSON serialization and all I/O to a Node.js worker thread,\n * completely eliminating any event-loop impact from logging. The main thread\n * only posts a raw message to the worker — it never calls JSON.stringify or\n * any I/O syscalls on the hot path.\n *\n * Architecture:\n * Main thread → MessageChannel → Worker thread → Wrapped transport\n *\n * The worker runs an ordinary logixia transport (file, database, console…)\n * inside its own event loop. If the worker crashes it is restarted automatically\n * (up to `maxRestarts` times) and buffered messages are replayed.\n *\n * @example\n * ```ts\n * import { WorkerTransport } from 'logixia/worker';\n *\n * const logger = createLogger({\n * transports: {\n * // Run file transport inside a worker thread — zero event-loop impact\n * worker: new WorkerTransport({\n * transportType: 'file',\n * transportConfig: { filename: 'app.log', dirname: './logs' },\n * bufferSize: 500,\n * maxRestarts: 3,\n * }),\n * },\n * });\n * ```\n */\n\nimport path from 'node:path';\nimport { Worker } from 'node:worker_threads';\n\nimport type { ITransport, TransportLogEntry } from '../types/transport.types';\nimport { internalError, internalWarn } from '../utils/internal-log';\n\nexport interface WorkerTransportConfig {\n /**\n * Which built-in logixia transport to run inside the worker thread.\n * The worker resolves the correct module automatically.\n */\n transportType: 'file' | 'database' | 'console';\n /** Config forwarded verbatim to the wrapped transport constructor. */\n transportConfig: Record<string, unknown>;\n /**\n * Max log entries to buffer in the main thread while the worker is starting\n * or restarting. Entries beyond this limit are dropped with a warning.\n * @default 1000\n */\n bufferSize?: number;\n /**\n * How many times to restart the worker if it crashes unexpectedly.\n * @default 3\n */\n maxRestarts?: number;\n /**\n * Log level filter — only entries at or above this level are forwarded.\n * Useful for routing only errors to an expensive transport in a worker.\n */\n level?: string;\n}\n\n/**\n * Transport that runs a wrapped transport inside a dedicated Node.js worker\n * thread, completely removing JSON serialization and I/O from the main event loop.\n */\nexport class WorkerTransport implements ITransport {\n public readonly name = 'worker';\n public readonly level: string | undefined;\n public readonly batchSize = 1;\n public readonly flushInterval = 0;\n\n private worker: Worker | null = null;\n private ready = false;\n private readonly buffer: TransportLogEntry[] = [];\n private readonly bufferSize: number;\n private restarts = 0;\n private readonly maxRestarts: number;\n private readonly config: WorkerTransportConfig;\n /** Pending restart-backoff timer, so close() can cancel a queued restart. */\n private restartTimer: NodeJS.Timeout | null = null;\n /** Set once close() begins, so a worker 'exit' no longer triggers a restart. */\n private closing = false;\n /** Max time to wait for the worker's 'flushed' ack before giving up. */\n private readonly FLUSH_TIMEOUT_MS = 5000;\n /** Max time to wait for a graceful worker exit before force-terminating. */\n private readonly SHUTDOWN_TIMEOUT_MS = 5000;\n\n constructor(config: WorkerTransportConfig) {\n this.config = config;\n this.bufferSize = config.bufferSize ?? 1000;\n this.maxRestarts = config.maxRestarts ?? 3;\n this.level = config.level;\n this.startWorker();\n }\n\n private startWorker(): void {\n try {\n this.worker = new Worker(this.workerFile(), {\n workerData: {\n transportType: this.config.transportType,\n transportConfig: this.config.transportConfig,\n },\n });\n\n this.worker.on('message', (msg: { type: string; error?: string }) => {\n if (msg.type === 'ready') {\n this.ready = true;\n this.drainBuffer();\n } else if (msg.type === 'error' || msg.type === 'write-error') {\n internalError(\n `WorkerTransport [${this.config.transportType}]: ${msg.error ?? 'unknown'}`\n );\n }\n });\n\n this.worker.on('error', (err) => {\n internalError('WorkerTransport worker error', err);\n this.handleWorkerExit();\n });\n\n this.worker.on('exit', (code) => {\n if (code !== 0) {\n internalWarn(`WorkerTransport worker exited with code ${code}`);\n this.handleWorkerExit();\n }\n });\n } catch (err) {\n internalError('WorkerTransport failed to start', err);\n }\n }\n\n /** The worker entry is always built as CommonJS, next to this module's output. */\n protected workerFile(): string {\n return path.join(__dirname, 'worker-entry.js');\n }\n\n private handleWorkerExit(): void {\n this.ready = false;\n // Don't resurrect a worker we're intentionally shutting down — close() sets\n // `closing` and nulls the worker, so a late 'exit'/'error' event must not\n // queue a restart (which would spawn a fresh leaked thread post-shutdown).\n if (this.closing) return;\n if (this.restarts < this.maxRestarts) {\n this.restarts++;\n internalWarn(`WorkerTransport restarting (attempt ${this.restarts}/${this.maxRestarts})`);\n // Small backoff before restart. unref() so a perpetually-failing worker's\n // pending restart never keeps the process alive on its own.\n this.restartTimer = setTimeout(() => {\n this.restartTimer = null;\n this.startWorker();\n }, 500 * this.restarts);\n if (this.restartTimer.unref) this.restartTimer.unref();\n } else {\n internalError(\n `WorkerTransport exhausted ${this.maxRestarts} restart attempts — transport disabled`\n );\n }\n }\n\n private drainBuffer(): void {\n while (this.buffer.length > 0 && this.ready && this.worker) {\n const entry = this.buffer.shift();\n if (entry) {\n this.worker.postMessage({ type: 'write', entry });\n }\n }\n }\n\n write(entry: TransportLogEntry): void {\n if (this.ready && this.worker) {\n this.worker.postMessage({ type: 'write', entry });\n } else {\n if (this.buffer.length >= this.bufferSize) {\n internalWarn('WorkerTransport buffer full — dropping oldest entry');\n this.buffer.shift();\n }\n this.buffer.push(entry);\n }\n }\n\n async flush(): Promise<void> {\n if (!this.ready || !this.worker) return;\n const worker = this.worker;\n return new Promise<void>((resolve) => {\n // Time-box the flush: if the worker dies or restarts before answering,\n // the 'flushed' message would never arrive and this promise would hang\n // forever, blocking shutdown until the force-exit timer kills the process\n // (losing everything). Resolve on timeout so close() can still terminate.\n const timer = setTimeout(() => {\n worker.off('message', handler);\n resolve();\n }, this.FLUSH_TIMEOUT_MS);\n if (timer.unref) timer.unref();\n\n const handler = (msg: { type: string }) => {\n if (msg.type === 'flushed') {\n clearTimeout(timer);\n worker.off('message', handler);\n resolve();\n }\n };\n worker.on('message', handler);\n worker.postMessage({ type: 'flush' });\n });\n }\n\n /**\n * Flush the worker's buffer and terminate the thread on shutdown.\n *\n * This MUST be named close() — TransportManager.close() invokes\n * transport.close(), so a method named only shutdown() was never called on\n * graceful exit, leaking the worker thread and dropping its buffered logs.\n */\n async close(): Promise<void> {\n // Stop the restart loop first: cancel any queued backoff restart and flag\n // that further worker exits are expected (so handleWorkerExit no-ops).\n this.closing = true;\n if (this.restartTimer) {\n clearTimeout(this.restartTimer);\n this.restartTimer = null;\n }\n\n if (!this.worker) return;\n const worker = this.worker;\n this.worker = null;\n\n // Push any locally-buffered (pre-ready) entries first: the worker's port\n // queues them until its listener attaches, so they are handled before the\n // shutdown message, which flushes the wrapped transport and exits.\n this.drainBufferTo(worker);\n worker.postMessage({ type: 'shutdown' });\n\n await new Promise<void>((resolve) => {\n // Don't wait forever for a wedged worker — terminate() it after a timeout.\n const timer = setTimeout(() => {\n worker.terminate().finally(() => resolve());\n }, this.SHUTDOWN_TIMEOUT_MS);\n if (timer.unref) timer.unref();\n\n worker.once('exit', () => {\n clearTimeout(timer);\n resolve();\n });\n });\n }\n\n /** Back-compat alias — prefer close(). */\n async shutdown(): Promise<void> {\n await this.close();\n }\n\n private drainBufferTo(worker: Worker): void {\n while (this.buffer.length > 0) {\n const entry = this.buffer.shift();\n if (entry) worker.postMessage({ type: 'write', entry });\n }\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { l as ITransport, p as TransportLogEntry } from "./transport.types-BuY84TwO.js";
1
+ import { l as ITransport, p as TransportLogEntry } from "./transport.types-CGoHpWQR.js";
2
2
 
3
3
  //#region src/transports/worker.transport.d.ts
4
4
 
@@ -73,4 +73,4 @@ declare class WorkerTransport implements ITransport {
73
73
  }
74
74
  //#endregion
75
75
  export { WorkerTransportConfig as n, WorkerTransport as t };
76
- //# sourceMappingURL=worker.transport-mKXgNK0L.d.ts.map
76
+ //# sourceMappingURL=worker.transport-CdzSZJmw.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.transport-mKXgNK0L.d.ts","names":[],"sources":["../src/transports/worker.transport.ts"],"sourcesContent":[],"mappings":";;;;UAuCiB,qBAAA;;;;;;;mBAOE;;;;;;;;;;;;;;;;;;;;;;cAuBN,eAAA,YAA2B;;;;;;;;;;;;;;;;;;;;sBAsBlB;;;;;;eAiFP;WAYE;;;;;;;;WAiCA;;cAkCG"}
1
+ {"version":3,"file":"worker.transport-CdzSZJmw.d.ts","names":[],"sources":["../src/transports/worker.transport.ts"],"sourcesContent":[],"mappings":";;;;UAuCiB,qBAAA;;;;;;;mBAOE;;;;;;;;;;;;;;;;;;;;;;cAuBN,eAAA,YAA2B;;;;;;;;;;;;;;;;;;;;sBAsBlB;;;;;;eAiFP;WAYE;;;;;;;;WAiCA;;cAkCG"}
@@ -1,4 +1,4 @@
1
- import { l as ITransport, p as TransportLogEntry } from "./transport.types-B5vcyv2k.mjs";
1
+ import { l as ITransport, p as TransportLogEntry } from "./transport.types-BMnurPcc.mjs";
2
2
 
3
3
  //#region src/transports/worker.transport.d.ts
4
4
 
@@ -73,4 +73,4 @@ declare class WorkerTransport implements ITransport {
73
73
  }
74
74
  //#endregion
75
75
  export { WorkerTransportConfig as n, WorkerTransport as t };
76
- //# sourceMappingURL=worker.transport-BP8Q28Z2.d.mts.map
76
+ //# sourceMappingURL=worker.transport-JvGPog3C.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.transport-BP8Q28Z2.d.mts","names":[],"sources":["../src/transports/worker.transport.ts"],"sourcesContent":[],"mappings":";;;;UAuCiB,qBAAA;;;;;;;mBAOE;;;;;;;;;;;;;;;;;;;;;;cAuBN,eAAA,YAA2B;;;;;;;;;;;;;;;;;;;;sBAsBlB;;;;;;eAiFP;WAYE;;;;;;;;WAiCA;;cAkCG"}
1
+ {"version":3,"file":"worker.transport-JvGPog3C.d.mts","names":[],"sources":["../src/transports/worker.transport.ts"],"sourcesContent":[],"mappings":";;;;UAuCiB,qBAAA;;;;;;;mBAOE;;;;;;;;;;;;;;;;;;;;;;cAuBN,eAAA,YAA2B;;;;;;;;;;;;;;;;;;;;sBAsBlB;;;;;;eAiFP;WAYE;;;;;;;;WAiCA;;cAkCG"}
@@ -164,4 +164,4 @@ var WorkerTransport = class {
164
164
 
165
165
  //#endregion
166
166
  export { WorkerTransport as t };
167
- //# sourceMappingURL=worker.transport-BhMyvqQ2.mjs.map
167
+ //# sourceMappingURL=worker.transport-lPxO2MVL.mjs.map