@logtape/file 1.0.0-dev.241 → 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.
Files changed (43) hide show
  1. package/deno.json +1 -1
  2. package/dist/filesink.base.cjs +52 -347
  3. package/dist/filesink.base.d.cts +3 -65
  4. package/dist/filesink.base.d.cts.map +1 -1
  5. package/dist/filesink.base.d.ts +3 -65
  6. package/dist/filesink.base.d.ts.map +1 -1
  7. package/dist/filesink.base.js +52 -347
  8. package/dist/filesink.base.js.map +1 -1
  9. package/dist/filesink.deno.cjs +23 -26
  10. package/dist/filesink.deno.d.cts +4 -17
  11. package/dist/filesink.deno.d.cts.map +1 -1
  12. package/dist/filesink.deno.d.ts +4 -17
  13. package/dist/filesink.deno.d.ts.map +1 -1
  14. package/dist/filesink.deno.js +24 -26
  15. package/dist/filesink.deno.js.map +1 -1
  16. package/dist/filesink.node.cjs +23 -33
  17. package/dist/filesink.node.d.cts +4 -17
  18. package/dist/filesink.node.d.cts.map +1 -1
  19. package/dist/filesink.node.d.ts +4 -17
  20. package/dist/filesink.node.d.ts.map +1 -1
  21. package/dist/filesink.node.js +24 -33
  22. package/dist/filesink.node.js.map +1 -1
  23. package/dist/mod.cjs +1 -3
  24. package/dist/mod.d.cts +1 -2
  25. package/dist/mod.d.ts +1 -2
  26. package/dist/mod.js +1 -2
  27. package/filesink.base.ts +37 -618
  28. package/filesink.deno.ts +4 -57
  29. package/filesink.jsr.ts +7 -32
  30. package/filesink.node.ts +4 -58
  31. package/filesink.test.ts +0 -120
  32. package/mod.ts +0 -2
  33. package/package.json +12 -7
  34. package/tsdown.config.ts +2 -2
  35. package/dist/streamfilesink.cjs +0 -84
  36. package/dist/streamfilesink.d.cts +0 -95
  37. package/dist/streamfilesink.d.cts.map +0 -1
  38. package/dist/streamfilesink.d.ts +0 -95
  39. package/dist/streamfilesink.d.ts.map +0 -1
  40. package/dist/streamfilesink.js +0 -84
  41. package/dist/streamfilesink.js.map +0 -1
  42. package/streamfilesink.test.ts +0 -336
  43. package/streamfilesink.ts +0 -136
package/filesink.deno.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import type { Sink } from "@logtape/logtape";
2
2
  import {
3
- type AsyncRotatingFileSinkDriver,
4
3
  type FileSinkOptions,
5
4
  getBaseFileSink,
6
5
  getBaseRotatingFileSink,
@@ -18,13 +17,6 @@ export const denoDriver: RotatingFileSinkDriver<Deno.FsFile> = {
18
17
  writeSync(fd, chunk) {
19
18
  fd.writeSync(chunk);
20
19
  },
21
- writeManySync(fd: Deno.FsFile, chunks: Uint8Array[]): void {
22
- // Deno doesn't have writev, but we can optimize by writing all chunks
23
- // then doing a single sync operation
24
- for (const chunk of chunks) {
25
- fd.writeSync(chunk);
26
- }
27
- },
28
20
  flushSync(fd) {
29
21
  fd.syncSync();
30
22
  },
@@ -35,27 +27,6 @@ export const denoDriver: RotatingFileSinkDriver<Deno.FsFile> = {
35
27
  renameSync: globalThis?.Deno.renameSync,
36
28
  };
37
29
 
38
- /**
39
- * A Deno-specific async file sink driver.
40
- * @since 1.0.0
41
- */
42
- export const denoAsyncDriver: AsyncRotatingFileSinkDriver<Deno.FsFile> = {
43
- ...denoDriver,
44
- async writeMany(fd: Deno.FsFile, chunks: Uint8Array[]): Promise<void> {
45
- // Deno doesn't have async writev, but we can write all chunks
46
- // then do a single async sync
47
- for (const chunk of chunks) {
48
- await fd.write(chunk);
49
- }
50
- },
51
- async flush(fd) {
52
- await fd.sync();
53
- },
54
- close(fd) {
55
- return Promise.resolve(fd.close());
56
- },
57
- };
58
-
59
30
  /**
60
31
  * Get a file sink.
61
32
  *
@@ -64,24 +35,12 @@ export const denoAsyncDriver: AsyncRotatingFileSinkDriver<Deno.FsFile> = {
64
35
  * @param path A path to the file to write to.
65
36
  * @param options The options for the sink.
66
37
  * @returns A sink that writes to the file. The sink is also a disposable
67
- * object that closes the file when disposed. If `nonBlocking` is enabled,
68
- * returns a sink that also implements {@link AsyncDisposable}.
38
+ * object that closes the file when disposed.
69
39
  */
70
- export function getFileSink(
71
- path: string,
72
- options?: FileSinkOptions,
73
- ): Sink & Disposable;
74
- export function getFileSink(
75
- path: string,
76
- options: FileSinkOptions & { nonBlocking: true },
77
- ): Sink & AsyncDisposable;
78
40
  export function getFileSink(
79
41
  path: string,
80
42
  options: FileSinkOptions = {},
81
- ): Sink & (Disposable | AsyncDisposable) {
82
- if (options.nonBlocking) {
83
- return getBaseFileSink(path, { ...options, ...denoAsyncDriver });
84
- }
43
+ ): Sink & Disposable {
85
44
  return getBaseFileSink(path, { ...options, ...denoDriver });
86
45
  }
87
46
 
@@ -98,24 +57,12 @@ export function getFileSink(
98
57
  * @param path A path to the file to write to.
99
58
  * @param options The options for the sink and the file driver.
100
59
  * @returns A sink that writes to the file. The sink is also a disposable
101
- * object that closes the file when disposed. If `nonBlocking` is enabled,
102
- * returns a sink that also implements {@link AsyncDisposable}.
60
+ * object that closes the file when disposed.
103
61
  */
104
- export function getRotatingFileSink(
105
- path: string,
106
- options?: RotatingFileSinkOptions,
107
- ): Sink & Disposable;
108
- export function getRotatingFileSink(
109
- path: string,
110
- options: RotatingFileSinkOptions & { nonBlocking: true },
111
- ): Sink & AsyncDisposable;
112
62
  export function getRotatingFileSink(
113
63
  path: string,
114
64
  options: RotatingFileSinkOptions = {},
115
- ): Sink & (Disposable | AsyncDisposable) {
116
- if (options.nonBlocking) {
117
- return getBaseRotatingFileSink(path, { ...options, ...denoAsyncDriver });
118
- }
65
+ ): Sink & Disposable {
119
66
  return getBaseRotatingFileSink(path, { ...options, ...denoDriver });
120
67
  }
121
68
 
package/filesink.jsr.ts CHANGED
@@ -4,10 +4,7 @@ import type {
4
4
  RotatingFileSinkOptions,
5
5
  } from "./filesink.base.ts";
6
6
 
7
- const filesink: Omit<
8
- typeof import("./filesink.deno.ts"),
9
- "denoDriver" | "denoAsyncDriver"
10
- > =
7
+ const filesink: Omit<typeof import("./filesink.deno.ts"), "denoDriver"> =
11
8
  // dnt-shim-ignore
12
9
  await ("Deno" in globalThis
13
10
  ? import("./filesink.deno.ts")
@@ -21,24 +18,13 @@ const filesink: Omit<
21
18
  * @param path A path to the file to write to.
22
19
  * @param options The options for the sink.
23
20
  * @returns A sink that writes to the file. The sink is also a disposable
24
- * object that closes the file when disposed. If `nonBlocking` is enabled,
25
- * returns a sink that also implements {@link AsyncDisposable}.
21
+ * object that closes the file when disposed.
26
22
  */
27
- export function getFileSink(
28
- path: string,
29
- options?: FileSinkOptions,
30
- ): Sink & Disposable;
31
- export function getFileSink(
32
- path: string,
33
- options: FileSinkOptions & { nonBlocking: true },
34
- ): Sink & AsyncDisposable;
35
23
  export function getFileSink(
36
24
  path: string,
37
25
  options: FileSinkOptions = {},
38
- ): Sink & (Disposable | AsyncDisposable) {
39
- return filesink.getFileSink(path, options) as
40
- & Sink
41
- & (Disposable | AsyncDisposable);
26
+ ): Sink & Disposable {
27
+ return filesink.getFileSink(path, options);
42
28
  }
43
29
 
44
30
  /**
@@ -54,24 +40,13 @@ export function getFileSink(
54
40
  * @param path A path to the file to write to.
55
41
  * @param options The options for the sink and the file driver.
56
42
  * @returns A sink that writes to the file. The sink is also a disposable
57
- * object that closes the file when disposed. If `nonBlocking` is enabled,
58
- * returns a sink that also implements {@link AsyncDisposable}.
43
+ * object that closes the file when disposed.
59
44
  */
60
- export function getRotatingFileSink(
61
- path: string,
62
- options?: RotatingFileSinkOptions,
63
- ): Sink & Disposable;
64
- export function getRotatingFileSink(
65
- path: string,
66
- options: RotatingFileSinkOptions & { nonBlocking: true },
67
- ): Sink & AsyncDisposable;
68
45
  export function getRotatingFileSink(
69
46
  path: string,
70
47
  options: RotatingFileSinkOptions = {},
71
- ): Sink & (Disposable | AsyncDisposable) {
72
- return filesink.getRotatingFileSink(path, options) as
73
- & Sink
74
- & (Disposable | AsyncDisposable);
48
+ ): Sink & Disposable {
49
+ return filesink.getRotatingFileSink(path, options);
75
50
  }
76
51
 
77
52
  // cSpell: ignore filesink
package/filesink.node.ts CHANGED
@@ -1,8 +1,6 @@
1
1
  import type { Sink } from "@logtape/logtape";
2
2
  import fs from "node:fs";
3
- import { promisify } from "node:util";
4
3
  import {
5
- type AsyncRotatingFileSinkDriver,
6
4
  type FileSinkOptions,
7
5
  getBaseFileSink,
8
6
  getBaseRotatingFileSink,
@@ -18,40 +16,12 @@ export const nodeDriver: RotatingFileSinkDriver<number | void> = {
18
16
  return fs.openSync(path, "a");
19
17
  },
20
18
  writeSync: fs.writeSync,
21
- writeManySync(fd: number, chunks: Uint8Array[]): void {
22
- if (chunks.length === 0) return;
23
- if (chunks.length === 1) {
24
- fs.writeSync(fd, chunks[0]);
25
- return;
26
- }
27
- // Use writev for multiple chunks
28
- fs.writevSync(fd, chunks);
29
- },
30
19
  flushSync: fs.fsyncSync,
31
20
  closeSync: fs.closeSync,
32
21
  statSync: fs.statSync,
33
22
  renameSync: fs.renameSync,
34
23
  };
35
24
 
36
- /**
37
- * A Node.js-specific async file sink driver.
38
- * @since 1.0.0
39
- */
40
- export const nodeAsyncDriver: AsyncRotatingFileSinkDriver<number | void> = {
41
- ...nodeDriver,
42
- async writeMany(fd: number, chunks: Uint8Array[]): Promise<void> {
43
- if (chunks.length === 0) return;
44
- if (chunks.length === 1) {
45
- await promisify(fs.write)(fd, chunks[0]);
46
- return;
47
- }
48
- // Use async writev for multiple chunks
49
- await promisify(fs.writev)(fd, chunks);
50
- },
51
- flush: promisify(fs.fsync),
52
- close: promisify(fs.close),
53
- };
54
-
55
25
  /**
56
26
  * Get a file sink.
57
27
  *
@@ -60,24 +30,12 @@ export const nodeAsyncDriver: AsyncRotatingFileSinkDriver<number | void> = {
60
30
  * @param path A path to the file to write to.
61
31
  * @param options The options for the sink.
62
32
  * @returns A sink that writes to the file. The sink is also a disposable
63
- * object that closes the file when disposed. If `nonBlocking` is enabled,
64
- * returns a sink that also implements {@link AsyncDisposable}.
33
+ * object that closes the file when disposed.
65
34
  */
66
- export function getFileSink(
67
- path: string,
68
- options?: FileSinkOptions,
69
- ): Sink & Disposable;
70
- export function getFileSink(
71
- path: string,
72
- options: FileSinkOptions & { nonBlocking: true },
73
- ): Sink & AsyncDisposable;
74
35
  export function getFileSink(
75
36
  path: string,
76
37
  options: FileSinkOptions = {},
77
- ): Sink & (Disposable | AsyncDisposable) {
78
- if (options.nonBlocking) {
79
- return getBaseFileSink(path, { ...options, ...nodeAsyncDriver });
80
- }
38
+ ): Sink & Disposable {
81
39
  return getBaseFileSink(path, { ...options, ...nodeDriver });
82
40
  }
83
41
 
@@ -94,24 +52,12 @@ export function getFileSink(
94
52
  * @param path A path to the file to write to.
95
53
  * @param options The options for the sink and the file driver.
96
54
  * @returns A sink that writes to the file. The sink is also a disposable
97
- * object that closes the file when disposed. If `nonBlocking` is enabled,
98
- * returns a sink that also implements {@link AsyncDisposable}.
55
+ * object that closes the file when disposed.
99
56
  */
100
- export function getRotatingFileSink(
101
- path: string,
102
- options?: RotatingFileSinkOptions,
103
- ): Sink & Disposable;
104
- export function getRotatingFileSink(
105
- path: string,
106
- options: RotatingFileSinkOptions & { nonBlocking: true },
107
- ): Sink & AsyncDisposable;
108
57
  export function getRotatingFileSink(
109
58
  path: string,
110
59
  options: RotatingFileSinkOptions = {},
111
- ): Sink & (Disposable | AsyncDisposable) {
112
- if (options.nonBlocking) {
113
- return getBaseRotatingFileSink(path, { ...options, ...nodeAsyncDriver });
114
- }
60
+ ): Sink & Disposable {
115
61
  return getBaseRotatingFileSink(path, { ...options, ...nodeDriver });
116
62
  }
117
63
 
package/filesink.test.ts CHANGED
@@ -2,10 +2,8 @@ import { getFileSink, getRotatingFileSink } from "#filesink";
2
2
  import { suite } from "@alinea/suite";
3
3
  import { isDeno } from "@david/which-runtime";
4
4
  import type { Sink } from "@logtape/logtape";
5
- import { assert } from "@std/assert/assert";
6
5
  import { assertEquals } from "@std/assert/equals";
7
6
  import { assertThrows } from "@std/assert/throws";
8
- import { delay } from "@std/async/delay";
9
7
  import { join } from "@std/path/join";
10
8
  import fs from "node:fs";
11
9
  import { tmpdir } from "node:os";
@@ -693,122 +691,4 @@ test("getBaseFileSink() with flushInterval disabled", () => {
693
691
  assertEquals(content.includes("Hello, 123 & 456!"), true);
694
692
  });
695
693
 
696
- test("getFileSink() with nonBlocking mode", async () => {
697
- const path = makeTempFileSync();
698
- const sink = getFileSink(path, {
699
- nonBlocking: true,
700
- bufferSize: 50, // Small buffer to trigger flush by size
701
- });
702
-
703
- // Check that it returns AsyncDisposable
704
- assert(typeof sink === "function");
705
- assert(Symbol.asyncDispose in sink);
706
-
707
- // Add enough records to trigger buffer flush
708
- sink(debug);
709
- sink(info);
710
-
711
- // Wait for async flush to complete
712
- await delay(50);
713
- const content = fs.readFileSync(path, { encoding: "utf-8" });
714
- assert(content.includes("Hello, 123 & 456!"));
715
-
716
- await (sink as Sink & AsyncDisposable)[Symbol.asyncDispose]();
717
- });
718
-
719
- test("getRotatingFileSink() with nonBlocking mode", async () => {
720
- const path = makeTempFileSync();
721
- const sink = getRotatingFileSink(path, {
722
- maxSize: 200,
723
- nonBlocking: true,
724
- bufferSize: 1000, // Large buffer to prevent immediate flush
725
- flushInterval: 50, // Short interval for testing
726
- });
727
-
728
- // Check that it returns AsyncDisposable
729
- assert(typeof sink === "function");
730
- assert(Symbol.asyncDispose in sink);
731
-
732
- // Add records with current timestamp
733
- const record1 = { ...debug, timestamp: Date.now() };
734
- const record2 = { ...info, timestamp: Date.now() };
735
- sink(record1);
736
- sink(record2);
737
- assertEquals(fs.readFileSync(path, { encoding: "utf-8" }), ""); // Not written yet
738
-
739
- // Wait for flush interval to pass
740
- await delay(100);
741
- const content = fs.readFileSync(path, { encoding: "utf-8" });
742
- assert(content.includes("Hello, 123 & 456!"));
743
-
744
- await (sink as Sink & AsyncDisposable)[Symbol.asyncDispose]();
745
- });
746
-
747
- test("getFileSink() with nonBlocking high-volume logging", async () => {
748
- const path = makeTempFileSync();
749
- const sink = getFileSink(path, {
750
- nonBlocking: true,
751
- bufferSize: 50, // Small buffer to trigger flush
752
- flushInterval: 0, // Disable time-based flushing for this test
753
- }) as unknown as Sink & AsyncDisposable;
754
-
755
- // Add enough records to trigger buffer flush (50 chars per record roughly)
756
- let totalChars = 0;
757
- let recordCount = 0;
758
- while (totalChars < 100) { // Exceed buffer size
759
- sink(debug);
760
- totalChars += 67; // Approximate length of each debug record
761
- recordCount++;
762
- }
763
-
764
- // Wait for async flush to complete
765
- await delay(50);
766
- const content = fs.readFileSync(path, { encoding: "utf-8" });
767
-
768
- // Should have some records written by now
769
- const writtenCount = (content.match(/Hello, 123 & 456!/g) || []).length;
770
- assert(
771
- writtenCount > 0,
772
- `Expected some records to be written, but got ${writtenCount}`,
773
- );
774
-
775
- await sink[Symbol.asyncDispose]();
776
- });
777
-
778
- test("getRotatingFileSink() with nonBlocking rotation", async () => {
779
- const path = makeTempFileSync();
780
- const sink = getRotatingFileSink(path, {
781
- maxSize: 150, // Small size to trigger rotation
782
- nonBlocking: true,
783
- bufferSize: 100,
784
- flushInterval: 10,
785
- }) as unknown as Sink & AsyncDisposable;
786
-
787
- // Add enough records to trigger rotation
788
- sink(debug);
789
- sink(info);
790
- sink(warning);
791
- sink(error);
792
-
793
- // Wait for all flushes and rotation to complete
794
- await delay(200);
795
-
796
- // Check that rotation occurred
797
- const mainContent = fs.readFileSync(path, { encoding: "utf-8" });
798
- let rotatedContent = "";
799
- try {
800
- rotatedContent = fs.readFileSync(`${path}.1`, { encoding: "utf-8" });
801
- } catch {
802
- // No rotation occurred
803
- }
804
-
805
- const allContent = mainContent + rotatedContent;
806
-
807
- // Should have all 4 records somewhere
808
- const recordCount = (allContent.match(/Hello, 123 & 456!/g) || []).length;
809
- assertEquals(recordCount, 4);
810
-
811
- await sink[Symbol.asyncDispose]();
812
- });
813
-
814
694
  // cSpell: ignore filesink
package/mod.ts CHANGED
@@ -4,6 +4,4 @@ export type {
4
4
  RotatingFileSinkDriver,
5
5
  RotatingFileSinkOptions,
6
6
  } from "./filesink.base.ts";
7
- export type { StreamFileSinkOptions } from "./streamfilesink.ts";
8
7
  export { getFileSink, getRotatingFileSink } from "#filesink";
9
- export { getStreamFileSink } from "./streamfilesink.ts";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logtape/file",
3
- "version": "1.0.0-dev.241+13810dcf",
3
+ "version": "1.0.0-dev.246+c7630de7",
4
4
  "description": "File sink and rotating file sink for LogTape",
5
5
  "keywords": [
6
6
  "logging",
@@ -34,29 +34,34 @@
34
34
  "types": "./dist/mod.d.ts",
35
35
  "exports": {
36
36
  ".": {
37
+ "types": {
38
+ "import": "./dist/mod.d.ts",
39
+ "require": "./dist/mod.d.cts"
40
+ },
37
41
  "import": "./dist/mod.js",
38
- "require": "./dist/mod.cjs",
39
- "types": "./dist/mod.d.ts"
42
+ "require": "./dist/mod.cjs"
40
43
  },
41
44
  "./package.json": "./package.json"
42
45
  },
43
46
  "imports": {
44
47
  "#filesink": {
48
+ "types": {
49
+ "import": "./dist/filesink.node.d.ts",
50
+ "require": "./dist/filesink.node.d.cts"
51
+ },
45
52
  "bun": "./dist/filesink.node.js",
46
53
  "deno": "./dist/filesink.deno.js",
47
54
  "import": "./dist/filesink.node.js",
48
- "require": "./dist/filesink.node.cjs",
49
- "types": "./dist/filesink.node.d.ts"
55
+ "require": "./dist/filesink.node.cjs"
50
56
  }
51
57
  },
52
58
  "peerDependencies": {
53
- "@logtape/logtape": "1.0.0-dev.241+13810dcf"
59
+ "@logtape/logtape": "1.0.0-dev.246+c7630de7"
54
60
  },
55
61
  "devDependencies": {
56
62
  "@alinea/suite": "^0.6.3",
57
63
  "@david/which-runtime": "npm:@jsr/david__which-runtime@^0.2.1",
58
64
  "@std/assert": "npm:@jsr/std__assert@^1.0.13",
59
- "@std/async": "npm:@jsr/std__async@^1.0.13",
60
65
  "@std/path": "npm:@jsr/std__path@^1.1.0",
61
66
  "tsdown": "^0.12.7",
62
67
  "typescript": "^5.8.3"
package/tsdown.config.ts CHANGED
@@ -6,13 +6,13 @@ export default defineConfig({
6
6
  sourcemap: true,
7
7
  },
8
8
  format: ["esm", "cjs"],
9
- platform: "node",
9
+ platform: "neutral",
10
10
  unbundle: true,
11
11
  inputOptions: {
12
12
  onLog(level, log, defaultHandler) {
13
13
  if (
14
14
  level === "warn" && log.code === "UNRESOLVED_IMPORT" &&
15
- log.exporter === "#filesink"
15
+ ["node:fs", "#filesink"].includes(log.exporter ?? "")
16
16
  ) {
17
17
  return;
18
18
  }
@@ -1,84 +0,0 @@
1
- const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
- const __logtape_logtape = require_rolldown_runtime.__toESM(require("@logtape/logtape"));
3
- const node_fs = require_rolldown_runtime.__toESM(require("node:fs"));
4
- const node_stream = require_rolldown_runtime.__toESM(require("node:stream"));
5
-
6
- //#region streamfilesink.ts
7
- /**
8
- * Create a high-performance stream-based file sink that writes log records to a file.
9
- *
10
- * This sink uses Node.js PassThrough streams piped to WriteStreams for optimal
11
- * I/O performance. It leverages the Node.js stream infrastructure to provide
12
- * automatic backpressure management, efficient buffering, and asynchronous writes
13
- * without blocking the main thread.
14
- *
15
- * ## Performance Characteristics
16
- *
17
- * - **High Performance**: Optimized for high-volume logging scenarios
18
- * - **Non-blocking**: Uses asynchronous I/O that doesn't block the main thread
19
- * - **Memory Efficient**: Automatic backpressure prevents memory buildup
20
- * - **Stream-based**: Leverages Node.js native stream optimizations
21
- *
22
- * ## When to Use
23
- *
24
- * Use this sink when you need:
25
- * - High-performance file logging for production applications
26
- * - Non-blocking I/O behavior for real-time applications
27
- * - Automatic backpressure handling for high-volume scenarios
28
- * - Simple file output without complex buffering configuration
29
- *
30
- * For more control over buffering behavior, consider using {@link getFileSink}
31
- * instead, which provides options for buffer size, flush intervals, and
32
- * non-blocking modes.
33
- *
34
- * ## Example
35
- *
36
- * ```typescript
37
- * import { configure } from "@logtape/logtape";
38
- * import { getStreamFileSink } from "@logtape/file";
39
- *
40
- * await configure({
41
- * sinks: {
42
- * file: getStreamFileSink("app.log", {
43
- * highWaterMark: 32768 // 32KB buffer for high-volume logging
44
- * })
45
- * },
46
- * loggers: [
47
- * { category: ["myapp"], sinks: ["file"] }
48
- * ]
49
- * });
50
- * ```
51
- *
52
- * @param path The path to the file to write logs to. The file will be created
53
- * if it doesn't exist, or appended to if it does exist.
54
- * @param options Configuration options for the stream-based sink.
55
- * @returns A sink that writes formatted log records to the specified file.
56
- * The returned sink implements `Disposable` for proper resource cleanup.
57
- *
58
- * @since 1.0.0
59
- */
60
- function getStreamFileSink(path, options = {}) {
61
- const highWaterMark = options.highWaterMark ?? 16384;
62
- const formatter = options.formatter ?? __logtape_logtape.defaultTextFormatter;
63
- const passThrough = new node_stream.PassThrough({
64
- highWaterMark,
65
- objectMode: false
66
- });
67
- const writeStream = (0, node_fs.createWriteStream)(path, { flags: "a" });
68
- passThrough.pipe(writeStream);
69
- let disposed = false;
70
- const sink = (record) => {
71
- if (disposed) return;
72
- passThrough.write(formatter(record));
73
- };
74
- sink[Symbol.dispose] = () => {
75
- if (disposed) return;
76
- disposed = true;
77
- passThrough.end();
78
- writeStream.end();
79
- };
80
- return sink;
81
- }
82
-
83
- //#endregion
84
- exports.getStreamFileSink = getStreamFileSink;
@@ -1,95 +0,0 @@
1
- import { Sink, TextFormatter } from "@logtape/logtape";
2
-
3
- //#region streamfilesink.d.ts
4
-
5
- /**
6
- * Options for the {@link getStreamFileSink} function.
7
- *
8
- * This interface configures the high-performance stream-based file sink that
9
- * uses Node.js PassThrough streams for optimal I/O performance with automatic
10
- * backpressure management.
11
- *
12
- * @since 1.0.0
13
- */
14
- interface StreamFileSinkOptions {
15
- /**
16
- * High water mark for the PassThrough stream buffer in bytes.
17
- *
18
- * This controls the internal buffer size of the PassThrough stream.
19
- * Higher values can improve performance for high-volume logging but use
20
- * more memory. Lower values reduce memory usage but may impact performance.
21
- *
22
- * @default 16384
23
- * @since 1.0.0
24
- */
25
- readonly highWaterMark?: number;
26
- /**
27
- * A custom formatter for log records.
28
- *
29
- * If not specified, the default text formatter will be used, which formats
30
- * records in the standard LogTape format with timestamp, level, category,
31
- * and message.
32
- *
33
- * @default defaultTextFormatter
34
- * @since 1.0.0
35
- */
36
- readonly formatter?: TextFormatter;
37
- }
38
- /**
39
- * Create a high-performance stream-based file sink that writes log records to a file.
40
- *
41
- * This sink uses Node.js PassThrough streams piped to WriteStreams for optimal
42
- * I/O performance. It leverages the Node.js stream infrastructure to provide
43
- * automatic backpressure management, efficient buffering, and asynchronous writes
44
- * without blocking the main thread.
45
- *
46
- * ## Performance Characteristics
47
- *
48
- * - **High Performance**: Optimized for high-volume logging scenarios
49
- * - **Non-blocking**: Uses asynchronous I/O that doesn't block the main thread
50
- * - **Memory Efficient**: Automatic backpressure prevents memory buildup
51
- * - **Stream-based**: Leverages Node.js native stream optimizations
52
- *
53
- * ## When to Use
54
- *
55
- * Use this sink when you need:
56
- * - High-performance file logging for production applications
57
- * - Non-blocking I/O behavior for real-time applications
58
- * - Automatic backpressure handling for high-volume scenarios
59
- * - Simple file output without complex buffering configuration
60
- *
61
- * For more control over buffering behavior, consider using {@link getFileSink}
62
- * instead, which provides options for buffer size, flush intervals, and
63
- * non-blocking modes.
64
- *
65
- * ## Example
66
- *
67
- * ```typescript
68
- * import { configure } from "@logtape/logtape";
69
- * import { getStreamFileSink } from "@logtape/file";
70
- *
71
- * await configure({
72
- * sinks: {
73
- * file: getStreamFileSink("app.log", {
74
- * highWaterMark: 32768 // 32KB buffer for high-volume logging
75
- * })
76
- * },
77
- * loggers: [
78
- * { category: ["myapp"], sinks: ["file"] }
79
- * ]
80
- * });
81
- * ```
82
- *
83
- * @param path The path to the file to write logs to. The file will be created
84
- * if it doesn't exist, or appended to if it does exist.
85
- * @param options Configuration options for the stream-based sink.
86
- * @returns A sink that writes formatted log records to the specified file.
87
- * The returned sink implements `Disposable` for proper resource cleanup.
88
- *
89
- * @since 1.0.0
90
- */
91
- declare function getStreamFileSink(path: string, options?: StreamFileSinkOptions): Sink & Disposable;
92
- //# sourceMappingURL=streamfilesink.d.ts.map
93
- //#endregion
94
- export { StreamFileSinkOptions, getStreamFileSink };
95
- //# sourceMappingURL=streamfilesink.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"streamfilesink.d.cts","names":[],"sources":["../streamfilesink.ts"],"sourcesContent":[],"mappings":";;;;;;AAkBA;AA+EA;;;;;AAGoB;UAlFH,qBAAA;;;;;;;;;;;;;;;;;;;;;;uBAuBM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwDP,iBAAA,yBAEL,wBACR,OAAO"}