@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 +1 -1
- package/dist/filesink.base.cjs +51 -129
- package/dist/filesink.base.d.cts +3 -51
- package/dist/filesink.base.d.cts.map +1 -1
- package/dist/filesink.base.d.ts +3 -51
- package/dist/filesink.base.d.ts.map +1 -1
- package/dist/filesink.base.js +51 -129
- package/dist/filesink.base.js.map +1 -1
- package/dist/filesink.deno.cjs +23 -20
- package/dist/filesink.deno.d.cts +4 -17
- package/dist/filesink.deno.d.cts.map +1 -1
- package/dist/filesink.deno.d.ts +4 -17
- package/dist/filesink.deno.d.ts.map +1 -1
- package/dist/filesink.deno.js +24 -20
- package/dist/filesink.deno.js.map +1 -1
- package/dist/filesink.node.cjs +23 -17
- package/dist/filesink.node.d.cts +4 -17
- package/dist/filesink.node.d.cts.map +1 -1
- package/dist/filesink.node.d.ts +4 -17
- package/dist/filesink.node.d.ts.map +1 -1
- package/dist/filesink.node.js +24 -17
- package/dist/filesink.node.js.map +1 -1
- package/filesink.base.ts +30 -250
- package/filesink.deno.ts +4 -43
- package/filesink.jsr.ts +7 -32
- package/filesink.node.ts +4 -40
- package/filesink.test.ts +0 -120
- package/package.json +12 -7
- package/tsdown.config.ts +1 -1
package/deno.json
CHANGED
package/dist/filesink.base.cjs
CHANGED
|
@@ -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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
}
|
|
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
|
|
65
|
-
if (
|
|
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)
|
|
71
|
-
else if (flushTimer === null && flushInterval > 0) startFlushTimer();
|
|
36
|
+
if (shouldFlushBySize || shouldFlushByTime) flushBuffer();
|
|
72
37
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
153
|
-
|
|
94
|
+
options.writeSync(fd, bytes);
|
|
95
|
+
options.flushSync(fd);
|
|
154
96
|
offset += bytes.length;
|
|
155
97
|
lastFlushTimestamp = Date.now();
|
|
156
|
-
}
|
|
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
|
-
|
|
171
|
-
|
|
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)
|
|
176
|
-
else if (flushTimer === null && flushInterval > 0) startFlushTimer();
|
|
105
|
+
if (shouldFlushBySize || shouldFlushByTime) flushBuffer();
|
|
177
106
|
};
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
|
111
|
+
return sink;
|
|
190
112
|
}
|
|
191
113
|
|
|
192
114
|
//#endregion
|
package/dist/filesink.base.d.cts
CHANGED
|
@@ -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.
|
|
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.
|
|
158
|
-
* returns a sink that also implements {@link AsyncDisposable}.
|
|
110
|
+
* object that closes the file when disposed.
|
|
159
111
|
*/
|
|
160
112
|
//#endregion
|
|
161
|
-
export {
|
|
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;
|
|
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"}
|
package/dist/filesink.base.d.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
158
|
-
* returns a sink that also implements {@link AsyncDisposable}.
|
|
110
|
+
* object that closes the file when disposed.
|
|
159
111
|
*/
|
|
160
112
|
//#endregion
|
|
161
|
-
export {
|
|
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;
|
|
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"}
|
package/dist/filesink.base.js
CHANGED
|
@@ -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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
}
|
|
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
|
|
64
|
-
if (
|
|
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)
|
|
70
|
-
else if (flushTimer === null && flushInterval > 0) startFlushTimer();
|
|
35
|
+
if (shouldFlushBySize || shouldFlushByTime) flushBuffer();
|
|
71
36
|
};
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
152
|
-
|
|
93
|
+
options.writeSync(fd, bytes);
|
|
94
|
+
options.flushSync(fd);
|
|
153
95
|
offset += bytes.length;
|
|
154
96
|
lastFlushTimestamp = Date.now();
|
|
155
|
-
}
|
|
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
|
-
|
|
170
|
-
|
|
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)
|
|
175
|
-
else if (flushTimer === null && flushInterval > 0) startFlushTimer();
|
|
104
|
+
if (shouldFlushBySize || shouldFlushByTime) flushBuffer();
|
|
176
105
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
|
110
|
+
return sink;
|
|
189
111
|
}
|
|
190
112
|
|
|
191
113
|
//#endregion
|