lograil 0.1.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 (373) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/LICENSE +21 -0
  3. package/README.md +40 -0
  4. package/dist/cjs/context/async-context.browser.d.ts +16 -0
  5. package/dist/cjs/context/async-context.browser.d.ts.map +1 -0
  6. package/dist/cjs/context/async-context.browser.js +29 -0
  7. package/dist/cjs/context/async-context.browser.js.map +1 -0
  8. package/dist/cjs/context/async-context.d.ts +10 -0
  9. package/dist/cjs/context/async-context.d.ts.map +1 -0
  10. package/dist/cjs/context/async-context.js +37 -0
  11. package/dist/cjs/context/async-context.js.map +1 -0
  12. package/dist/cjs/context/context.d.ts +33 -0
  13. package/dist/cjs/context/context.d.ts.map +1 -0
  14. package/dist/cjs/context/context.js +57 -0
  15. package/dist/cjs/context/context.js.map +1 -0
  16. package/dist/cjs/context/index.d.ts +3 -0
  17. package/dist/cjs/context/index.d.ts.map +1 -0
  18. package/dist/cjs/context/index.js +19 -0
  19. package/dist/cjs/context/index.js.map +1 -0
  20. package/dist/cjs/core/entry.d.ts +30 -0
  21. package/dist/cjs/core/entry.d.ts.map +1 -0
  22. package/dist/cjs/core/entry.js +37 -0
  23. package/dist/cjs/core/entry.js.map +1 -0
  24. package/dist/cjs/core/index.d.ts +7 -0
  25. package/dist/cjs/core/index.d.ts.map +1 -0
  26. package/dist/cjs/core/index.js +24 -0
  27. package/dist/cjs/core/index.js.map +1 -0
  28. package/dist/cjs/core/level.d.ts +12 -0
  29. package/dist/cjs/core/level.d.ts.map +1 -0
  30. package/dist/cjs/core/level.js +31 -0
  31. package/dist/cjs/core/level.js.map +1 -0
  32. package/dist/cjs/core/logger.d.ts +271 -0
  33. package/dist/cjs/core/logger.d.ts.map +1 -0
  34. package/dist/cjs/core/logger.js +751 -0
  35. package/dist/cjs/core/logger.js.map +1 -0
  36. package/dist/cjs/core/printf.d.ts +34 -0
  37. package/dist/cjs/core/printf.d.ts.map +1 -0
  38. package/dist/cjs/core/printf.js +133 -0
  39. package/dist/cjs/core/printf.js.map +1 -0
  40. package/dist/cjs/index.d.ts +40 -0
  41. package/dist/cjs/index.d.ts.map +1 -0
  42. package/dist/cjs/index.js +56 -0
  43. package/dist/cjs/index.js.map +1 -0
  44. package/dist/cjs/package.json +1 -0
  45. package/dist/cjs/pipeline/filter.d.ts +10 -0
  46. package/dist/cjs/pipeline/filter.d.ts.map +1 -0
  47. package/dist/cjs/pipeline/filter.js +16 -0
  48. package/dist/cjs/pipeline/filter.js.map +1 -0
  49. package/dist/cjs/pipeline/formatter.d.ts +19 -0
  50. package/dist/cjs/pipeline/formatter.d.ts.map +1 -0
  51. package/dist/cjs/pipeline/formatter.js +183 -0
  52. package/dist/cjs/pipeline/formatter.js.map +1 -0
  53. package/dist/cjs/pipeline/index.d.ts +6 -0
  54. package/dist/cjs/pipeline/index.d.ts.map +1 -0
  55. package/dist/cjs/pipeline/index.js +22 -0
  56. package/dist/cjs/pipeline/index.js.map +1 -0
  57. package/dist/cjs/pipeline/pipeline.d.ts +45 -0
  58. package/dist/cjs/pipeline/pipeline.d.ts.map +1 -0
  59. package/dist/cjs/pipeline/pipeline.js +80 -0
  60. package/dist/cjs/pipeline/pipeline.js.map +1 -0
  61. package/dist/cjs/pipeline/processor.d.ts +67 -0
  62. package/dist/cjs/pipeline/processor.d.ts.map +1 -0
  63. package/dist/cjs/pipeline/processor.js +284 -0
  64. package/dist/cjs/pipeline/processor.js.map +1 -0
  65. package/dist/cjs/pipeline/sampler.d.ts +45 -0
  66. package/dist/cjs/pipeline/sampler.d.ts.map +1 -0
  67. package/dist/cjs/pipeline/sampler.js +62 -0
  68. package/dist/cjs/pipeline/sampler.js.map +1 -0
  69. package/dist/cjs/plugin/index.d.ts +4 -0
  70. package/dist/cjs/plugin/index.d.ts.map +1 -0
  71. package/dist/cjs/plugin/index.js +20 -0
  72. package/dist/cjs/plugin/index.js.map +1 -0
  73. package/dist/cjs/plugin/manager.d.ts +38 -0
  74. package/dist/cjs/plugin/manager.d.ts.map +1 -0
  75. package/dist/cjs/plugin/manager.js +79 -0
  76. package/dist/cjs/plugin/manager.js.map +1 -0
  77. package/dist/cjs/plugin/otel-trace.d.ts +19 -0
  78. package/dist/cjs/plugin/otel-trace.d.ts.map +1 -0
  79. package/dist/cjs/plugin/otel-trace.js +91 -0
  80. package/dist/cjs/plugin/otel-trace.js.map +1 -0
  81. package/dist/cjs/plugin/plugin.d.ts +41 -0
  82. package/dist/cjs/plugin/plugin.d.ts.map +1 -0
  83. package/dist/cjs/plugin/plugin.js +3 -0
  84. package/dist/cjs/plugin/plugin.js.map +1 -0
  85. package/dist/cjs/runtime/adapter.d.ts +81 -0
  86. package/dist/cjs/runtime/adapter.d.ts.map +1 -0
  87. package/dist/cjs/runtime/adapter.js +3 -0
  88. package/dist/cjs/runtime/adapter.js.map +1 -0
  89. package/dist/cjs/runtime/defaults.d.ts +27 -0
  90. package/dist/cjs/runtime/defaults.d.ts.map +1 -0
  91. package/dist/cjs/runtime/defaults.js +30 -0
  92. package/dist/cjs/runtime/defaults.js.map +1 -0
  93. package/dist/cjs/runtime/electron-binding.browser.d.ts +10 -0
  94. package/dist/cjs/runtime/electron-binding.browser.d.ts.map +1 -0
  95. package/dist/cjs/runtime/electron-binding.browser.js +18 -0
  96. package/dist/cjs/runtime/electron-binding.browser.js.map +1 -0
  97. package/dist/cjs/runtime/electron-binding.d.ts +24 -0
  98. package/dist/cjs/runtime/electron-binding.d.ts.map +1 -0
  99. package/dist/cjs/runtime/electron-binding.js +49 -0
  100. package/dist/cjs/runtime/electron-binding.js.map +1 -0
  101. package/dist/cjs/runtime/electron-lifecycle.d.ts +17 -0
  102. package/dist/cjs/runtime/electron-lifecycle.d.ts.map +1 -0
  103. package/dist/cjs/runtime/electron-lifecycle.js +47 -0
  104. package/dist/cjs/runtime/electron-lifecycle.js.map +1 -0
  105. package/dist/cjs/runtime/electron-main.d.ts +24 -0
  106. package/dist/cjs/runtime/electron-main.d.ts.map +1 -0
  107. package/dist/cjs/runtime/electron-main.js +102 -0
  108. package/dist/cjs/runtime/electron-main.js.map +1 -0
  109. package/dist/cjs/runtime/electron-renderer.d.ts +26 -0
  110. package/dist/cjs/runtime/electron-renderer.d.ts.map +1 -0
  111. package/dist/cjs/runtime/electron-renderer.js +33 -0
  112. package/dist/cjs/runtime/electron-renderer.js.map +1 -0
  113. package/dist/cjs/runtime/electron.d.ts +20 -0
  114. package/dist/cjs/runtime/electron.d.ts.map +1 -0
  115. package/dist/cjs/runtime/electron.js +27 -0
  116. package/dist/cjs/runtime/electron.js.map +1 -0
  117. package/dist/cjs/runtime/index.d.ts +21 -0
  118. package/dist/cjs/runtime/index.d.ts.map +1 -0
  119. package/dist/cjs/runtime/index.js +41 -0
  120. package/dist/cjs/runtime/index.js.map +1 -0
  121. package/dist/cjs/runtime/node.d.ts +27 -0
  122. package/dist/cjs/runtime/node.d.ts.map +1 -0
  123. package/dist/cjs/runtime/node.js +126 -0
  124. package/dist/cjs/runtime/node.js.map +1 -0
  125. package/dist/cjs/runtime/process-lifecycle.d.ts +13 -0
  126. package/dist/cjs/runtime/process-lifecycle.d.ts.map +1 -0
  127. package/dist/cjs/runtime/process-lifecycle.js +80 -0
  128. package/dist/cjs/runtime/process-lifecycle.js.map +1 -0
  129. package/dist/cjs/runtime/web-lifecycle.d.ts +13 -0
  130. package/dist/cjs/runtime/web-lifecycle.d.ts.map +1 -0
  131. package/dist/cjs/runtime/web-lifecycle.js +39 -0
  132. package/dist/cjs/runtime/web-lifecycle.js.map +1 -0
  133. package/dist/cjs/runtime/web.d.ts +14 -0
  134. package/dist/cjs/runtime/web.d.ts.map +1 -0
  135. package/dist/cjs/runtime/web.js +61 -0
  136. package/dist/cjs/runtime/web.js.map +1 -0
  137. package/dist/cjs/shims/index.browser.d.ts +26 -0
  138. package/dist/cjs/shims/index.browser.d.ts.map +1 -0
  139. package/dist/cjs/shims/index.browser.js +67 -0
  140. package/dist/cjs/shims/index.browser.js.map +1 -0
  141. package/dist/cjs/shims/index.d.ts +15 -0
  142. package/dist/cjs/shims/index.d.ts.map +1 -0
  143. package/dist/cjs/shims/index.js +39 -0
  144. package/dist/cjs/shims/index.js.map +1 -0
  145. package/dist/cjs/transport/cluster-ipc.d.ts +36 -0
  146. package/dist/cjs/transport/cluster-ipc.d.ts.map +1 -0
  147. package/dist/cjs/transport/cluster-ipc.js +76 -0
  148. package/dist/cjs/transport/cluster-ipc.js.map +1 -0
  149. package/dist/cjs/transport/console.d.ts +28 -0
  150. package/dist/cjs/transport/console.d.ts.map +1 -0
  151. package/dist/cjs/transport/console.js +48 -0
  152. package/dist/cjs/transport/console.js.map +1 -0
  153. package/dist/cjs/transport/electron-ipc.d.ts +69 -0
  154. package/dist/cjs/transport/electron-ipc.d.ts.map +1 -0
  155. package/dist/cjs/transport/electron-ipc.js +153 -0
  156. package/dist/cjs/transport/electron-ipc.js.map +1 -0
  157. package/dist/cjs/transport/file.d.ts +190 -0
  158. package/dist/cjs/transport/file.d.ts.map +1 -0
  159. package/dist/cjs/transport/file.js +666 -0
  160. package/dist/cjs/transport/file.js.map +1 -0
  161. package/dist/cjs/transport/index.d.ts +9 -0
  162. package/dist/cjs/transport/index.d.ts.map +1 -0
  163. package/dist/cjs/transport/index.js +25 -0
  164. package/dist/cjs/transport/index.js.map +1 -0
  165. package/dist/cjs/transport/live.d.ts +72 -0
  166. package/dist/cjs/transport/live.d.ts.map +1 -0
  167. package/dist/cjs/transport/live.js +104 -0
  168. package/dist/cjs/transport/live.js.map +1 -0
  169. package/dist/cjs/transport/otlp.d.ts +97 -0
  170. package/dist/cjs/transport/otlp.d.ts.map +1 -0
  171. package/dist/cjs/transport/otlp.js +194 -0
  172. package/dist/cjs/transport/otlp.js.map +1 -0
  173. package/dist/cjs/transport/rotating-file.d.ts +67 -0
  174. package/dist/cjs/transport/rotating-file.d.ts.map +1 -0
  175. package/dist/cjs/transport/rotating-file.js +179 -0
  176. package/dist/cjs/transport/rotating-file.js.map +1 -0
  177. package/dist/cjs/transport/transport.d.ts +35 -0
  178. package/dist/cjs/transport/transport.d.ts.map +1 -0
  179. package/dist/cjs/transport/transport.js +3 -0
  180. package/dist/cjs/transport/transport.js.map +1 -0
  181. package/dist/cjs/transport/worker-ipc.d.ts +43 -0
  182. package/dist/cjs/transport/worker-ipc.d.ts.map +1 -0
  183. package/dist/cjs/transport/worker-ipc.js +106 -0
  184. package/dist/cjs/transport/worker-ipc.js.map +1 -0
  185. package/dist/cjs/types.d.ts +72 -0
  186. package/dist/cjs/types.d.ts.map +1 -0
  187. package/dist/cjs/types.js +45 -0
  188. package/dist/cjs/types.js.map +1 -0
  189. package/dist/esm/context/async-context.browser.d.ts +16 -0
  190. package/dist/esm/context/async-context.browser.d.ts.map +1 -0
  191. package/dist/esm/context/async-context.browser.js +25 -0
  192. package/dist/esm/context/async-context.browser.js.map +1 -0
  193. package/dist/esm/context/async-context.d.ts +10 -0
  194. package/dist/esm/context/async-context.d.ts.map +1 -0
  195. package/dist/esm/context/async-context.js +33 -0
  196. package/dist/esm/context/async-context.js.map +1 -0
  197. package/dist/esm/context/context.d.ts +33 -0
  198. package/dist/esm/context/context.d.ts.map +1 -0
  199. package/dist/esm/context/context.js +52 -0
  200. package/dist/esm/context/context.js.map +1 -0
  201. package/dist/esm/context/index.d.ts +3 -0
  202. package/dist/esm/context/index.d.ts.map +1 -0
  203. package/dist/esm/context/index.js +3 -0
  204. package/dist/esm/context/index.js.map +1 -0
  205. package/dist/esm/core/entry.d.ts +30 -0
  206. package/dist/esm/core/entry.d.ts.map +1 -0
  207. package/dist/esm/core/entry.js +34 -0
  208. package/dist/esm/core/entry.js.map +1 -0
  209. package/dist/esm/core/index.d.ts +7 -0
  210. package/dist/esm/core/index.d.ts.map +1 -0
  211. package/dist/esm/core/index.js +6 -0
  212. package/dist/esm/core/index.js.map +1 -0
  213. package/dist/esm/core/level.d.ts +12 -0
  214. package/dist/esm/core/level.d.ts.map +1 -0
  215. package/dist/esm/core/level.js +25 -0
  216. package/dist/esm/core/level.js.map +1 -0
  217. package/dist/esm/core/logger.d.ts +271 -0
  218. package/dist/esm/core/logger.d.ts.map +1 -0
  219. package/dist/esm/core/logger.js +747 -0
  220. package/dist/esm/core/logger.js.map +1 -0
  221. package/dist/esm/core/printf.d.ts +34 -0
  222. package/dist/esm/core/printf.d.ts.map +1 -0
  223. package/dist/esm/core/printf.js +129 -0
  224. package/dist/esm/core/printf.js.map +1 -0
  225. package/dist/esm/index.d.ts +40 -0
  226. package/dist/esm/index.d.ts.map +1 -0
  227. package/dist/esm/index.js +38 -0
  228. package/dist/esm/index.js.map +1 -0
  229. package/dist/esm/pipeline/filter.d.ts +10 -0
  230. package/dist/esm/pipeline/filter.d.ts.map +1 -0
  231. package/dist/esm/pipeline/filter.js +11 -0
  232. package/dist/esm/pipeline/filter.js.map +1 -0
  233. package/dist/esm/pipeline/formatter.d.ts +19 -0
  234. package/dist/esm/pipeline/formatter.d.ts.map +1 -0
  235. package/dist/esm/pipeline/formatter.js +179 -0
  236. package/dist/esm/pipeline/formatter.js.map +1 -0
  237. package/dist/esm/pipeline/index.d.ts +6 -0
  238. package/dist/esm/pipeline/index.d.ts.map +1 -0
  239. package/dist/esm/pipeline/index.js +6 -0
  240. package/dist/esm/pipeline/index.js.map +1 -0
  241. package/dist/esm/pipeline/pipeline.d.ts +45 -0
  242. package/dist/esm/pipeline/pipeline.d.ts.map +1 -0
  243. package/dist/esm/pipeline/pipeline.js +76 -0
  244. package/dist/esm/pipeline/pipeline.js.map +1 -0
  245. package/dist/esm/pipeline/processor.d.ts +67 -0
  246. package/dist/esm/pipeline/processor.d.ts.map +1 -0
  247. package/dist/esm/pipeline/processor.js +277 -0
  248. package/dist/esm/pipeline/processor.js.map +1 -0
  249. package/dist/esm/pipeline/sampler.d.ts +45 -0
  250. package/dist/esm/pipeline/sampler.d.ts.map +1 -0
  251. package/dist/esm/pipeline/sampler.js +59 -0
  252. package/dist/esm/pipeline/sampler.js.map +1 -0
  253. package/dist/esm/plugin/index.d.ts +4 -0
  254. package/dist/esm/plugin/index.d.ts.map +1 -0
  255. package/dist/esm/plugin/index.js +4 -0
  256. package/dist/esm/plugin/index.js.map +1 -0
  257. package/dist/esm/plugin/manager.d.ts +38 -0
  258. package/dist/esm/plugin/manager.d.ts.map +1 -0
  259. package/dist/esm/plugin/manager.js +75 -0
  260. package/dist/esm/plugin/manager.js.map +1 -0
  261. package/dist/esm/plugin/otel-trace.d.ts +19 -0
  262. package/dist/esm/plugin/otel-trace.d.ts.map +1 -0
  263. package/dist/esm/plugin/otel-trace.js +55 -0
  264. package/dist/esm/plugin/otel-trace.js.map +1 -0
  265. package/dist/esm/plugin/plugin.d.ts +41 -0
  266. package/dist/esm/plugin/plugin.d.ts.map +1 -0
  267. package/dist/esm/plugin/plugin.js +2 -0
  268. package/dist/esm/plugin/plugin.js.map +1 -0
  269. package/dist/esm/runtime/adapter.d.ts +81 -0
  270. package/dist/esm/runtime/adapter.d.ts.map +1 -0
  271. package/dist/esm/runtime/adapter.js +2 -0
  272. package/dist/esm/runtime/adapter.js.map +1 -0
  273. package/dist/esm/runtime/defaults.d.ts +27 -0
  274. package/dist/esm/runtime/defaults.d.ts.map +1 -0
  275. package/dist/esm/runtime/defaults.js +27 -0
  276. package/dist/esm/runtime/defaults.js.map +1 -0
  277. package/dist/esm/runtime/electron-binding.browser.d.ts +10 -0
  278. package/dist/esm/runtime/electron-binding.browser.d.ts.map +1 -0
  279. package/dist/esm/runtime/electron-binding.browser.js +13 -0
  280. package/dist/esm/runtime/electron-binding.browser.js.map +1 -0
  281. package/dist/esm/runtime/electron-binding.d.ts +24 -0
  282. package/dist/esm/runtime/electron-binding.d.ts.map +1 -0
  283. package/dist/esm/runtime/electron-binding.js +44 -0
  284. package/dist/esm/runtime/electron-binding.js.map +1 -0
  285. package/dist/esm/runtime/electron-lifecycle.d.ts +17 -0
  286. package/dist/esm/runtime/electron-lifecycle.d.ts.map +1 -0
  287. package/dist/esm/runtime/electron-lifecycle.js +44 -0
  288. package/dist/esm/runtime/electron-lifecycle.js.map +1 -0
  289. package/dist/esm/runtime/electron-main.d.ts +24 -0
  290. package/dist/esm/runtime/electron-main.d.ts.map +1 -0
  291. package/dist/esm/runtime/electron-main.js +99 -0
  292. package/dist/esm/runtime/electron-main.js.map +1 -0
  293. package/dist/esm/runtime/electron-renderer.d.ts +26 -0
  294. package/dist/esm/runtime/electron-renderer.d.ts.map +1 -0
  295. package/dist/esm/runtime/electron-renderer.js +30 -0
  296. package/dist/esm/runtime/electron-renderer.js.map +1 -0
  297. package/dist/esm/runtime/electron.d.ts +20 -0
  298. package/dist/esm/runtime/electron.d.ts.map +1 -0
  299. package/dist/esm/runtime/electron.js +21 -0
  300. package/dist/esm/runtime/electron.js.map +1 -0
  301. package/dist/esm/runtime/index.d.ts +21 -0
  302. package/dist/esm/runtime/index.d.ts.map +1 -0
  303. package/dist/esm/runtime/index.js +29 -0
  304. package/dist/esm/runtime/index.js.map +1 -0
  305. package/dist/esm/runtime/node.d.ts +27 -0
  306. package/dist/esm/runtime/node.d.ts.map +1 -0
  307. package/dist/esm/runtime/node.js +123 -0
  308. package/dist/esm/runtime/node.js.map +1 -0
  309. package/dist/esm/runtime/process-lifecycle.d.ts +13 -0
  310. package/dist/esm/runtime/process-lifecycle.d.ts.map +1 -0
  311. package/dist/esm/runtime/process-lifecycle.js +77 -0
  312. package/dist/esm/runtime/process-lifecycle.js.map +1 -0
  313. package/dist/esm/runtime/web-lifecycle.d.ts +13 -0
  314. package/dist/esm/runtime/web-lifecycle.d.ts.map +1 -0
  315. package/dist/esm/runtime/web-lifecycle.js +36 -0
  316. package/dist/esm/runtime/web-lifecycle.js.map +1 -0
  317. package/dist/esm/runtime/web.d.ts +14 -0
  318. package/dist/esm/runtime/web.d.ts.map +1 -0
  319. package/dist/esm/runtime/web.js +58 -0
  320. package/dist/esm/runtime/web.js.map +1 -0
  321. package/dist/esm/shims/index.browser.d.ts +26 -0
  322. package/dist/esm/shims/index.browser.d.ts.map +1 -0
  323. package/dist/esm/shims/index.browser.js +54 -0
  324. package/dist/esm/shims/index.browser.js.map +1 -0
  325. package/dist/esm/shims/index.d.ts +15 -0
  326. package/dist/esm/shims/index.d.ts.map +1 -0
  327. package/dist/esm/shims/index.js +22 -0
  328. package/dist/esm/shims/index.js.map +1 -0
  329. package/dist/esm/transport/cluster-ipc.d.ts +36 -0
  330. package/dist/esm/transport/cluster-ipc.d.ts.map +1 -0
  331. package/dist/esm/transport/cluster-ipc.js +71 -0
  332. package/dist/esm/transport/cluster-ipc.js.map +1 -0
  333. package/dist/esm/transport/console.d.ts +28 -0
  334. package/dist/esm/transport/console.d.ts.map +1 -0
  335. package/dist/esm/transport/console.js +44 -0
  336. package/dist/esm/transport/console.js.map +1 -0
  337. package/dist/esm/transport/electron-ipc.d.ts +69 -0
  338. package/dist/esm/transport/electron-ipc.d.ts.map +1 -0
  339. package/dist/esm/transport/electron-ipc.js +146 -0
  340. package/dist/esm/transport/electron-ipc.js.map +1 -0
  341. package/dist/esm/transport/file.d.ts +190 -0
  342. package/dist/esm/transport/file.d.ts.map +1 -0
  343. package/dist/esm/transport/file.js +662 -0
  344. package/dist/esm/transport/file.js.map +1 -0
  345. package/dist/esm/transport/index.d.ts +9 -0
  346. package/dist/esm/transport/index.d.ts.map +1 -0
  347. package/dist/esm/transport/index.js +9 -0
  348. package/dist/esm/transport/index.js.map +1 -0
  349. package/dist/esm/transport/live.d.ts +72 -0
  350. package/dist/esm/transport/live.d.ts.map +1 -0
  351. package/dist/esm/transport/live.js +100 -0
  352. package/dist/esm/transport/live.js.map +1 -0
  353. package/dist/esm/transport/otlp.d.ts +97 -0
  354. package/dist/esm/transport/otlp.d.ts.map +1 -0
  355. package/dist/esm/transport/otlp.js +190 -0
  356. package/dist/esm/transport/otlp.js.map +1 -0
  357. package/dist/esm/transport/rotating-file.d.ts +67 -0
  358. package/dist/esm/transport/rotating-file.d.ts.map +1 -0
  359. package/dist/esm/transport/rotating-file.js +175 -0
  360. package/dist/esm/transport/rotating-file.js.map +1 -0
  361. package/dist/esm/transport/transport.d.ts +35 -0
  362. package/dist/esm/transport/transport.d.ts.map +1 -0
  363. package/dist/esm/transport/transport.js +2 -0
  364. package/dist/esm/transport/transport.js.map +1 -0
  365. package/dist/esm/transport/worker-ipc.d.ts +43 -0
  366. package/dist/esm/transport/worker-ipc.d.ts.map +1 -0
  367. package/dist/esm/transport/worker-ipc.js +101 -0
  368. package/dist/esm/transport/worker-ipc.js.map +1 -0
  369. package/dist/esm/types.d.ts +72 -0
  370. package/dist/esm/types.d.ts.map +1 -0
  371. package/dist/esm/types.js +39 -0
  372. package/dist/esm/types.js.map +1 -0
  373. package/package.json +128 -0
@@ -0,0 +1,662 @@
1
+ import { mkdir, open, rename, rm, stat, readdir } from '../shims/index.js';
2
+ import { basename, dirname, join } from '../shims/index.js';
3
+ import { tmpdir } from '../shims/index.js';
4
+ import { createJsonFormatter } from '../pipeline/formatter.js';
5
+ function timeStamp(d, unit) {
6
+ const y = d.getFullYear();
7
+ const m = String(d.getMonth() + 1).padStart(2, '0');
8
+ const day = String(d.getDate()).padStart(2, '0');
9
+ if (unit === 'day')
10
+ return `${y}-${m}-${day}`;
11
+ const h = String(d.getHours()).padStart(2, '0');
12
+ return `${y}-${m}-${day}-${h}`;
13
+ }
14
+ // ---- shared helpers -------------------------------------------------------
15
+ /** Best-effort cap: delete the oldest bucket/generation files beyond `maxFiles`.
16
+ * Only touches files the transport has explicitly created (tracked in `owned`).
17
+ * When `exclude` is provided, files matching its basename are also kept (used
18
+ * to protect the just-rotated-away file so it survives until the next bucket). */
19
+ async function trimRing(dir, appName, ext, maxFiles, owned, exclude) {
20
+ // maxFiles<=1 → no cap configured; skip trimming.
21
+ if (maxFiles <= 1)
22
+ return;
23
+ const keep = maxFiles - 1;
24
+ const excludeName = exclude ? basename(exclude) : undefined;
25
+ try {
26
+ const backups = (await readdir(dir))
27
+ .filter((f) => owned.has(f) &&
28
+ f !== `${appName}.${ext}` &&
29
+ (excludeName === undefined || f !== excludeName))
30
+ .sort();
31
+ const excess = backups.length - keep;
32
+ for (let i = 0; i < excess; i++) {
33
+ const toDelete = backups[i];
34
+ await rm(join(dir, toDelete), { force: true }).catch(() => { });
35
+ owned.delete(toDelete);
36
+ }
37
+ }
38
+ catch {
39
+ /* ignore */
40
+ }
41
+ }
42
+ /** Best-effort cap that counts by **time buckets** (stamps) rather than files.
43
+ * Groups owned files by their timestamp stamp, then deletes the oldest
44
+ * complete bucket(s) when the number of distinct stamps exceeds `maxFiles`.
45
+ * This is the correct trimming strategy for `rotate-time` with `maxSize`,
46
+ * where a single bucket may produce multiple seq-numbered files. */
47
+ async function trimTimeRing(dir, appName, ext, maxFiles, owned) {
48
+ if (maxFiles <= 1)
49
+ return;
50
+ const prefix = `${appName}.`;
51
+ const suffix = `.${ext}`;
52
+ const stampRe = /^\d{4}-\d{2}-\d{2}(?:-\d{2})?/;
53
+ try {
54
+ // Group owned files by stamp.
55
+ const groups = new Map();
56
+ for (const f of owned) {
57
+ if (f === `${appName}.${ext}`)
58
+ continue;
59
+ if (!f.startsWith(prefix) || !f.endsWith(suffix))
60
+ continue;
61
+ const body = f.slice(prefix.length, -suffix.length);
62
+ const m = body.match(stampRe);
63
+ if (m) {
64
+ const stamp = m[0];
65
+ let arr = groups.get(stamp);
66
+ if (!arr) {
67
+ arr = [];
68
+ groups.set(stamp, arr);
69
+ }
70
+ arr.push(f);
71
+ }
72
+ }
73
+ const stamps = [...groups.keys()].sort();
74
+ const excess = stamps.length - maxFiles;
75
+ if (excess <= 0)
76
+ return;
77
+ for (let i = 0; i < excess; i++) {
78
+ const files = groups.get(stamps[i]);
79
+ for (const f of files) {
80
+ await rm(join(dir, f), { force: true }).catch(() => { });
81
+ owned.delete(f);
82
+ }
83
+ }
84
+ }
85
+ catch {
86
+ /* ignore */
87
+ }
88
+ }
89
+ /** Best-effort cap on the number of seq files **within one time bucket**.
90
+ * Deletes the oldest seq files of `stamp` when the bucket holds more than
91
+ * `maxPerBucket` files, so a bucket forms an inner ring. The active file
92
+ * (highest seq) is never deleted. Iterates the `owned` set (not the
93
+ * directory) so the just-rotated-to active file — which may not exist on
94
+ * disk yet — is still counted. Best-effort: any fs error is swallowed. */
95
+ async function trimBucketSeq(dir, appName, ext, stamp, maxPerBucket, owned) {
96
+ if (maxPerBucket <= 0)
97
+ return;
98
+ const prefix = `${appName}.${stamp}.`;
99
+ const suffix = `.${ext}`;
100
+ try {
101
+ const files = [...owned].filter((f) => f.startsWith(prefix) && f.endsWith(suffix)).sort();
102
+ const excess = files.length - maxPerBucket;
103
+ for (let i = 0; i < excess; i++) {
104
+ await rm(join(dir, files[i]), { force: true }).catch(() => { });
105
+ owned.delete(files[i]);
106
+ }
107
+ }
108
+ catch {
109
+ /* ignore */
110
+ }
111
+ }
112
+ /**
113
+ * Global capacity guard: alongside (and independent of) per-mode `maxFiles`,
114
+ * delete the **oldest** owned files when either a total-size cap or an age cap
115
+ * is exceeded. "Oldest" is judged by modification time so it works uniformly
116
+ * across every mode. The active file is never deleted, even if it is the
117
+ * oldest. Best-effort: any fs error is swallowed.
118
+ */
119
+ async function enforceGlobalCaps(params) {
120
+ const { dir, activePath, maxTotalSize, maxAge, now, owned } = params;
121
+ if (!Number.isFinite(maxTotalSize) && maxAge < 0)
122
+ return;
123
+ try {
124
+ const names = (await readdir(dir)).filter((f) => owned.has(f) && join(dir, f) !== activePath);
125
+ const files = await Promise.all(names.map(async (f) => {
126
+ try {
127
+ const s = await stat(join(dir, f));
128
+ return { name: f, size: s.size, mtimeMs: s.mtimeMs };
129
+ }
130
+ catch {
131
+ return null; // skip unstatable files — no infinite delete loop
132
+ }
133
+ }));
134
+ const valid = files.filter((f) => f !== null);
135
+ valid.sort((a, b) => a.mtimeMs - b.mtimeMs);
136
+ let activeSize = 0;
137
+ try {
138
+ activeSize = (await stat(activePath)).size;
139
+ }
140
+ catch {
141
+ /* active file not created yet */
142
+ }
143
+ const toDelete = [];
144
+ // Age cap: drop anything older than the threshold (0 = delete all).
145
+ if (maxAge >= 0) {
146
+ for (const f of valid) {
147
+ if (maxAge === 0 || now - f.mtimeMs > maxAge)
148
+ toDelete.push(f.name);
149
+ }
150
+ }
151
+ // Size cap: drop oldest history files until active + history is under the limit.
152
+ if (Number.isFinite(maxTotalSize)) {
153
+ let total = activeSize;
154
+ for (const f of valid)
155
+ total += f.size;
156
+ for (const f of valid) {
157
+ if (total <= maxTotalSize)
158
+ break;
159
+ if (!toDelete.includes(f.name)) {
160
+ toDelete.push(f.name);
161
+ total -= f.size;
162
+ }
163
+ }
164
+ }
165
+ for (const f of toDelete) {
166
+ await rm(join(dir, f), { force: true }).catch(() => { });
167
+ owned.delete(f);
168
+ }
169
+ }
170
+ catch {
171
+ /* ignore */
172
+ }
173
+ }
174
+ // ---- 1.1 single -----------------------------------------------------------
175
+ class SingleRotator {
176
+ constructor(opts, dir, ext) {
177
+ this.path = join(dir, `${opts.appName}.${ext}`);
178
+ }
179
+ activePath() {
180
+ return this.path;
181
+ }
182
+ async prepare(_bytes, _entry, _now, io) {
183
+ io.owned.add(basename(this.path));
184
+ return false;
185
+ }
186
+ reset() {
187
+ /* no transient state */
188
+ }
189
+ }
190
+ // ---- 1.2 single-truncate --------------------------------------------------
191
+ class TruncateRotator {
192
+ constructor(opts, dir, ext) {
193
+ this.path = join(dir, `${opts.appName}.${ext}`);
194
+ this.backup = join(dir, opts.backupName ?? `${opts.appName}.bak`);
195
+ this.maxSize = opts.maxSize;
196
+ }
197
+ activePath() {
198
+ return this.path;
199
+ }
200
+ async prepare(bytes, _entry, _now, io) {
201
+ io.owned.add(basename(this.path));
202
+ io.owned.add(basename(this.backup));
203
+ let size = 0;
204
+ try {
205
+ size = (await stat(this.path)).size;
206
+ }
207
+ catch {
208
+ /* file not written yet */
209
+ }
210
+ if (size + bytes > this.maxSize) {
211
+ await io.closeHandle();
212
+ // Remove any previous backup first: on Windows `rename` refuses to
213
+ // overwrite an existing target, which would otherwise block truncation.
214
+ await rm(this.backup, { force: true }).catch(() => { });
215
+ io.owned.delete(basename(this.backup));
216
+ try {
217
+ await rename(this.path, this.backup);
218
+ io.owned.delete(basename(this.path));
219
+ io.owned.add(basename(this.backup));
220
+ return true; // truncated → a new active file was started
221
+ }
222
+ catch {
223
+ /* nothing to back up yet */
224
+ }
225
+ }
226
+ return false;
227
+ }
228
+ reset() {
229
+ /* no transient state */
230
+ }
231
+ }
232
+ // ---- 2.1 rotate-size -----------------------------------------------------
233
+ class SizeRotator {
234
+ constructor(opts, dir, ext) {
235
+ this.active = join(dir, `${opts.appName}.${ext}`);
236
+ this.maxSize = opts.maxSize;
237
+ this.maxFiles = opts.maxFiles;
238
+ }
239
+ activePath() {
240
+ return this.active;
241
+ }
242
+ genPath(seq, io) {
243
+ return join(io.dir, `${io.appName}.${seq}.${io.ext}`);
244
+ }
245
+ async prepare(bytes, _entry, _now, io) {
246
+ io.owned.add(basename(this.active));
247
+ let size = 0;
248
+ try {
249
+ size = (await stat(this.active)).size;
250
+ }
251
+ catch {
252
+ /* file not written yet */
253
+ }
254
+ if (size + bytes > this.maxSize) {
255
+ await io.closeHandle();
256
+ const gens = this.maxFiles - 1;
257
+ for (let k = gens; k >= 2; k--) {
258
+ try {
259
+ const from = this.genPath(k - 1, io);
260
+ const to = this.genPath(k, io);
261
+ await rename(from, to);
262
+ io.owned.delete(basename(from));
263
+ io.owned.add(basename(to));
264
+ }
265
+ catch {
266
+ /* missing generation — skip */
267
+ }
268
+ }
269
+ try {
270
+ await rename(this.active, this.genPath(1, io));
271
+ io.owned.delete(basename(this.active));
272
+ io.owned.add(basename(this.genPath(1, io)));
273
+ }
274
+ catch {
275
+ /* nothing to rotate yet */
276
+ }
277
+ // Generations are capped by the rename chain above; no extra trim needed.
278
+ return true;
279
+ }
280
+ return false;
281
+ }
282
+ reset() {
283
+ /* no transient state */
284
+ }
285
+ }
286
+ // ---- 2.2 rotate-time -----------------------------------------------------
287
+ class TimeRotator {
288
+ constructor(opts, dir, ext) {
289
+ this.seq = 0;
290
+ this.dir = dir;
291
+ this.ext = ext;
292
+ this.appName = opts.appName;
293
+ this.unit = opts.unit;
294
+ this.maxFiles = opts.maxFiles;
295
+ this.maxSize = opts.maxSize;
296
+ this.maxFilesPerBucket = opts.maxFilesPerBucket;
297
+ this.path = join(dir, `${opts.appName}.${ext}`);
298
+ }
299
+ activePath() {
300
+ return this.path;
301
+ }
302
+ stampPath(stamp, seq) {
303
+ return join(this.dir, `${this.appName}.${stamp}.${seq}.${this.ext}`);
304
+ }
305
+ /** Most recent existing bucket at or before `upTo`, so a restart continues
306
+ * the ring instead of orphaning yesterday's file. */
307
+ async latestExistingStamp(upTo) {
308
+ try {
309
+ const files = (await readdir(this.dir)).filter((f) => f.startsWith(`${this.appName}.`) && f.endsWith(`.${this.ext}`));
310
+ const stampRe = this.unit === 'hour' ? /^\d{4}-\d{2}-\d{2}-\d{2}/ : /^\d{4}-\d{2}-\d{2}/;
311
+ const prefix = `${this.appName}.`;
312
+ const suffix = `.${this.ext}`;
313
+ files.sort();
314
+ for (let i = files.length - 1; i >= 0; i--) {
315
+ const body = files[i].slice(prefix.length, -suffix.length);
316
+ // body is either `${stamp}` or `${stamp}.${seq}` — extract stamp
317
+ const dotIdx = body.lastIndexOf('.');
318
+ const stamp = dotIdx > 0 ? body.slice(0, dotIdx) : body;
319
+ if (stampRe.test(stamp) && stamp <= upTo)
320
+ return stamp;
321
+ }
322
+ }
323
+ catch {
324
+ /* directory not readable yet — start fresh */
325
+ }
326
+ return undefined;
327
+ }
328
+ /** Find the highest seq number among files in the given time bucket. */
329
+ async latestExistingSeq(stamp) {
330
+ if (!this.maxSize)
331
+ return 0;
332
+ try {
333
+ const prefix = `${this.appName}.${stamp}.`;
334
+ const suffix = `.${this.ext}`;
335
+ const files = (await readdir(this.dir)).filter((f) => f.startsWith(prefix) && f.endsWith(suffix));
336
+ let maxSeq = 0;
337
+ for (const f of files) {
338
+ const body = f.slice(this.appName.length + 1, -this.ext.length - 1);
339
+ // body is `${stamp}.${seq}`
340
+ const parts = body.split('.');
341
+ const seq = Number(parts[parts.length - 1]);
342
+ if (Number.isFinite(seq) && seq > maxSeq)
343
+ maxSeq = seq;
344
+ }
345
+ return maxSeq;
346
+ }
347
+ catch {
348
+ return 0;
349
+ }
350
+ }
351
+ async prepare(bytes, _entry, now, io) {
352
+ const stamp = timeStamp(now, this.unit);
353
+ if (this.currentStamp === undefined) {
354
+ const existing = await this.latestExistingStamp(stamp);
355
+ this.currentStamp = existing ?? stamp;
356
+ this.seq = await this.latestExistingSeq(this.currentStamp);
357
+ this.path = this.stampPath(this.currentStamp, this.seq);
358
+ io.owned.add(basename(this.path));
359
+ if (existing && existing !== stamp) {
360
+ // Bucket already rolled over; open the new one and drop stale files.
361
+ this.currentStamp = stamp;
362
+ this.seq = 0;
363
+ await io.closeHandle();
364
+ this.path = this.stampPath(stamp, 0);
365
+ io.owned.add(basename(this.path));
366
+ await trimTimeRing(io.dir, io.appName, io.ext, this.maxFiles ?? 0, io.owned);
367
+ return true;
368
+ }
369
+ await trimTimeRing(io.dir, io.appName, io.ext, this.maxFiles ?? 0, io.owned);
370
+ return false;
371
+ }
372
+ if (stamp !== this.currentStamp) {
373
+ // Time bucket changed — archive the previous file and open a new one.
374
+ this.currentStamp = stamp;
375
+ this.seq = 0;
376
+ await io.closeHandle();
377
+ this.path = this.stampPath(stamp, 0);
378
+ io.owned.add(basename(this.path));
379
+ await trimTimeRing(io.dir, io.appName, io.ext, this.maxFiles ?? 0, io.owned);
380
+ return true;
381
+ }
382
+ // Same time bucket — check size-based splitting within the bucket.
383
+ if (this.maxSize !== undefined) {
384
+ let size = 0;
385
+ try {
386
+ size = (await stat(this.path)).size;
387
+ }
388
+ catch {
389
+ /* file not written yet */
390
+ }
391
+ if (size + bytes > this.maxSize) {
392
+ this.seq += 1;
393
+ await io.closeHandle();
394
+ this.path = this.stampPath(this.currentStamp, this.seq);
395
+ io.owned.add(basename(this.path));
396
+ await trimTimeRing(io.dir, io.appName, io.ext, this.maxFiles ?? 0, io.owned);
397
+ // Cap the seq count inside the current bucket (inner ring).
398
+ await trimBucketSeq(io.dir, io.appName, io.ext, this.currentStamp, this.maxFilesPerBucket ?? 0, io.owned);
399
+ return true;
400
+ }
401
+ }
402
+ return false;
403
+ }
404
+ reset() {
405
+ this.currentStamp = undefined;
406
+ this.seq = 0;
407
+ this.path = join(this.dir, `${this.appName}.${this.ext}`);
408
+ }
409
+ }
410
+ // ---- 2.3 rotate-custom ---------------------------------------------------
411
+ class CustomRotator {
412
+ constructor(opts, dir, ext) {
413
+ this.seq = 0;
414
+ this.dir = dir;
415
+ this.ext = ext;
416
+ this.appName = opts.appName;
417
+ this.maxFiles = opts.maxFiles;
418
+ this.shouldRotate = opts.shouldRotate;
419
+ this.fileName = opts.fileName;
420
+ this.path = join(dir, this.fileName(opts.appName, 0, ext));
421
+ }
422
+ activePath() {
423
+ return this.path;
424
+ }
425
+ async prepare(_bytes, entry, now, io) {
426
+ const ctx = {
427
+ entry,
428
+ size: 0,
429
+ time: now.toISOString(),
430
+ };
431
+ if (this.shouldRotate(entry, ctx)) {
432
+ this.seq += 1;
433
+ await io.closeHandle();
434
+ this.path = join(io.dir, this.fileName(io.appName, this.seq, io.ext));
435
+ io.owned.add(basename(this.path));
436
+ await trimRing(io.dir, io.appName, io.ext, this.maxFiles ?? 0, io.owned);
437
+ return true;
438
+ }
439
+ return false;
440
+ }
441
+ reset() {
442
+ this.seq = 0;
443
+ this.path = join(this.dir, this.fileName(this.appName, 0, this.ext));
444
+ }
445
+ }
446
+ /**
447
+ * Single file transport covering every file-output strategy. Each strategy is
448
+ * an isolated `Rotator` (see above); this class only performs the shared
449
+ * filesystem plumbing on a serialized queue.
450
+ *
451
+ * Modes:
452
+ * - `single` (1.1): one fixed file, append forever.
453
+ * - `single-truncate` (1.2): back up + truncate when `maxSize` would be exceeded.
454
+ * - `rotate-size` (2.1): roll by size into N generations.
455
+ * - `rotate-time` (2.2): roll by hour/day into timestamped files.
456
+ * - `rotate-custom` (2.3): roll whenever a user predicate says so.
457
+ *
458
+ * `appName` is required and is embedded in every file name.
459
+ */
460
+ export class FileTransport {
461
+ /** Effective capacity limits, for diagnostics (e.g. "why was my log file
462
+ * deleted?"). `maxSize`/`maxFiles` reflect the active rotation mode;
463
+ * `maxTotalSize`/`maxAge` are the global caps (`Infinity`/`-1` = unset). */
464
+ get caps() {
465
+ const o = this.options;
466
+ return {
467
+ maxSize: 'maxSize' in o ? o.maxSize : undefined,
468
+ maxFiles: 'maxFiles' in o ? o.maxFiles : undefined,
469
+ maxFilesPerBucket: 'maxFilesPerBucket' in o ? o.maxFilesPerBucket : undefined,
470
+ maxTotalSize: this.maxTotalSize,
471
+ maxAge: this.maxAge,
472
+ };
473
+ }
474
+ constructor(options) {
475
+ this.owned = new Set();
476
+ this.closed = false;
477
+ this.reportedFirstError = false;
478
+ this.handle = null;
479
+ this.queue = Promise.resolve();
480
+ this.ownedScanned = false;
481
+ this.writeCount = 0;
482
+ this.lastCheckMs = 0;
483
+ if (!options.appName) {
484
+ throw new Error('FileTransport requires an "appName"');
485
+ }
486
+ this.options = options;
487
+ this.dir = options.dir ?? tmpdir();
488
+ this.ext = options.ext ?? 'log';
489
+ this.name = options.name ?? `file:${options.appName}`;
490
+ this.formatter = options.formatter ?? createJsonFormatter();
491
+ this.filter = options.filter;
492
+ this.maxTotalSize = options.maxTotalSize ?? Infinity;
493
+ this.maxAge = options.maxAge ?? -1;
494
+ this.createdAt = Date.now();
495
+ switch (options.mode) {
496
+ case 'single':
497
+ this.rotator = new SingleRotator(options, this.dir, this.ext);
498
+ break;
499
+ case 'single-truncate':
500
+ this.rotator = new TruncateRotator(options, this.dir, this.ext);
501
+ break;
502
+ case 'rotate-size':
503
+ this.rotator = new SizeRotator(options, this.dir, this.ext);
504
+ break;
505
+ case 'rotate-time':
506
+ this.rotator = new TimeRotator(options, this.dir, this.ext);
507
+ break;
508
+ case 'rotate-custom':
509
+ this.rotator = new CustomRotator(options, this.dir, this.ext);
510
+ break;
511
+ }
512
+ // Capture the clock synchronously at write time so a rotate-time transport
513
+ // uses the timestamp of the call, not a later microtask.
514
+ this.clock = options.mode === 'rotate-time' && options.now ? options.now : () => new Date();
515
+ this.io = {
516
+ dir: this.dir,
517
+ ext: this.ext,
518
+ appName: options.appName,
519
+ closeHandle: () => this.closeHandle(),
520
+ owned: this.owned,
521
+ };
522
+ }
523
+ /** Absolute path of the log directory. */
524
+ getDir() {
525
+ return this.dir;
526
+ }
527
+ /** Absolute path of the file currently being written to. */
528
+ getActiveFile() {
529
+ return this.rotator.activePath();
530
+ }
531
+ /** List all log files managed by this transport.
532
+ *
533
+ * By default returns every file the transport knows about, including
534
+ * files left over from previous runs (discovered via `scanOwned`). Pass
535
+ * `{ currentSessionOnly: true }` to restrict the result to files created
536
+ * by the current transport instance. */
537
+ async getFiles(options) {
538
+ await this.scanOwned();
539
+ const activePath = this.rotator.activePath();
540
+ const results = [];
541
+ for (const name of this.owned) {
542
+ const filePath = join(this.dir, name);
543
+ try {
544
+ const s = await stat(filePath);
545
+ if (options?.currentSessionOnly && s.mtimeMs < this.createdAt)
546
+ continue;
547
+ results.push({
548
+ name,
549
+ path: filePath,
550
+ size: s.size,
551
+ mtime: s.mtimeMs,
552
+ active: filePath === activePath,
553
+ });
554
+ }
555
+ catch {
556
+ // file disappeared between readdir and stat — skip
557
+ }
558
+ }
559
+ return results;
560
+ }
561
+ async ensureHandle() {
562
+ if (!this.handle) {
563
+ await this.scanOwned();
564
+ await mkdir(dirname(this.rotator.activePath()), { recursive: true });
565
+ this.handle = await open(this.rotator.activePath(), 'a');
566
+ this.io.owned.add(basename(this.rotator.activePath()));
567
+ }
568
+ return this.handle;
569
+ }
570
+ async scanOwned() {
571
+ if (this.ownedScanned)
572
+ return;
573
+ this.ownedScanned = true;
574
+ try {
575
+ const files = await readdir(this.dir);
576
+ const prefix = `${this.io.appName}.`;
577
+ const suffix = `.${this.io.ext}`;
578
+ for (const f of files) {
579
+ if (f.startsWith(prefix) && f.endsWith(suffix)) {
580
+ this.io.owned.add(f);
581
+ }
582
+ }
583
+ }
584
+ catch {
585
+ /* ignore scan failures */
586
+ }
587
+ }
588
+ async closeHandle() {
589
+ if (this.handle) {
590
+ await this.handle.close();
591
+ this.handle = null;
592
+ }
593
+ }
594
+ write(entry, formatted) {
595
+ if (this.closed || (this.filter && !this.filter(entry)))
596
+ return;
597
+ const line = formatted + '\n';
598
+ const bytes = Buffer.byteLength(line, 'utf8');
599
+ const now = this.clock();
600
+ const nowMs = now.getTime();
601
+ const task = this.queue
602
+ .then(async () => {
603
+ const rotated = await this.rotator.prepare(bytes, entry, now, this.io);
604
+ // Run the global cap check only when a rotation just happened (a new
605
+ // file landed) — that is when stale files can exceed the caps. Non-
606
+ // rotating modes (e.g. `single`) rely on the throttled periodic check
607
+ // below, so we never scan the directory on every hot-path write.
608
+ if (rotated) {
609
+ await enforceGlobalCaps({
610
+ dir: this.dir,
611
+ activePath: this.rotator.activePath(),
612
+ maxTotalSize: this.maxTotalSize,
613
+ maxAge: this.maxAge,
614
+ now: nowMs,
615
+ owned: this.io.owned,
616
+ });
617
+ }
618
+ // Throttled periodic check so caps are still honored between rotations
619
+ // (or when a mode never rotates). At most once per PERIODIC_EVERY writes
620
+ // and once per PERIODIC_INTERVAL_MS.
621
+ this.writeCount++;
622
+ const due = this.writeCount % FileTransport.PERIODIC_EVERY === 0 &&
623
+ nowMs - this.lastCheckMs >= FileTransport.PERIODIC_INTERVAL_MS;
624
+ if (due) {
625
+ this.lastCheckMs = nowMs;
626
+ await enforceGlobalCaps({
627
+ dir: this.dir,
628
+ activePath: this.rotator.activePath(),
629
+ maxTotalSize: this.maxTotalSize,
630
+ maxAge: this.maxAge,
631
+ now: nowMs,
632
+ owned: this.io.owned,
633
+ });
634
+ }
635
+ const handle = await this.ensureHandle();
636
+ await handle.write(line);
637
+ })
638
+ .catch((err) => {
639
+ if (!this.reportedFirstError) {
640
+ this.reportedFirstError = true;
641
+ console.error('[lograil] FileTransport write error (subsequent errors suppressed):', err);
642
+ }
643
+ });
644
+ this.queue = task;
645
+ return task;
646
+ }
647
+ async flush() {
648
+ await this.queue;
649
+ }
650
+ async close() {
651
+ await this.queue;
652
+ await this.closeHandle();
653
+ this.rotator.reset();
654
+ this.closed = true;
655
+ }
656
+ }
657
+ // Throttled periodic capacity check (in addition to the mandatory check that
658
+ // runs after every rotation): inspect at most once per `PERIODIC_EVERY`
659
+ // writes and at most once per `PERIODIC_INTERVAL_MS`.
660
+ FileTransport.PERIODIC_EVERY = 256;
661
+ FileTransport.PERIODIC_INTERVAL_MS = 60000;
662
+ //# sourceMappingURL=file.js.map