@visulima/pail 3.1.0 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/LICENSE.md +3 -407
  3. package/README.md +298 -0
  4. package/dist/constants.d.ts +37 -0
  5. package/dist/index.browser.d.ts +47 -12
  6. package/dist/index.browser.js +12 -1
  7. package/dist/index.server.d.ts +65 -40
  8. package/dist/index.server.js +533 -2
  9. package/dist/interactive/index.d.ts +2 -28
  10. package/dist/interactive/index.js +2 -1
  11. package/dist/interactive/interactive-manager.d.ts +108 -0
  12. package/dist/interactive/interactive-stream-hook.d.ts +68 -0
  13. package/dist/object-tree.d.ts +65 -7
  14. package/dist/object-tree.js +89 -2
  15. package/dist/packem_shared/AbstractJsonReporter-intFdT_A.js +204 -0
  16. package/dist/packem_shared/InteractiveManager-CZ85hGNW.js +172 -0
  17. package/dist/packem_shared/InteractiveStreamHook-DiSubbJ1.js +21 -0
  18. package/dist/packem_shared/JsonReporter-C0AXk99i.js +58 -0
  19. package/dist/packem_shared/JsonReporter-DcM2LBX9.js +28 -0
  20. package/dist/packem_shared/PrettyReporter-BFWaYP_J.js +222 -0
  21. package/dist/packem_shared/PrettyReporter-CuLLKr6-.js +169 -0
  22. package/dist/packem_shared/abstract-pretty-reporter-DMPDCslJ.js +50 -0
  23. package/dist/packem_shared/constants-DfDr4MHC.js +119 -0
  24. package/dist/packem_shared/format-label-Btft2KGP.js +1194 -0
  25. package/dist/packem_shared/get-longest-label-C9PWeyKq.js +9 -0
  26. package/dist/packem_shared/index-BomQ3E6J.js +650 -0
  27. package/dist/packem_shared/index-DqKWykfa.js +1146 -0
  28. package/dist/packem_shared/interactive-stream-hook-DG4BtN12.js +141 -0
  29. package/dist/packem_shared/pail.browser-CPjQrsyy.js +1427 -0
  30. package/dist/packem_shared/write-console-log-based-on-level-DBmRYXpj.js +14 -0
  31. package/dist/packem_shared/write-stream-BG8fhcs3.js +6 -0
  32. package/dist/pail.browser.d.ts +412 -0
  33. package/dist/pail.server.d.ts +233 -0
  34. package/dist/processor/caller/caller-processor.d.ts +40 -7
  35. package/dist/processor/caller/caller-processor.js +59 -1
  36. package/dist/processor/caller/get-caller-filename.d.ts +23 -0
  37. package/dist/processor/message-formatter-processor.d.ts +44 -9
  38. package/dist/processor/message-formatter-processor.js +67 -1
  39. package/dist/processor/opentelemetry-processor.d.ts +70 -0
  40. package/dist/processor/opentelemetry-processor.js +52 -0
  41. package/dist/processor/redact-processor.d.ts +39 -8
  42. package/dist/processor/redact-processor.js +30 -1
  43. package/dist/progress-bar.d.ts +75 -15
  44. package/dist/progress-bar.js +404 -1
  45. package/dist/reporter/file/json-file-reporter.d.ts +39 -20
  46. package/dist/reporter/file/json-file-reporter.js +136 -4
  47. package/dist/reporter/file/utils/rotating-file-stream.d.ts +48 -0
  48. package/dist/reporter/http/abstract-http-reporter.d.ts +215 -0
  49. package/dist/reporter/http/abstract-http-reporter.js +435 -0
  50. package/dist/reporter/http/http-reporter.d.ts +39 -0
  51. package/dist/reporter/http/http-reporter.edge-light.d.ts +40 -0
  52. package/dist/reporter/http/http-reporter.edge-light.js +651 -0
  53. package/dist/reporter/http/http-reporter.js +13 -0
  54. package/dist/reporter/http/utils/compression.d.ts +7 -0
  55. package/dist/reporter/http/utils/log-size-error.d.ts +30 -0
  56. package/dist/reporter/http/utils/retry.d.ts +27 -0
  57. package/dist/reporter/json/abstract-json-reporter.d.ts +61 -0
  58. package/dist/reporter/json/index.browser.d.ts +3 -13
  59. package/dist/reporter/json/index.browser.js +2 -1
  60. package/dist/reporter/json/index.d.ts +3 -16
  61. package/dist/reporter/json/index.js +2 -1
  62. package/dist/reporter/json/json-reporter.browser.d.ts +40 -0
  63. package/dist/reporter/json/json-reporter.server.d.ts +50 -0
  64. package/dist/reporter/pretty/abstract-pretty-reporter.d.ts +83 -0
  65. package/dist/reporter/pretty/index.browser.d.ts +2 -13
  66. package/dist/reporter/pretty/index.browser.js +1 -1
  67. package/dist/reporter/pretty/index.d.ts +2 -25
  68. package/dist/reporter/pretty/index.js +1 -1
  69. package/dist/reporter/pretty/pretty-reporter.browser.d.ts +36 -0
  70. package/dist/reporter/pretty/pretty-reporter.server.d.ts +70 -0
  71. package/dist/reporter/raw/raw-reporter.browser.d.ts +5 -0
  72. package/dist/reporter/raw/raw-reporter.server.d.ts +13 -0
  73. package/dist/reporter/simple/simple-reporter.server.d.ts +10 -14
  74. package/dist/reporter/simple/simple-reporter.server.js +186 -8
  75. package/dist/reporter/utils/default-inspector-config.d.ts +3 -0
  76. package/dist/reporter/utils/format-label.d.ts +3 -0
  77. package/dist/spinner.d.ts +170 -104
  78. package/dist/spinner.js +2150 -1
  79. package/dist/types.d.ts +241 -0
  80. package/dist/utils/ansi-escapes.d.ts +4 -0
  81. package/dist/utils/arrayify.d.ts +2 -0
  82. package/dist/utils/get-longest-badge.d.ts +4 -0
  83. package/dist/utils/get-longest-label.d.ts +4 -0
  84. package/dist/utils/merge-types.d.ts +4 -0
  85. package/dist/utils/stream/safe-stream-handler.d.ts +21 -0
  86. package/dist/utils/write-console-log-based-on-level.d.ts +4 -0
  87. package/dist/utils/write-stream.d.ts +2 -0
  88. package/package.json +53 -4
  89. package/dist/packem_shared/AbstractJsonReporter-UftN6CIL.js +0 -1
  90. package/dist/packem_shared/InteractiveManager-CgmJyW9x.js +0 -3
  91. package/dist/packem_shared/InteractiveStreamHook-NtJu71aN.js +0 -1
  92. package/dist/packem_shared/JsonReporter-DTBtHNaD.js +0 -2
  93. package/dist/packem_shared/JsonReporter-Dl4m0xZe.js +0 -1
  94. package/dist/packem_shared/PrettyReporter-Bns0ZWLy.js +0 -12
  95. package/dist/packem_shared/PrettyReporter-CGKSTI7X.js +0 -5
  96. package/dist/packem_shared/abstract-json-reporter-CPsNkpz8.d.ts +0 -22
  97. package/dist/packem_shared/abstract-pretty-reporter-CUtSm20r.js +0 -1
  98. package/dist/packem_shared/abstract-pretty-reporter-DB2G-qlI.d.ts +0 -28
  99. package/dist/packem_shared/constants-DKfCaSUR.js +0 -1
  100. package/dist/packem_shared/format-label-CpyyTBom.js +0 -26
  101. package/dist/packem_shared/get-longest-label-B0NrI-o2.js +0 -1
  102. package/dist/packem_shared/index-CysYvHXs.js +0 -8
  103. package/dist/packem_shared/index-D9hWq9ka.js +0 -1
  104. package/dist/packem_shared/index.d-BR1GjZri.d.ts +0 -53
  105. package/dist/packem_shared/index.d-oxZvg_y7.d.ts +0 -20
  106. package/dist/packem_shared/interactive-stream-hook-CeVo4Kth.js +0 -2
  107. package/dist/packem_shared/pail.browser-BmHoDvEA.js +0 -19
  108. package/dist/packem_shared/pail.browser-CmWcqnn9.d.ts +0 -64
  109. package/dist/packem_shared/types-DVzG8TWL.d.ts +0 -95
  110. package/dist/packem_shared/write-console-log-based-on-level-BP95fgQZ.js +0 -1
  111. package/dist/packem_shared/write-stream-CD8XFv1L.js +0 -1
@@ -1 +1,404 @@
1
- var B=Object.defineProperty;var f=(o,r)=>B(o,"name",{value:r,configurable:!0});var S=Object.defineProperty,d=f((o,r)=>S(o,"name",{value:r,configurable:!0}),"g");const w={default:["█","▓","▒","░"],rect:["▬","▮","▯","▭"]},A=/\[([^[\]]*)\]/u,u=d((o,r,t=!0)=>{if(o)return o;switch(r){case"ascii":return t?"#":"-";case"filled":return t?"█":" ";case"rect":return t?"▬":"▭";case"shades_classic":return t?"█":"░";case"shades_grey":return t?"▓":"░";case"solid":return t?"█":" ";default:return t?"█":"░"}},"getBarChar"),k=d(o=>{if(!o.style)return o;const{style:r}=o,t={...o};return t.barCompleteChar===void 0&&(t.barCompleteChar=u(void 0,r,!0)),t.barIncompleteChar===void 0&&(t.barIncompleteChar=u(void 0,r,!1)),t.barGlue===void 0&&(t.barGlue=""),t},"applyStyleToOptions");class T{static{f(this,"ProgressBar")}static{d(this,"ProgressBar")}options;current;startTime;interactiveManager;isActive=!1;payload;constructor(r,t,e){const a=Array.isArray(r.barCompleteChar),s=Array.isArray(r.barIncompleteChar),n=a||s,l=a?r.barCompleteChar:u(r.barCompleteChar,"shades_classic"),c=s?r.barIncompleteChar:u(r.barIncompleteChar,"shades_classic",!1);this.options={barCompleteChar:l,barIncompleteChar:c,current:0,fps:10,width:40,...r},n&&(Array.isArray(this.options.barCompleteChar)||(this.options.barCompleteChar=[this.options.barCompleteChar]),Array.isArray(this.options.barIncompleteChar)||(this.options.barIncompleteChar=[this.options.barIncompleteChar])),this.current=this.options.current??0,this.startTime=Date.now(),this.interactiveManager=t,this.payload=e}update(r,t){if(this.current=Math.min(r,this.options.total),t&&(this.payload={...this.payload,...t}),this.interactiveManager&&this.isActive){const e=this.render();this.interactiveManager.update("stdout",[e])}}increment(r=1,t){this.update(this.current+r,t)}render(){const r=this.options.total>0?this.options.total:1,t=Math.max(0,this.options.width??40),e=Math.max(0,Math.min(100,Math.round(this.current/r*100))),a=Math.max(0,Math.min(t,Math.round(this.current/r*t))),s=t-a;let n;if(Array.isArray(this.options.barCompleteChar)||Array.isArray(this.options.barIncompleteChar)){const i=Array.isArray(this.options.barCompleteChar)?this.options.barCompleteChar:void 0,h=Array.isArray(this.options.barIncompleteChar)?this.options.barIncompleteChar:void 0,C=i?.[i.length-1]??(typeof this.options.barCompleteChar=="string"?this.options.barCompleteChar:"█"),p=h?.[0]??(typeof this.options.barIncompleteChar=="string"?this.options.barIncompleteChar:"░"),m=i?.length??1,y=this.current/r,M=t*m,v=Math.round(y*M)%m;let g="";for(let b=0;b<t;b+=1)if(b<a){const I=b===a-1&&v>0&&i;g+=I?i[Math.max(0,v-1)]:C}else g+=p;n=g}else{const i=typeof this.options.barCompleteChar=="string"?this.options.barCompleteChar:"█",h=typeof this.options.barIncompleteChar=="string"?this.options.barIncompleteChar:"░";n=i.repeat(a)+h.repeat(s)}let l=this.options.format??"progress [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}";if(this.payload)for(const[i,h]of Object.entries(this.payload))l=l.replaceAll(`{${i}}`,String(h));const c=this.calculateETA();return l.replaceAll("{bar}",n).replaceAll("{percentage}",String(e)).replaceAll("{value}",String(this.current)).replaceAll("{total}",String(this.options.total)).replaceAll("{eta}",String(c))}start(r,t,e){r!==void 0&&(this.options.total=r),t!==void 0&&(this.current=t),this.startTime=Date.now(),this.isActive=!0,this.interactiveManager&&(this.interactiveManager.hook(),this.update(this.current,e))}stop(){this.isActive=!1,this.interactiveManager&&this.interactiveManager.unhook(!1)}calculateETA(){if(this.current===0)return 0;const r=(Date.now()-this.startTime)/1e3;if(r<.1)return 0;const t=this.current/r,e=this.options.total-this.current;return Math.round(e/t)}}class x extends T{static{f(this,"MultiBarInstance")}static{d(this,"MultiBarInstance")}multiBar;constructor(r,t,e){super(t,void 0,e),this.multiBar=r}update(r,t){super.update(r,t),this.multiBar.renderAll()}getBarState(){return{char:(Array.isArray(this.options.barCompleteChar)?this.options.barCompleteChar[this.options.barCompleteChar.length-1]:u(this.options.barCompleteChar,this.options.style??"shades_classic",!0))??"█",current:this.current,total:this.options.total}}}class E{static{f(this,"MultiProgressBar")}static{d(this,"MultiProgressBar")}bars=new Map;options;interactiveManager;isActive=!1;nextBarId=0;composite=!1;barColors=new Map;constructor(r={},t){this.options={barCompleteChar:u(void 0,"shades_classic"),barIncompleteChar:u(void 0,"shades_classic",!1),composite:!1,format:"progress [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}",fps:10,...r},this.composite=this.options.composite??!1,this.interactiveManager=t}create(r,t=0,e){const a=`bar_${this.nextBarId++}`,s=new x(this,{barCompleteChar:this.options.barCompleteChar,barIncompleteChar:this.options.barIncompleteChar,current:t,format:this.options.format,fps:this.options.fps,total:r,width:40},e);return this.bars.set(a,s),!this.isActive&&this.interactiveManager&&(this.interactiveManager.hook(),this.isActive=!0,this.renderAll()),s}remove(r){for(const[t,e]of this.bars.entries())if(e===r)return this.bars.delete(t),this.bars.size===0?(this.interactiveManager&&this.interactiveManager.unhook(!1),this.isActive=!1):this.renderAll(),!0;return!1}renderAll(){if(!this.interactiveManager||!this.isActive)return;const r=[];if(this.composite){const t=[...this.bars.values()];if(t.length>0){const e=this.renderComposite(t);r.push(e)}}else for(const t of this.bars.values())r.push(t.render());this.interactiveManager.update("stdout",r)}setBarColor(r,t){for(const e of this.bars.values())if(e===r){t?this.barColors.set(e,t):this.barColors.delete(e);break}}stop(){this.isActive=!1,this.interactiveManager&&this.interactiveManager.unhook(!1)}renderComposite(r){if(r.length===0)return"";const t=r[0];if(!t)return"";const e=t.render(),a=e.match(A);if(!a||!a[1])return e;const s=a[1].length,n=Array.from({length:s},()=>[]);r.forEach((c,i)=>{const h=c.getBarState(),C=Math.round(h.current/h.total*s);for(let p=0;p<s;p+=1)p<C&&n[p]?.push(i)});const l=Array.from({length:s},(c,i)=>this.getCompositeChar(r,n[i])).join("");return e.replace(A,`[${l}]`)}getCompositeChar(r,t){if(!t||t.length===0)return r[0]?.getBarState().char??"█";const e=w[this.options.style==="rect"?"rect":"default"],a=e?.[Math.min(t.length-1,e.length-1)]??"█";let s,n=100;for(const h of t){const C=r[h];if(!C)continue;const p=C.getBarState(),m=p.current/p.total*100;(m<n||m===n&&(s===void 0||h>s))&&(n=m,s=h)}const l=s??t[0],c=r[l??0];if(!c)return a;const i=this.barColors.get(c);return i?i(a):a}}export{x as MultiBarInstance,E as MultiProgressBar,T as ProgressBar,k as applyStyleToOptions,u as getBarChar};
1
+ const CHAR_GRADIENTS = {
2
+ default: ["█", "▓", "▒", "░"],
3
+ rect: ["▬", "▮", "▯", "▭"]
4
+ };
5
+ const BAR_REGEX = /\[([^[\]]*)\]/u;
6
+ const getBarChar = (char, style, complete = true) => {
7
+ if (char) {
8
+ return char;
9
+ }
10
+ switch (style) {
11
+ case "ascii": {
12
+ return complete ? "#" : "-";
13
+ }
14
+ case "filled": {
15
+ return complete ? "█" : " ";
16
+ }
17
+ case "rect": {
18
+ return complete ? "▬" : "▭";
19
+ }
20
+ case "shades_classic": {
21
+ return complete ? "█" : "░";
22
+ }
23
+ case "shades_grey": {
24
+ return complete ? "▓" : "░";
25
+ }
26
+ case "solid": {
27
+ return complete ? "█" : " ";
28
+ }
29
+ default: {
30
+ return complete ? "█" : "░";
31
+ }
32
+ }
33
+ };
34
+ const applyStyleToOptions = (options) => {
35
+ if (!options.style) {
36
+ return options;
37
+ }
38
+ const { style } = options;
39
+ const result = { ...options };
40
+ if (result.barCompleteChar === void 0) {
41
+ result.barCompleteChar = getBarChar(void 0, style, true);
42
+ }
43
+ if (result.barIncompleteChar === void 0) {
44
+ result.barIncompleteChar = getBarChar(void 0, style, false);
45
+ }
46
+ if (result.barGlue === void 0) {
47
+ result.barGlue = "";
48
+ }
49
+ return result;
50
+ };
51
+ class ProgressBar {
52
+ options;
53
+ current;
54
+ startTime;
55
+ interactiveManager;
56
+ isActive = false;
57
+ payload;
58
+ /**
59
+ * Creates a new progress bar instance.
60
+ * @param options Configuration options for the progress bar
61
+ * @param interactiveManager Optional interactive manager for rendering
62
+ * @param payload Optional initial payload data for format placeholders
63
+ */
64
+ constructor(options, interactiveManager, payload) {
65
+ const isCompleteArray = Array.isArray(options.barCompleteChar);
66
+ const isIncompleteArray = Array.isArray(options.barIncompleteChar);
67
+ const isGradientMode = isCompleteArray || isIncompleteArray;
68
+ const completeChar = isCompleteArray ? options.barCompleteChar : getBarChar(options.barCompleteChar, "shades_classic");
69
+ const incompleteChar = isIncompleteArray ? options.barIncompleteChar : getBarChar(options.barIncompleteChar, "shades_classic", false);
70
+ this.options = {
71
+ barCompleteChar: completeChar,
72
+ barIncompleteChar: incompleteChar,
73
+ current: 0,
74
+ fps: 10,
75
+ width: 40,
76
+ ...options
77
+ };
78
+ if (isGradientMode) {
79
+ if (!Array.isArray(this.options.barCompleteChar)) {
80
+ this.options.barCompleteChar = [this.options.barCompleteChar];
81
+ }
82
+ if (!Array.isArray(this.options.barIncompleteChar)) {
83
+ this.options.barIncompleteChar = [this.options.barIncompleteChar];
84
+ }
85
+ }
86
+ this.current = this.options.current ?? 0;
87
+ this.startTime = Date.now();
88
+ this.interactiveManager = interactiveManager;
89
+ this.payload = payload;
90
+ }
91
+ /**
92
+ * Updates the progress bar to a new value.
93
+ * @param current The current progress value
94
+ * @param payload Optional payload data to merge with existing data
95
+ */
96
+ update(current, payload) {
97
+ this.current = Math.min(current, this.options.total);
98
+ if (payload) {
99
+ this.payload = { ...this.payload, ...payload };
100
+ }
101
+ if (this.interactiveManager && this.isActive) {
102
+ const progressBar = this.render();
103
+ this.interactiveManager.update("stdout", [progressBar]);
104
+ }
105
+ }
106
+ /**
107
+ * Increments the progress bar by a specified step.
108
+ * @param step Amount to increment (default: 1)
109
+ * @param payload Optional payload data to merge with existing data
110
+ */
111
+ increment(step = 1, payload) {
112
+ this.update(this.current + step, payload);
113
+ }
114
+ /**
115
+ * Renders the progress bar as a formatted string.
116
+ * @returns Formatted progress bar string with all placeholders replaced
117
+ */
118
+ // eslint-disable-next-line sonarjs/cognitive-complexity
119
+ render() {
120
+ const total = this.options.total > 0 ? this.options.total : 1;
121
+ const width = Math.max(0, this.options.width ?? 40);
122
+ const percentage = Math.max(0, Math.min(100, Math.round(this.current / total * 100)));
123
+ const filled = Math.max(0, Math.min(width, Math.round(this.current / total * width)));
124
+ const empty = width - filled;
125
+ let bar;
126
+ if (Array.isArray(this.options.barCompleteChar) || Array.isArray(this.options.barIncompleteChar)) {
127
+ const completeChars = Array.isArray(this.options.barCompleteChar) ? this.options.barCompleteChar : void 0;
128
+ const incompleteChars = Array.isArray(this.options.barIncompleteChar) ? this.options.barIncompleteChar : void 0;
129
+ const completeChar = completeChars?.[completeChars.length - 1] ?? (typeof this.options.barCompleteChar === "string" ? this.options.barCompleteChar : "█");
130
+ const incompleteChar = incompleteChars?.[0] ?? (typeof this.options.barIncompleteChar === "string" ? this.options.barIncompleteChar : "░");
131
+ const completeLength = completeChars?.length ?? 1;
132
+ const progressRatio = this.current / total;
133
+ const totalSteps = width * completeLength;
134
+ const currentStep = Math.round(progressRatio * totalSteps);
135
+ const fractional = currentStep % completeLength;
136
+ let barContent = "";
137
+ for (let i = 0; i < width; i += 1) {
138
+ if (i < filled) {
139
+ const isGradientBoundary = i === filled - 1 && fractional > 0 && completeChars;
140
+ barContent += isGradientBoundary ? completeChars[Math.max(0, fractional - 1)] : completeChar;
141
+ } else {
142
+ barContent += incompleteChar;
143
+ }
144
+ }
145
+ bar = barContent;
146
+ } else {
147
+ const completeChar = typeof this.options.barCompleteChar === "string" ? this.options.barCompleteChar : "█";
148
+ const incompleteChar = typeof this.options.barIncompleteChar === "string" ? this.options.barIncompleteChar : "░";
149
+ bar = completeChar.repeat(filled) + incompleteChar.repeat(empty);
150
+ }
151
+ let format = this.options.format ?? "progress [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}";
152
+ if (this.payload) {
153
+ for (const [k, v] of Object.entries(this.payload)) {
154
+ format = format.replaceAll(`{${k}}`, String(v));
155
+ }
156
+ }
157
+ const eta = this.calculateETA();
158
+ return format.replaceAll("{bar}", bar).replaceAll("{percentage}", String(percentage)).replaceAll("{value}", String(this.current)).replaceAll("{total}", String(this.options.total)).replaceAll("{eta}", String(eta));
159
+ }
160
+ /**
161
+ * Starts the progress bar.
162
+ * @param total Optional total value to set
163
+ * @param startValue Optional starting value
164
+ * @param payload Optional initial payload data
165
+ */
166
+ start(total, startValue, payload) {
167
+ if (total !== void 0) {
168
+ this.options.total = total;
169
+ }
170
+ if (startValue !== void 0) {
171
+ this.current = startValue;
172
+ }
173
+ this.startTime = Date.now();
174
+ this.isActive = true;
175
+ if (this.interactiveManager) {
176
+ this.interactiveManager.hook();
177
+ this.update(this.current, payload);
178
+ }
179
+ }
180
+ /**
181
+ * Stops the progress bar and cleanup.
182
+ */
183
+ stop() {
184
+ this.isActive = false;
185
+ if (this.interactiveManager) {
186
+ this.interactiveManager.unhook(false);
187
+ }
188
+ }
189
+ calculateETA() {
190
+ if (this.current === 0) {
191
+ return 0;
192
+ }
193
+ const elapsed = (Date.now() - this.startTime) / 1e3;
194
+ if (elapsed < 0.1) {
195
+ return 0;
196
+ }
197
+ const rate = this.current / elapsed;
198
+ const remaining = this.options.total - this.current;
199
+ return Math.round(remaining / rate);
200
+ }
201
+ }
202
+ class MultiBarInstance extends ProgressBar {
203
+ multiBar;
204
+ constructor(multiBar, options, payload) {
205
+ super(options, void 0, payload);
206
+ this.multiBar = multiBar;
207
+ }
208
+ update(current, payload) {
209
+ super.update(current, payload);
210
+ this.multiBar.renderAll();
211
+ }
212
+ getBarState() {
213
+ const completeChar = Array.isArray(this.options.barCompleteChar) ? this.options.barCompleteChar[this.options.barCompleteChar.length - 1] : getBarChar(this.options.barCompleteChar, this.options.style ?? "shades_classic", true);
214
+ return {
215
+ char: completeChar ?? "█",
216
+ current: this.current,
217
+ total: this.options.total
218
+ };
219
+ }
220
+ }
221
+ class MultiProgressBar {
222
+ bars = /* @__PURE__ */ new Map();
223
+ options;
224
+ interactiveManager;
225
+ isActive = false;
226
+ nextBarId = 0;
227
+ composite = false;
228
+ barColors = /* @__PURE__ */ new Map();
229
+ /**
230
+ * Creates a new multi progress bar manager.
231
+ * @param options Configuration options for the progress bars
232
+ * @param interactiveManager Optional interactive manager for rendering
233
+ */
234
+ constructor(options = {}, interactiveManager) {
235
+ this.options = {
236
+ barCompleteChar: getBarChar(void 0, "shades_classic"),
237
+ barIncompleteChar: getBarChar(void 0, "shades_classic", false),
238
+ composite: false,
239
+ format: "progress [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}",
240
+ fps: 10,
241
+ ...options
242
+ };
243
+ this.composite = this.options.composite ?? false;
244
+ this.interactiveManager = interactiveManager;
245
+ }
246
+ /**
247
+ * Creates a new progress bar within this multi-bar manager.
248
+ * @param total Total value for the progress bar
249
+ * @param current Starting current value (default: 0)
250
+ * @param payload Optional initial payload data for format placeholders
251
+ * @returns The created progress bar instance
252
+ */
253
+ create(total, current = 0, payload) {
254
+ const barId = `bar_${this.nextBarId++}`;
255
+ const bar = new MultiBarInstance(
256
+ this,
257
+ {
258
+ barCompleteChar: this.options.barCompleteChar,
259
+ barIncompleteChar: this.options.barIncompleteChar,
260
+ current,
261
+ format: this.options.format,
262
+ fps: this.options.fps,
263
+ total,
264
+ width: 40
265
+ },
266
+ payload
267
+ );
268
+ this.bars.set(barId, bar);
269
+ if (!this.isActive && this.interactiveManager) {
270
+ this.interactiveManager.hook();
271
+ this.isActive = true;
272
+ this.renderAll();
273
+ }
274
+ return bar;
275
+ }
276
+ /**
277
+ * Removes a progress bar from the manager.
278
+ * @param bar The progress bar instance to remove
279
+ * @returns True if the bar was removed, false if not found
280
+ */
281
+ remove(bar) {
282
+ for (const [id, existingBar] of this.bars.entries()) {
283
+ if (existingBar === bar) {
284
+ this.bars.delete(id);
285
+ if (this.bars.size === 0) {
286
+ if (this.interactiveManager) {
287
+ this.interactiveManager.unhook(false);
288
+ }
289
+ this.isActive = false;
290
+ } else {
291
+ this.renderAll();
292
+ }
293
+ return true;
294
+ }
295
+ }
296
+ return false;
297
+ }
298
+ /**
299
+ * Renders all progress bars.
300
+ */
301
+ renderAll() {
302
+ if (!this.interactiveManager || !this.isActive) {
303
+ return;
304
+ }
305
+ const lines = [];
306
+ if (this.composite) {
307
+ const barsArray = [...this.bars.values()];
308
+ if (barsArray.length > 0) {
309
+ const compositeOutput = this.renderComposite(barsArray);
310
+ lines.push(compositeOutput);
311
+ }
312
+ } else {
313
+ for (const bar of this.bars.values()) {
314
+ lines.push(bar.render());
315
+ }
316
+ }
317
+ this.interactiveManager.update("stdout", lines);
318
+ }
319
+ /**
320
+ * Sets or removes a color function for a specific bar.
321
+ * @param bar The progress bar instance to color (must be from this MultiProgressBar)
322
+ * @param color Color function or undefined to remove color
323
+ */
324
+ setBarColor(bar, color) {
325
+ for (const instance of this.bars.values()) {
326
+ if (instance === bar) {
327
+ if (color) {
328
+ this.barColors.set(instance, color);
329
+ } else {
330
+ this.barColors.delete(instance);
331
+ }
332
+ break;
333
+ }
334
+ }
335
+ }
336
+ /**
337
+ * Stops all progress bars and cleanup.
338
+ */
339
+ // eslint-disable-next-line sonarjs/no-identical-functions
340
+ stop() {
341
+ this.isActive = false;
342
+ if (this.interactiveManager) {
343
+ this.interactiveManager.unhook(false);
344
+ }
345
+ }
346
+ renderComposite(bars) {
347
+ if (bars.length === 0) {
348
+ return "";
349
+ }
350
+ const firstBar = bars[0];
351
+ if (!firstBar) {
352
+ return "";
353
+ }
354
+ const output = firstBar.render();
355
+ const barMatch = output.match(BAR_REGEX);
356
+ if (!barMatch || !barMatch[1]) {
357
+ return output;
358
+ }
359
+ const width = barMatch[1].length;
360
+ const grid = Array.from({ length: width }, () => []);
361
+ bars.forEach((bar, index) => {
362
+ const state = bar.getBarState();
363
+ const filled = Math.round(state.current / state.total * width);
364
+ for (let i = 0; i < width; i += 1) {
365
+ if (i < filled) {
366
+ grid[i]?.push(index);
367
+ }
368
+ }
369
+ });
370
+ const composite = Array.from({ length: width }, (_, i) => this.getCompositeChar(bars, grid[i])).join("");
371
+ return output.replace(BAR_REGEX, `[${composite}]`);
372
+ }
373
+ getCompositeChar(bars, stack) {
374
+ if (!stack || stack.length === 0) {
375
+ const defaultBar = bars[0];
376
+ return defaultBar?.getBarState().char ?? "█";
377
+ }
378
+ const charGradient = CHAR_GRADIENTS[this.options.style === "rect" ? "rect" : "default"];
379
+ const char = charGradient?.[Math.min(stack.length - 1, charGradient.length - 1)] ?? "█";
380
+ let selectedBar;
381
+ let smallestPercent = 100;
382
+ for (const stackBarIndex of stack) {
383
+ const bar = bars[stackBarIndex];
384
+ if (!bar) {
385
+ continue;
386
+ }
387
+ const barState = bar.getBarState();
388
+ const barPercent = barState.current / barState.total * 100;
389
+ if (barPercent < smallestPercent || barPercent === smallestPercent && (selectedBar === void 0 || stackBarIndex > selectedBar)) {
390
+ smallestPercent = barPercent;
391
+ selectedBar = stackBarIndex;
392
+ }
393
+ }
394
+ const barIndex = selectedBar ?? stack[0];
395
+ const targetBar = bars[barIndex ?? 0];
396
+ if (!targetBar) {
397
+ return char;
398
+ }
399
+ const barColor = this.barColors.get(targetBar);
400
+ return barColor ? barColor(char) : char;
401
+ }
402
+ }
403
+
404
+ export { MultiBarInstance, MultiProgressBar, ProgressBar, applyStyleToOptions, getBarChar };
@@ -1,27 +1,46 @@
1
- import { Options } from 'rotating-file-stream';
2
- import { a as AbstractJsonReporterOptions, A as AbstractJsonReporter } from '../../packem_shared/abstract-json-reporter-CPsNkpz8.js';
3
- import '../../packem_shared/index.d-oxZvg_y7.js';
4
- import 'type-fest';
5
- import '../../packem_shared/types-DVzG8TWL.js';
6
- import '@visulima/colorize';
7
- import '../../interactive/index.js';
8
-
9
- declare class RotatingFileStream {
10
- #private;
11
- constructor(filePath: string, writeImmediately?: boolean, options?: Options);
12
- write(message: string): void;
13
- end(): void;
14
- }
15
-
16
- type FileReporterOptions = AbstractJsonReporterOptions & Options & {
1
+ import type { Options as RfsOptions } from "rotating-file-stream";
2
+ import type { AbstractJsonReporterOptions } from "../json/abstract-json-reporter.d.ts";
3
+ import { AbstractJsonReporter } from "../json/abstract-json-reporter.d.ts";
4
+ import RotatingFileStream from "./utils/rotating-file-stream.d.ts";
5
+ /**
6
+ * Options for configuring the JsonFileReporter.
7
+ */
8
+ export type FileReporterOptions = AbstractJsonReporterOptions & RfsOptions & {
9
+ /** Path to the log file */
17
10
  filePath: string;
11
+ /** Whether to write immediately to disk instead of buffering */
18
12
  writeImmediately?: boolean;
19
13
  };
20
- declare class JsonFileReporter<L extends string = string> extends AbstractJsonReporter<L> {
14
+ /**
15
+ * JSON File Reporter.
16
+ *
17
+ * A reporter that writes structured JSON log entries to rotating files on disk.
18
+ * Supports automatic file rotation based on size, time intervals, and compression.
19
+ * @template L - The log level type
20
+ * @example
21
+ * ```typescript
22
+ * const reporter = new JsonFileReporter({
23
+ * filePath: "/var/log/app.log",
24
+ * interval: "1d", // Rotate daily
25
+ * size: "10M", // Rotate when file reaches 10MB
26
+ * compress: "gzip"
27
+ * });
28
+ *
29
+ * logger.registerReporters([reporter]);
30
+ * ```
31
+ */
32
+ export declare class JsonFileReporter<L extends string = string> extends AbstractJsonReporter<L> {
33
+ /** The rotating file stream instance */
21
34
  protected stream: RotatingFileStream;
35
+ /**
36
+ * Creates a new JsonFileReporter instance.
37
+ * @param options Configuration options for file rotation and JSON formatting
38
+ */
22
39
  constructor(options: FileReporterOptions);
40
+ /**
41
+ * Writes a JSON message to the rotating file stream.
42
+ * @param message The JSON-formatted log message to write
43
+ * @protected
44
+ */
23
45
  protected _log(message: string): void;
24
46
  }
25
-
26
- export { JsonFileReporter };
27
- export type { FileReporterOptions };
@@ -1,4 +1,136 @@
1
- var h=Object.defineProperty;var s=(e,t)=>h(e,"name",{value:t,configurable:!0});import{AbstractJsonReporter as n}from"../../packem_shared/AbstractJsonReporter-UftN6CIL.js";import __cjs_mod__ from "node:module"; // -- packem CommonJS require shim --
2
- const require = __cjs_mod__.createRequire(import.meta.url);
3
- var o=Object.defineProperty,c=s((e,t)=>o(e,"name",{value:t,configurable:!0}),"e");class l{static{s(this,"n")}static{c(this,"SafeStreamHandler")}#t=!0;#e;#r;constructor(t,r){this.#e=t,this.#r=r}write(t){this.writeStream(t)}end(...t){this.#e.end(...t)}get isReady(){return this.#t}writeStream(t){if(!this.#t){console.warn(`Stream busy: ${this.#r}. Write will be dropped: "${t}"`);return}this.#t=!1,this.#e.on("error",r=>{throw r}),this.#e.on("drain",()=>{this.#t=!0}),this.#e.on("finish",()=>{this.#t=!0}),this.#t=this.#e.write(t,()=>{})}}var u=Object.defineProperty,m=s((e,t)=>u(e,"name",{value:t,configurable:!0}),"r$1");class d{static{s(this,"o")}static{m(this,"RotatingFileStream")}#t;#e;#r;#s;#i;constructor(t,r=!1,i={}){if(this.#t=t,this.#e=r,this.#s=i,!this.#e){try{this.#i=require("rotating-file-stream").createStream}catch{throw new Error("The 'rotating-file-stream' package is missing. Make sure to install the 'rotating-file-stream' package.")}this.#r=this.#i(this.#t,i)}}write(t){let r=this.#r;this.#e&&(r=this.#i(this.#t,this.#s));const i=new l(r,this.#t);i.write(t),this.#e&&i.end()}end(){this.#r!==void 0&&this.#r.end()}}var f=Object.defineProperty,p=s((e,t)=>f(e,"name",{value:t,configurable:!0}),"r");class v extends n{static{s(this,"JsonFileReporter")}static{p(this,"JsonFileReporter")}stream;constructor(t){super();const{filePath:r,writeImmediately:i=!1,...a}=t;this.stream=new d(r,i,{compress:"gzip",interval:"1d",size:"10M",...a})}_log(t){this.stream.write(`${t}
4
- `)}}export{v as JsonFileReporter};
1
+ import { AbstractJsonReporter } from '../../packem_shared/AbstractJsonReporter-intFdT_A.js';
2
+
3
+ class SafeStreamHandler {
4
+ #ready = true;
5
+ #stream;
6
+ #name;
7
+ constructor(stream, name) {
8
+ this.#stream = stream;
9
+ this.#name = name;
10
+ }
11
+ /**
12
+ * Writes `message` to the instance's internal stream.
13
+ * @param message Message to write
14
+ */
15
+ write(message) {
16
+ this.writeStream(message);
17
+ }
18
+ /**
19
+ * Calls `end` on this instance's internal stream
20
+ */
21
+ end(...arguments_) {
22
+ this.#stream.end(...arguments_);
23
+ }
24
+ get isReady() {
25
+ return this.#ready;
26
+ }
27
+ writeStream(message) {
28
+ if (!this.#ready) {
29
+ console.warn(`Stream busy: ${this.#name}. Write will be dropped: "${message}"`);
30
+ return;
31
+ }
32
+ this.#ready = false;
33
+ this.#stream.on("error", (error) => {
34
+ throw error;
35
+ });
36
+ this.#stream.on("drain", () => {
37
+ this.#ready = true;
38
+ });
39
+ this.#stream.on("finish", () => {
40
+ this.#ready = true;
41
+ });
42
+ this.#ready = this.#stream.write(message, () => {
43
+ });
44
+ }
45
+ }
46
+
47
+ class RotatingFileStream {
48
+ #filePath;
49
+ #immediate;
50
+ #stream;
51
+ #options;
52
+ #createRfsStream;
53
+ /**
54
+ * Creates a new RotatingFileStream instance.
55
+ * @param filePath Path to the log file
56
+ * @param writeImmediately Whether to write immediately or buffer writes
57
+ * @param options Options for the rotating file stream
58
+ * @throws {Error} If the 'rotating-file-stream' package is not installed
59
+ */
60
+ constructor(filePath, writeImmediately = false, options = {}) {
61
+ this.#filePath = filePath;
62
+ this.#immediate = writeImmediately;
63
+ this.#options = options;
64
+ if (!this.#immediate) {
65
+ try {
66
+ this.#createRfsStream = require("rotating-file-stream").createStream;
67
+ } catch {
68
+ throw new Error("The 'rotating-file-stream' package is missing. Make sure to install the 'rotating-file-stream' package.");
69
+ }
70
+ this.#stream = this.#createRfsStream(this.#filePath, options);
71
+ }
72
+ }
73
+ /**
74
+ * Writes a message to the rotating file stream.
75
+ *
76
+ * If writeImmediately was set to true in the constructor, a new stream
77
+ * is created for each write operation. Otherwise, uses the buffered stream.
78
+ * @param message The message to write to the file
79
+ */
80
+ write(message) {
81
+ let fileStream = this.#stream;
82
+ if (this.#immediate) {
83
+ fileStream = this.#createRfsStream(this.#filePath, this.#options);
84
+ }
85
+ const stream = new SafeStreamHandler(fileStream, this.#filePath);
86
+ stream.write(message);
87
+ if (this.#immediate) {
88
+ stream.end();
89
+ }
90
+ }
91
+ /**
92
+ * Ends the rotating file stream.
93
+ *
94
+ * Closes the underlying stream. When `writeImmediately` is not `true`,
95
+ * calling `write` after calling this method will throw an error.
96
+ */
97
+ end() {
98
+ if (this.#stream !== void 0) {
99
+ this.#stream.end();
100
+ }
101
+ }
102
+ }
103
+
104
+ class JsonFileReporter extends AbstractJsonReporter {
105
+ /** The rotating file stream instance */
106
+ stream;
107
+ /**
108
+ * Creates a new JsonFileReporter instance.
109
+ * @param options Configuration options for file rotation and JSON formatting
110
+ */
111
+ constructor(options) {
112
+ super();
113
+ const { filePath, writeImmediately = false, ...rfsOptions } = options;
114
+ this.stream = new RotatingFileStream(filePath, writeImmediately, {
115
+ compress: "gzip",
116
+ // compress rotated files
117
+ interval: "1d",
118
+ // rotate daily
119
+ size: "10M",
120
+ // rotate every 10 MegaBytes written,
121
+ ...rfsOptions
122
+ });
123
+ }
124
+ /**
125
+ * Writes a JSON message to the rotating file stream.
126
+ * @param message The JSON-formatted log message to write
127
+ * @protected
128
+ */
129
+ // eslint-disable-next-line no-underscore-dangle
130
+ _log(message) {
131
+ this.stream.write(`${message}
132
+ `);
133
+ }
134
+ }
135
+
136
+ export { JsonFileReporter };
@@ -0,0 +1,48 @@
1
+ import type { Options as RfsOptions } from "rotating-file-stream";
2
+ /**
3
+ * Rotating File Stream.
4
+ *
5
+ * A wrapper for the `rotating-file-stream` module that provides optional immediate
6
+ * writing to disk by creating and closing a new stream on each write operation.
7
+ * This is useful for ensuring log messages are written immediately rather than buffered.
8
+ * @example
9
+ * ```typescript
10
+ * // Buffered writing (default)
11
+ * const bufferedStream = new RotatingFileStream("/var/log/app.log", false, {
12
+ * interval: "1d",
13
+ * size: "10M"
14
+ * });
15
+ *
16
+ * // Immediate writing
17
+ * const immediateStream = new RotatingFileStream("/var/log/app.log", true, {
18
+ * interval: "1d"
19
+ * });
20
+ * ```
21
+ */
22
+ declare class RotatingFileStream {
23
+ #private;
24
+ /**
25
+ * Creates a new RotatingFileStream instance.
26
+ * @param filePath Path to the log file
27
+ * @param writeImmediately Whether to write immediately or buffer writes
28
+ * @param options Options for the rotating file stream
29
+ * @throws {Error} If the 'rotating-file-stream' package is not installed
30
+ */
31
+ constructor(filePath: string, writeImmediately?: boolean, options?: RfsOptions);
32
+ /**
33
+ * Writes a message to the rotating file stream.
34
+ *
35
+ * If writeImmediately was set to true in the constructor, a new stream
36
+ * is created for each write operation. Otherwise, uses the buffered stream.
37
+ * @param message The message to write to the file
38
+ */
39
+ write(message: string): void;
40
+ /**
41
+ * Ends the rotating file stream.
42
+ *
43
+ * Closes the underlying stream. When `writeImmediately` is not `true`,
44
+ * calling `write` after calling this method will throw an error.
45
+ */
46
+ end(): void;
47
+ }
48
+ export default RotatingFileStream;