@logtape/file 1.0.0-dev.240 → 1.0.0-dev.246

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.
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logtape/file",
3
- "version": "1.0.0-dev.240+9524a425",
3
+ "version": "1.0.0-dev.246+c7630de7",
4
4
  "license": "MIT",
5
5
  "exports": "./mod.ts",
6
6
  "imports": {
@@ -2,6 +2,15 @@ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
2
  const __logtape_logtape = require_rolldown_runtime.__toESM(require("@logtape/logtape"));
3
3
 
4
4
  //#region filesink.base.ts
5
+ /**
6
+ * Get a platform-independent file sink.
7
+ *
8
+ * @typeParam TFile The type of the file descriptor.
9
+ * @param path A path to the file to write to.
10
+ * @param options The options for the sink and the file driver.
11
+ * @returns A sink that writes to the file. The sink is also a disposable
12
+ * object that closes the file when disposed.
13
+ */
5
14
  function getBaseFileSink(path, options) {
6
15
  const formatter = options.formatter ?? __logtape_logtape.defaultTextFormatter;
7
16
  const encoder = options.encoder ?? new TextEncoder();
@@ -10,79 +19,43 @@ function getBaseFileSink(path, options) {
10
19
  let fd = options.lazy ? null : options.openSync(path);
11
20
  let buffer = "";
12
21
  let lastFlushTimestamp = Date.now();
13
- if (!options.nonBlocking) {
14
- function flushBuffer$1() {
15
- if (fd == null) return;
16
- if (buffer.length > 0) {
17
- options.writeSync(fd, encoder.encode(buffer));
18
- buffer = "";
19
- options.flushSync(fd);
20
- lastFlushTimestamp = Date.now();
21
- }
22
- }
23
- const sink = (record) => {
24
- if (fd == null) fd = options.openSync(path);
25
- buffer += formatter(record);
26
- const shouldFlushBySize = buffer.length >= bufferSize;
27
- const shouldFlushByTime = flushInterval > 0 && record.timestamp - lastFlushTimestamp >= flushInterval;
28
- if (shouldFlushBySize || shouldFlushByTime) flushBuffer$1();
29
- };
30
- sink[Symbol.dispose] = () => {
31
- if (fd !== null) {
32
- flushBuffer$1();
33
- options.closeSync(fd);
34
- }
35
- };
36
- return sink;
37
- }
38
- const asyncOptions = options;
39
- let disposed = false;
40
- let activeFlush = null;
41
- let flushTimer = null;
42
- async function flushBuffer() {
43
- if (fd == null || buffer.length === 0) return;
44
- const data = buffer;
45
- buffer = "";
46
- try {
47
- asyncOptions.writeSync(fd, encoder.encode(data));
48
- await asyncOptions.flush(fd);
22
+ function flushBuffer() {
23
+ if (fd == null) return;
24
+ if (buffer.length > 0) {
25
+ options.writeSync(fd, encoder.encode(buffer));
26
+ buffer = "";
27
+ options.flushSync(fd);
49
28
  lastFlushTimestamp = Date.now();
50
- } catch {}
51
- }
52
- function scheduleFlush() {
53
- if (activeFlush || disposed) return;
54
- activeFlush = flushBuffer().finally(() => {
55
- activeFlush = null;
56
- });
57
- }
58
- function startFlushTimer() {
59
- if (flushTimer !== null || disposed) return;
60
- flushTimer = setInterval(() => {
61
- scheduleFlush();
62
- }, flushInterval);
29
+ }
63
30
  }
64
- const nonBlockingSink = (record) => {
65
- if (disposed) return;
66
- if (fd == null) fd = asyncOptions.openSync(path);
31
+ const sink = (record) => {
32
+ if (fd == null) fd = options.openSync(path);
67
33
  buffer += formatter(record);
68
34
  const shouldFlushBySize = buffer.length >= bufferSize;
69
35
  const shouldFlushByTime = flushInterval > 0 && record.timestamp - lastFlushTimestamp >= flushInterval;
70
- if (shouldFlushBySize || shouldFlushByTime) scheduleFlush();
71
- else if (flushTimer === null && flushInterval > 0) startFlushTimer();
36
+ if (shouldFlushBySize || shouldFlushByTime) flushBuffer();
72
37
  };
73
- nonBlockingSink[Symbol.asyncDispose] = async () => {
74
- disposed = true;
75
- if (flushTimer !== null) {
76
- clearInterval(flushTimer);
77
- flushTimer = null;
38
+ sink[Symbol.dispose] = () => {
39
+ if (fd !== null) {
40
+ flushBuffer();
41
+ options.closeSync(fd);
78
42
  }
79
- await flushBuffer();
80
- if (fd !== null) try {
81
- await asyncOptions.close(fd);
82
- } catch {}
83
43
  };
84
- return nonBlockingSink;
44
+ return sink;
85
45
  }
46
+ /**
47
+ * Get a platform-independent rotating file sink.
48
+ *
49
+ * This sink writes log records to a file, and rotates the file when it reaches
50
+ * the `maxSize`. The rotated files are named with the original file name
51
+ * followed by a dot and a number, starting from 1. The number is incremented
52
+ * for each rotation, and the maximum number of files to keep is `maxFiles`.
53
+ *
54
+ * @param path A path to the file to write to.
55
+ * @param options The options for the sink and the file driver.
56
+ * @returns A sink that writes to the file. The sink is also a disposable
57
+ * object that closes the file when disposed.
58
+ */
86
59
  function getBaseRotatingFileSink(path, options) {
87
60
  const formatter = options.formatter ?? __logtape_logtape.defaultTextFormatter;
88
61
  const encoder = options.encoder ?? new TextEncoder();
@@ -97,7 +70,6 @@ function getBaseRotatingFileSink(path, options) {
97
70
  } catch {}
98
71
  let fd = options.openSync(path);
99
72
  let lastFlushTimestamp = Date.now();
100
- let buffer = "";
101
73
  function shouldRollover(bytes) {
102
74
  return offset + bytes.length > maxSize;
103
75
  }
@@ -114,79 +86,29 @@ function getBaseRotatingFileSink(path, options) {
114
86
  offset = 0;
115
87
  fd = options.openSync(path);
116
88
  }
117
- if (!options.nonBlocking) {
118
- function flushBuffer$1() {
119
- if (buffer.length > 0) {
120
- const bytes = encoder.encode(buffer);
121
- buffer = "";
122
- if (shouldRollover(bytes)) performRollover();
123
- options.writeSync(fd, bytes);
124
- options.flushSync(fd);
125
- offset += bytes.length;
126
- lastFlushTimestamp = Date.now();
127
- }
128
- }
129
- const sink = (record) => {
130
- buffer += formatter(record);
131
- const shouldFlushBySize = buffer.length >= bufferSize;
132
- const shouldFlushByTime = flushInterval > 0 && record.timestamp - lastFlushTimestamp >= flushInterval;
133
- if (shouldFlushBySize || shouldFlushByTime) flushBuffer$1();
134
- };
135
- sink[Symbol.dispose] = () => {
136
- flushBuffer$1();
137
- options.closeSync(fd);
138
- };
139
- return sink;
140
- }
141
- const asyncOptions = options;
142
- let disposed = false;
143
- let activeFlush = null;
144
- let flushTimer = null;
145
- async function flushBuffer() {
146
- if (buffer.length === 0) return;
147
- const data = buffer;
148
- buffer = "";
149
- try {
150
- const bytes = encoder.encode(data);
89
+ function flushBuffer() {
90
+ if (buffer.length > 0) {
91
+ const bytes = encoder.encode(buffer);
92
+ buffer = "";
151
93
  if (shouldRollover(bytes)) performRollover();
152
- asyncOptions.writeSync(fd, bytes);
153
- await asyncOptions.flush(fd);
94
+ options.writeSync(fd, bytes);
95
+ options.flushSync(fd);
154
96
  offset += bytes.length;
155
97
  lastFlushTimestamp = Date.now();
156
- } catch {}
157
- }
158
- function scheduleFlush() {
159
- if (activeFlush || disposed) return;
160
- activeFlush = flushBuffer().finally(() => {
161
- activeFlush = null;
162
- });
163
- }
164
- function startFlushTimer() {
165
- if (flushTimer !== null || disposed) return;
166
- flushTimer = setInterval(() => {
167
- scheduleFlush();
168
- }, flushInterval);
98
+ }
169
99
  }
170
- const nonBlockingSink = (record) => {
171
- if (disposed) return;
100
+ let buffer = "";
101
+ const sink = (record) => {
172
102
  buffer += formatter(record);
173
103
  const shouldFlushBySize = buffer.length >= bufferSize;
174
104
  const shouldFlushByTime = flushInterval > 0 && record.timestamp - lastFlushTimestamp >= flushInterval;
175
- if (shouldFlushBySize || shouldFlushByTime) scheduleFlush();
176
- else if (flushTimer === null && flushInterval > 0) startFlushTimer();
105
+ if (shouldFlushBySize || shouldFlushByTime) flushBuffer();
177
106
  };
178
- nonBlockingSink[Symbol.asyncDispose] = async () => {
179
- disposed = true;
180
- if (flushTimer !== null) {
181
- clearInterval(flushTimer);
182
- flushTimer = null;
183
- }
184
- await flushBuffer();
185
- try {
186
- await asyncOptions.close(fd);
187
- } catch {}
107
+ sink[Symbol.dispose] = () => {
108
+ flushBuffer();
109
+ options.closeSync(fd);
188
110
  };
189
- return nonBlockingSink;
111
+ return sink;
190
112
  }
191
113
 
192
114
  //#endregion
@@ -26,15 +26,6 @@ type FileSinkOptions = StreamSinkOptions & {
26
26
  * @since 0.12.0
27
27
  */
28
28
  flushInterval?: number;
29
- /**
30
- * Enable non-blocking mode with background flushing.
31
- * When enabled, flush operations are performed asynchronously to prevent
32
- * blocking the main thread during file I/O operations.
33
- *
34
- * @default `false`
35
- * @since 1.0.0
36
- */
37
- nonBlocking?: boolean;
38
29
  };
39
30
  /**
40
31
  * A platform-specific file sink driver.
@@ -63,23 +54,6 @@ interface FileSinkDriver<TFile> {
63
54
  */
64
55
  closeSync(fd: TFile): void;
65
56
  }
66
- /**
67
- * A platform-specific async file sink driver.
68
- * @typeParam TFile The type of the file descriptor.
69
- * @since 1.0.0
70
- */
71
- interface AsyncFileSinkDriver<TFile> extends FileSinkDriver<TFile> {
72
- /**
73
- * Asynchronously flush the file to ensure that all data is written to the disk.
74
- * @param fd The file descriptor.
75
- */
76
- flush(fd: TFile): Promise<void>;
77
- /**
78
- * Asynchronously close the file.
79
- * @param fd The file descriptor.
80
- */
81
- close(fd: TFile): Promise<void>;
82
- }
83
57
  /**
84
58
  * Get a platform-independent file sink.
85
59
  *
@@ -87,8 +61,7 @@ interface AsyncFileSinkDriver<TFile> extends FileSinkDriver<TFile> {
87
61
  * @param path A path to the file to write to.
88
62
  * @param options The options for the sink and the file driver.
89
63
  * @returns A sink that writes to the file. The sink is also a disposable
90
- * object that closes the file when disposed. If `nonBlocking` is enabled,
91
- * returns a sink that also implements {@link AsyncDisposable}.
64
+ * object that closes the file when disposed.
92
65
  */
93
66
 
94
67
  /**
@@ -123,26 +96,6 @@ interface RotatingFileSinkDriver<TFile> extends FileSinkDriver<TFile> {
123
96
  */
124
97
  renameSync(oldPath: string, newPath: string): void;
125
98
  }
126
- /**
127
- * A platform-specific async rotating file sink driver.
128
- * @since 1.0.0
129
- */
130
- interface AsyncRotatingFileSinkDriver<TFile> extends AsyncFileSinkDriver<TFile> {
131
- /**
132
- * Get the size of the file.
133
- * @param path A path to the file.
134
- * @returns The `size` of the file in bytes, in an object.
135
- */
136
- statSync(path: string): {
137
- size: number;
138
- };
139
- /**
140
- * Rename a file.
141
- * @param oldPath A path to the file to rename.
142
- * @param newPath A path to be renamed to.
143
- */
144
- renameSync(oldPath: string, newPath: string): void;
145
- }
146
99
  /**
147
100
  * Get a platform-independent rotating file sink.
148
101
  *
@@ -154,9 +107,8 @@ interface AsyncRotatingFileSinkDriver<TFile> extends AsyncFileSinkDriver<TFile>
154
107
  * @param path A path to the file to write to.
155
108
  * @param options The options for the sink and the file driver.
156
109
  * @returns A sink that writes to the file. The sink is also a disposable
157
- * object that closes the file when disposed. If `nonBlocking` is enabled,
158
- * returns a sink that also implements {@link AsyncDisposable}.
110
+ * object that closes the file when disposed.
159
111
  */
160
112
  //#endregion
161
- export { AsyncRotatingFileSinkDriver, FileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions };
113
+ export { FileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions };
162
114
  //# sourceMappingURL=filesink.base.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"filesink.base.d.cts","names":[],"sources":["../filesink.base.ts"],"sourcesContent":[],"mappings":";;;;;;AAUA;AAuCiB,KAvCL,eAAA,GAAkB,iBAuCC,GAAA;EAAA;;;EAYV,IAAS,CAAA,EAAA,OAAA;EAAU;;AAYnB;AAQrB;;;;EAKiB,UAAG,CAAA,EAAA,MAAA;EAAO;;;AALuC;AA0JlE;;;EAAqE,aAApB,CAAA,EAAA,MAAA;EAAI;AAerD;;;;AAAqE;AAoBrE;;EAA4C,WACd,CAAA,EAAA,OAAA;CAAK;AAAN;;;;UA9NZ;;;;;0BAKS;;;;;;gBAOV,cAAc;;;;;gBAMd;;;;;gBAMA;;;;;;;UAQC,mCAAmC,eAAe;;;;;YAKvD,QAAQ;;;;;YAMR,QAAQ;;;;;;;;;;;;;;;;UA+IH,uBAAA,SAAgC,KAAK;;;;;;;;;;;;;UAerC,sCAAsC,eAAe;;;;;;;;;;;;;;;;;;;;UAoBrD,2CACP,oBAAoB"}
1
+ {"version":3,"file":"filesink.base.d.cts","names":[],"sources":["../filesink.base.ts"],"sourcesContent":[],"mappings":";;;;;;AAUA;AA6BiB,KA7BL,eAAA,GAAkB,iBA6BC,GAAA;EAAA;;;EAYV,IAAS,CAAA,EAAA,OAAA;EAAU;;AAYnB;AA0DrB;;;;EAAqD,UAAA,CAAA,EAAA,MAAA;EAepC;;;;AAAoD;;;;;;;;;UAjGpD;;;;;0BAKS;;;;;;gBAOV,cAAc;;;;;gBAMd;;;;;gBAMA;;;;;;;;;;;;;;;UA0DC,uBAAA,SAAgC,KAAK;;;;;;;;;;;;;UAerC,sCAAsC,eAAe"}
@@ -26,15 +26,6 @@ type FileSinkOptions = StreamSinkOptions & {
26
26
  * @since 0.12.0
27
27
  */
28
28
  flushInterval?: number;
29
- /**
30
- * Enable non-blocking mode with background flushing.
31
- * When enabled, flush operations are performed asynchronously to prevent
32
- * blocking the main thread during file I/O operations.
33
- *
34
- * @default `false`
35
- * @since 1.0.0
36
- */
37
- nonBlocking?: boolean;
38
29
  };
39
30
  /**
40
31
  * A platform-specific file sink driver.
@@ -63,23 +54,6 @@ interface FileSinkDriver<TFile> {
63
54
  */
64
55
  closeSync(fd: TFile): void;
65
56
  }
66
- /**
67
- * A platform-specific async file sink driver.
68
- * @typeParam TFile The type of the file descriptor.
69
- * @since 1.0.0
70
- */
71
- interface AsyncFileSinkDriver<TFile> extends FileSinkDriver<TFile> {
72
- /**
73
- * Asynchronously flush the file to ensure that all data is written to the disk.
74
- * @param fd The file descriptor.
75
- */
76
- flush(fd: TFile): Promise<void>;
77
- /**
78
- * Asynchronously close the file.
79
- * @param fd The file descriptor.
80
- */
81
- close(fd: TFile): Promise<void>;
82
- }
83
57
  /**
84
58
  * Get a platform-independent file sink.
85
59
  *
@@ -87,8 +61,7 @@ interface AsyncFileSinkDriver<TFile> extends FileSinkDriver<TFile> {
87
61
  * @param path A path to the file to write to.
88
62
  * @param options The options for the sink and the file driver.
89
63
  * @returns A sink that writes to the file. The sink is also a disposable
90
- * object that closes the file when disposed. If `nonBlocking` is enabled,
91
- * returns a sink that also implements {@link AsyncDisposable}.
64
+ * object that closes the file when disposed.
92
65
  */
93
66
 
94
67
  /**
@@ -123,26 +96,6 @@ interface RotatingFileSinkDriver<TFile> extends FileSinkDriver<TFile> {
123
96
  */
124
97
  renameSync(oldPath: string, newPath: string): void;
125
98
  }
126
- /**
127
- * A platform-specific async rotating file sink driver.
128
- * @since 1.0.0
129
- */
130
- interface AsyncRotatingFileSinkDriver<TFile> extends AsyncFileSinkDriver<TFile> {
131
- /**
132
- * Get the size of the file.
133
- * @param path A path to the file.
134
- * @returns The `size` of the file in bytes, in an object.
135
- */
136
- statSync(path: string): {
137
- size: number;
138
- };
139
- /**
140
- * Rename a file.
141
- * @param oldPath A path to the file to rename.
142
- * @param newPath A path to be renamed to.
143
- */
144
- renameSync(oldPath: string, newPath: string): void;
145
- }
146
99
  /**
147
100
  * Get a platform-independent rotating file sink.
148
101
  *
@@ -154,9 +107,8 @@ interface AsyncRotatingFileSinkDriver<TFile> extends AsyncFileSinkDriver<TFile>
154
107
  * @param path A path to the file to write to.
155
108
  * @param options The options for the sink and the file driver.
156
109
  * @returns A sink that writes to the file. The sink is also a disposable
157
- * object that closes the file when disposed. If `nonBlocking` is enabled,
158
- * returns a sink that also implements {@link AsyncDisposable}.
110
+ * object that closes the file when disposed.
159
111
  */
160
112
  //#endregion
161
- export { AsyncRotatingFileSinkDriver, FileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions };
113
+ export { FileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions };
162
114
  //# sourceMappingURL=filesink.base.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"filesink.base.d.ts","names":[],"sources":["../filesink.base.ts"],"sourcesContent":[],"mappings":";;;;;;AAUA;AAuCiB,KAvCL,eAAA,GAAkB,iBAuCC,GAAA;EAAA;;;EAYV,IAAS,CAAA,EAAA,OAAA;EAAU;;AAYnB;AAQrB;;;;EAKiB,UAAG,CAAA,EAAA,MAAA;EAAO;;;AALuC;AA0JlE;;;EAAqE,aAApB,CAAA,EAAA,MAAA;EAAI;AAerD;;;;AAAqE;AAoBrE;;EAA4C,WACd,CAAA,EAAA,OAAA;CAAK;AAAN;;;;UA9NZ;;;;;0BAKS;;;;;;gBAOV,cAAc;;;;;gBAMd;;;;;gBAMA;;;;;;;UAQC,mCAAmC,eAAe;;;;;YAKvD,QAAQ;;;;;YAMR,QAAQ;;;;;;;;;;;;;;;;UA+IH,uBAAA,SAAgC,KAAK;;;;;;;;;;;;;UAerC,sCAAsC,eAAe;;;;;;;;;;;;;;;;;;;;UAoBrD,2CACP,oBAAoB"}
1
+ {"version":3,"file":"filesink.base.d.ts","names":[],"sources":["../filesink.base.ts"],"sourcesContent":[],"mappings":";;;;;;AAUA;AA6BiB,KA7BL,eAAA,GAAkB,iBA6BC,GAAA;EAAA;;;EAYV,IAAS,CAAA,EAAA,OAAA;EAAU;;AAYnB;AA0DrB;;;;EAAqD,UAAA,CAAA,EAAA,MAAA;EAepC;;;;AAAoD;;;;;;;;;UAjGpD;;;;;0BAKS;;;;;;gBAOV,cAAc;;;;;gBAMd;;;;;gBAMA;;;;;;;;;;;;;;;UA0DC,uBAAA,SAAgC,KAAK;;;;;;;;;;;;;UAerC,sCAAsC,eAAe"}
@@ -1,6 +1,15 @@
1
1
  import { defaultTextFormatter } from "@logtape/logtape";
2
2
 
3
3
  //#region filesink.base.ts
4
+ /**
5
+ * Get a platform-independent file sink.
6
+ *
7
+ * @typeParam TFile The type of the file descriptor.
8
+ * @param path A path to the file to write to.
9
+ * @param options The options for the sink and the file driver.
10
+ * @returns A sink that writes to the file. The sink is also a disposable
11
+ * object that closes the file when disposed.
12
+ */
4
13
  function getBaseFileSink(path, options) {
5
14
  const formatter = options.formatter ?? defaultTextFormatter;
6
15
  const encoder = options.encoder ?? new TextEncoder();
@@ -9,79 +18,43 @@ function getBaseFileSink(path, options) {
9
18
  let fd = options.lazy ? null : options.openSync(path);
10
19
  let buffer = "";
11
20
  let lastFlushTimestamp = Date.now();
12
- if (!options.nonBlocking) {
13
- function flushBuffer$1() {
14
- if (fd == null) return;
15
- if (buffer.length > 0) {
16
- options.writeSync(fd, encoder.encode(buffer));
17
- buffer = "";
18
- options.flushSync(fd);
19
- lastFlushTimestamp = Date.now();
20
- }
21
- }
22
- const sink = (record) => {
23
- if (fd == null) fd = options.openSync(path);
24
- buffer += formatter(record);
25
- const shouldFlushBySize = buffer.length >= bufferSize;
26
- const shouldFlushByTime = flushInterval > 0 && record.timestamp - lastFlushTimestamp >= flushInterval;
27
- if (shouldFlushBySize || shouldFlushByTime) flushBuffer$1();
28
- };
29
- sink[Symbol.dispose] = () => {
30
- if (fd !== null) {
31
- flushBuffer$1();
32
- options.closeSync(fd);
33
- }
34
- };
35
- return sink;
36
- }
37
- const asyncOptions = options;
38
- let disposed = false;
39
- let activeFlush = null;
40
- let flushTimer = null;
41
- async function flushBuffer() {
42
- if (fd == null || buffer.length === 0) return;
43
- const data = buffer;
44
- buffer = "";
45
- try {
46
- asyncOptions.writeSync(fd, encoder.encode(data));
47
- await asyncOptions.flush(fd);
21
+ function flushBuffer() {
22
+ if (fd == null) return;
23
+ if (buffer.length > 0) {
24
+ options.writeSync(fd, encoder.encode(buffer));
25
+ buffer = "";
26
+ options.flushSync(fd);
48
27
  lastFlushTimestamp = Date.now();
49
- } catch {}
50
- }
51
- function scheduleFlush() {
52
- if (activeFlush || disposed) return;
53
- activeFlush = flushBuffer().finally(() => {
54
- activeFlush = null;
55
- });
56
- }
57
- function startFlushTimer() {
58
- if (flushTimer !== null || disposed) return;
59
- flushTimer = setInterval(() => {
60
- scheduleFlush();
61
- }, flushInterval);
28
+ }
62
29
  }
63
- const nonBlockingSink = (record) => {
64
- if (disposed) return;
65
- if (fd == null) fd = asyncOptions.openSync(path);
30
+ const sink = (record) => {
31
+ if (fd == null) fd = options.openSync(path);
66
32
  buffer += formatter(record);
67
33
  const shouldFlushBySize = buffer.length >= bufferSize;
68
34
  const shouldFlushByTime = flushInterval > 0 && record.timestamp - lastFlushTimestamp >= flushInterval;
69
- if (shouldFlushBySize || shouldFlushByTime) scheduleFlush();
70
- else if (flushTimer === null && flushInterval > 0) startFlushTimer();
35
+ if (shouldFlushBySize || shouldFlushByTime) flushBuffer();
71
36
  };
72
- nonBlockingSink[Symbol.asyncDispose] = async () => {
73
- disposed = true;
74
- if (flushTimer !== null) {
75
- clearInterval(flushTimer);
76
- flushTimer = null;
37
+ sink[Symbol.dispose] = () => {
38
+ if (fd !== null) {
39
+ flushBuffer();
40
+ options.closeSync(fd);
77
41
  }
78
- await flushBuffer();
79
- if (fd !== null) try {
80
- await asyncOptions.close(fd);
81
- } catch {}
82
42
  };
83
- return nonBlockingSink;
43
+ return sink;
84
44
  }
45
+ /**
46
+ * Get a platform-independent rotating file sink.
47
+ *
48
+ * This sink writes log records to a file, and rotates the file when it reaches
49
+ * the `maxSize`. The rotated files are named with the original file name
50
+ * followed by a dot and a number, starting from 1. The number is incremented
51
+ * for each rotation, and the maximum number of files to keep is `maxFiles`.
52
+ *
53
+ * @param path A path to the file to write to.
54
+ * @param options The options for the sink and the file driver.
55
+ * @returns A sink that writes to the file. The sink is also a disposable
56
+ * object that closes the file when disposed.
57
+ */
85
58
  function getBaseRotatingFileSink(path, options) {
86
59
  const formatter = options.formatter ?? defaultTextFormatter;
87
60
  const encoder = options.encoder ?? new TextEncoder();
@@ -96,7 +69,6 @@ function getBaseRotatingFileSink(path, options) {
96
69
  } catch {}
97
70
  let fd = options.openSync(path);
98
71
  let lastFlushTimestamp = Date.now();
99
- let buffer = "";
100
72
  function shouldRollover(bytes) {
101
73
  return offset + bytes.length > maxSize;
102
74
  }
@@ -113,79 +85,29 @@ function getBaseRotatingFileSink(path, options) {
113
85
  offset = 0;
114
86
  fd = options.openSync(path);
115
87
  }
116
- if (!options.nonBlocking) {
117
- function flushBuffer$1() {
118
- if (buffer.length > 0) {
119
- const bytes = encoder.encode(buffer);
120
- buffer = "";
121
- if (shouldRollover(bytes)) performRollover();
122
- options.writeSync(fd, bytes);
123
- options.flushSync(fd);
124
- offset += bytes.length;
125
- lastFlushTimestamp = Date.now();
126
- }
127
- }
128
- const sink = (record) => {
129
- buffer += formatter(record);
130
- const shouldFlushBySize = buffer.length >= bufferSize;
131
- const shouldFlushByTime = flushInterval > 0 && record.timestamp - lastFlushTimestamp >= flushInterval;
132
- if (shouldFlushBySize || shouldFlushByTime) flushBuffer$1();
133
- };
134
- sink[Symbol.dispose] = () => {
135
- flushBuffer$1();
136
- options.closeSync(fd);
137
- };
138
- return sink;
139
- }
140
- const asyncOptions = options;
141
- let disposed = false;
142
- let activeFlush = null;
143
- let flushTimer = null;
144
- async function flushBuffer() {
145
- if (buffer.length === 0) return;
146
- const data = buffer;
147
- buffer = "";
148
- try {
149
- const bytes = encoder.encode(data);
88
+ function flushBuffer() {
89
+ if (buffer.length > 0) {
90
+ const bytes = encoder.encode(buffer);
91
+ buffer = "";
150
92
  if (shouldRollover(bytes)) performRollover();
151
- asyncOptions.writeSync(fd, bytes);
152
- await asyncOptions.flush(fd);
93
+ options.writeSync(fd, bytes);
94
+ options.flushSync(fd);
153
95
  offset += bytes.length;
154
96
  lastFlushTimestamp = Date.now();
155
- } catch {}
156
- }
157
- function scheduleFlush() {
158
- if (activeFlush || disposed) return;
159
- activeFlush = flushBuffer().finally(() => {
160
- activeFlush = null;
161
- });
162
- }
163
- function startFlushTimer() {
164
- if (flushTimer !== null || disposed) return;
165
- flushTimer = setInterval(() => {
166
- scheduleFlush();
167
- }, flushInterval);
97
+ }
168
98
  }
169
- const nonBlockingSink = (record) => {
170
- if (disposed) return;
99
+ let buffer = "";
100
+ const sink = (record) => {
171
101
  buffer += formatter(record);
172
102
  const shouldFlushBySize = buffer.length >= bufferSize;
173
103
  const shouldFlushByTime = flushInterval > 0 && record.timestamp - lastFlushTimestamp >= flushInterval;
174
- if (shouldFlushBySize || shouldFlushByTime) scheduleFlush();
175
- else if (flushTimer === null && flushInterval > 0) startFlushTimer();
104
+ if (shouldFlushBySize || shouldFlushByTime) flushBuffer();
176
105
  };
177
- nonBlockingSink[Symbol.asyncDispose] = async () => {
178
- disposed = true;
179
- if (flushTimer !== null) {
180
- clearInterval(flushTimer);
181
- flushTimer = null;
182
- }
183
- await flushBuffer();
184
- try {
185
- await asyncOptions.close(fd);
186
- } catch {}
106
+ sink[Symbol.dispose] = () => {
107
+ flushBuffer();
108
+ options.closeSync(fd);
187
109
  };
188
- return nonBlockingSink;
110
+ return sink;
189
111
  }
190
112
 
191
113
  //#endregion