@logtape/file 1.2.0-dev.344 → 1.2.0-dev.354

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.2.0-dev.344+834f24a9",
3
+ "version": "1.2.0-dev.354+e11ec186",
4
4
  "license": "MIT",
5
5
  "exports": "./src/mod.ts",
6
6
  "imports": {
@@ -53,7 +53,8 @@ const node_stream = require_rolldown_runtime.__toESM(require("node:stream"));
53
53
  * if it doesn't exist, or appended to if it does exist.
54
54
  * @param options Configuration options for the stream-based sink.
55
55
  * @returns A sink that writes formatted log records to the specified file.
56
- * The returned sink implements `Disposable` for proper resource cleanup.
56
+ * The returned sink implements `AsyncDisposable` for proper resource cleanup
57
+ * that waits for all data to be flushed to disk.
57
58
  *
58
59
  * @since 1.0.0
59
60
  */
@@ -84,7 +84,8 @@ interface StreamFileSinkOptions {
84
84
  * if it doesn't exist, or appended to if it does exist.
85
85
  * @param options Configuration options for the stream-based sink.
86
86
  * @returns A sink that writes formatted log records to the specified file.
87
- * The returned sink implements `Disposable` for proper resource cleanup.
87
+ * The returned sink implements `AsyncDisposable` for proper resource cleanup
88
+ * that waits for all data to be flushed to disk.
88
89
  *
89
90
  * @since 1.0.0
90
91
  */
@@ -1 +1 @@
1
- {"version":3,"file":"streamfilesink.d.cts","names":[],"sources":["../src/streamfilesink.ts"],"sourcesContent":[],"mappings":";;;;;;AAkBA;AA+EA;;;;;AAGyB;UAlFR,qBAAA;;;;;;;;;;;;;;;;;;;;;;uBAuBM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwDP,iBAAA,yBAEL,wBACR,OAAO"}
1
+ {"version":3,"file":"streamfilesink.d.cts","names":[],"sources":["../src/streamfilesink.ts"],"sourcesContent":[],"mappings":";;;;;;AAkBA;AAgFA;;;;;AAGyB;UAnFR,qBAAA;;;;;;;;;;;;;;;;;;;;;;uBAuBM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyDP,iBAAA,yBAEL,wBACR,OAAO"}
@@ -84,7 +84,8 @@ interface StreamFileSinkOptions {
84
84
  * if it doesn't exist, or appended to if it does exist.
85
85
  * @param options Configuration options for the stream-based sink.
86
86
  * @returns A sink that writes formatted log records to the specified file.
87
- * The returned sink implements `Disposable` for proper resource cleanup.
87
+ * The returned sink implements `AsyncDisposable` for proper resource cleanup
88
+ * that waits for all data to be flushed to disk.
88
89
  *
89
90
  * @since 1.0.0
90
91
  */
@@ -1 +1 @@
1
- {"version":3,"file":"streamfilesink.d.ts","names":[],"sources":["../src/streamfilesink.ts"],"sourcesContent":[],"mappings":";;;;;;AAkBA;AA+EA;;;;;AAGyB;UAlFR,qBAAA;;;;;;;;;;;;;;;;;;;;;;uBAuBM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwDP,iBAAA,yBAEL,wBACR,OAAO"}
1
+ {"version":3,"file":"streamfilesink.d.ts","names":[],"sources":["../src/streamfilesink.ts"],"sourcesContent":[],"mappings":";;;;;;AAkBA;AAgFA;;;;;AAGyB;UAnFR,qBAAA;;;;;;;;;;;;;;;;;;;;;;uBAuBM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyDP,iBAAA,yBAEL,wBACR,OAAO"}
@@ -52,7 +52,8 @@ import { PassThrough } from "node:stream";
52
52
  * if it doesn't exist, or appended to if it does exist.
53
53
  * @param options Configuration options for the stream-based sink.
54
54
  * @returns A sink that writes formatted log records to the specified file.
55
- * The returned sink implements `Disposable` for proper resource cleanup.
55
+ * The returned sink implements `AsyncDisposable` for proper resource cleanup
56
+ * that waits for all data to be flushed to disk.
56
57
  *
57
58
  * @since 1.0.0
58
59
  */
@@ -1 +1 @@
1
- {"version":3,"file":"streamfilesink.js","names":["path: string","options: StreamFileSinkOptions","sink: Sink & AsyncDisposable","record: LogRecord"],"sources":["../src/streamfilesink.ts"],"sourcesContent":["import {\n defaultTextFormatter,\n type LogRecord,\n type Sink,\n type TextFormatter,\n} from \"@logtape/logtape\";\nimport { createWriteStream } from \"node:fs\";\nimport { PassThrough } from \"node:stream\";\n\n/**\n * Options for the {@link getStreamFileSink} function.\n *\n * This interface configures the high-performance stream-based file sink that\n * uses Node.js PassThrough streams for optimal I/O performance with automatic\n * backpressure management.\n *\n * @since 1.0.0\n */\nexport interface StreamFileSinkOptions {\n /**\n * High water mark for the PassThrough stream buffer in bytes.\n *\n * This controls the internal buffer size of the PassThrough stream.\n * Higher values can improve performance for high-volume logging but use\n * more memory. Lower values reduce memory usage but may impact performance.\n *\n * @default 16384\n * @since 1.0.0\n */\n readonly highWaterMark?: number;\n\n /**\n * A custom formatter for log records.\n *\n * If not specified, the default text formatter will be used, which formats\n * records in the standard LogTape format with timestamp, level, category,\n * and message.\n *\n * @default defaultTextFormatter\n * @since 1.0.0\n */\n readonly formatter?: TextFormatter;\n}\n\n/**\n * Create a high-performance stream-based file sink that writes log records to a file.\n *\n * This sink uses Node.js PassThrough streams piped to WriteStreams for optimal\n * I/O performance. It leverages the Node.js stream infrastructure to provide\n * automatic backpressure management, efficient buffering, and asynchronous writes\n * without blocking the main thread.\n *\n * ## Performance Characteristics\n *\n * - **High Performance**: Optimized for high-volume logging scenarios\n * - **Non-blocking**: Uses asynchronous I/O that doesn't block the main thread\n * - **Memory Efficient**: Automatic backpressure prevents memory buildup\n * - **Stream-based**: Leverages Node.js native stream optimizations\n *\n * ## When to Use\n *\n * Use this sink when you need:\n * - High-performance file logging for production applications\n * - Non-blocking I/O behavior for real-time applications\n * - Automatic backpressure handling for high-volume scenarios\n * - Simple file output without complex buffering configuration\n *\n * For more control over buffering behavior, consider using {@link getFileSink}\n * instead, which provides options for buffer size, flush intervals, and\n * non-blocking modes.\n *\n * ## Example\n *\n * ```typescript\n * import { configure } from \"@logtape/logtape\";\n * import { getStreamFileSink } from \"@logtape/file\";\n *\n * await configure({\n * sinks: {\n * file: getStreamFileSink(\"app.log\", {\n * highWaterMark: 32768 // 32KB buffer for high-volume logging\n * })\n * },\n * loggers: [\n * { category: [\"myapp\"], sinks: [\"file\"] }\n * ]\n * });\n * ```\n *\n * @param path The path to the file to write logs to. The file will be created\n * if it doesn't exist, or appended to if it does exist.\n * @param options Configuration options for the stream-based sink.\n * @returns A sink that writes formatted log records to the specified file.\n * The returned sink implements `Disposable` for proper resource cleanup.\n *\n * @since 1.0.0\n */\nexport function getStreamFileSink(\n path: string,\n options: StreamFileSinkOptions = {},\n): Sink & AsyncDisposable {\n const highWaterMark = options.highWaterMark ?? 16384;\n const formatter = options.formatter ?? defaultTextFormatter;\n\n // Create PassThrough stream for optimal performance\n const passThrough = new PassThrough({\n highWaterMark,\n objectMode: false,\n });\n\n // Create WriteStream immediately (not lazy)\n const writeStream = createWriteStream(path, { flags: \"a\" });\n\n // Pipe PassThrough to WriteStream for automatic backpressure handling\n passThrough.pipe(writeStream);\n\n let disposed = false;\n\n // Stream-based sink function for high performance\n const sink: Sink & AsyncDisposable = (record: LogRecord) => {\n if (disposed) return;\n\n // Direct write to PassThrough stream\n passThrough.write(formatter(record));\n };\n\n // Asynchronous disposal with sequential stream closure\n sink[Symbol.asyncDispose] = async () => {\n if (disposed) return;\n disposed = true;\n\n // Wait for PassThrough to drain if needed\n if (passThrough.writableNeedDrain) {\n await new Promise<void>((resolve) => {\n passThrough.once(\"drain\", resolve);\n });\n }\n\n // End the PassThrough stream first and wait for it to finish\n await new Promise<void>((resolve) => {\n passThrough.once(\"finish\", resolve);\n passThrough.end();\n });\n\n // Wait for WriteStream to finish and close (piped streams auto-close)\n await new Promise<void>((resolve) => {\n if (writeStream.closed || writeStream.destroyed) {\n resolve();\n return;\n }\n writeStream.once(\"close\", resolve);\n });\n };\n\n return sink;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiGA,SAAgB,kBACdA,MACAC,UAAiC,CAAE,GACX;CACxB,MAAM,gBAAgB,QAAQ,iBAAiB;CAC/C,MAAM,YAAY,QAAQ,aAAa;CAGvC,MAAM,cAAc,IAAI,YAAY;EAClC;EACA,YAAY;CACb;CAGD,MAAM,cAAc,kBAAkB,MAAM,EAAE,OAAO,IAAK,EAAC;AAG3D,aAAY,KAAK,YAAY;CAE7B,IAAI,WAAW;CAGf,MAAMC,OAA+B,CAACC,WAAsB;AAC1D,MAAI,SAAU;AAGd,cAAY,MAAM,UAAU,OAAO,CAAC;CACrC;AAGD,MAAK,OAAO,gBAAgB,YAAY;AACtC,MAAI,SAAU;AACd,aAAW;AAGX,MAAI,YAAY,kBACd,OAAM,IAAI,QAAc,CAAC,YAAY;AACnC,eAAY,KAAK,SAAS,QAAQ;EACnC;AAIH,QAAM,IAAI,QAAc,CAAC,YAAY;AACnC,eAAY,KAAK,UAAU,QAAQ;AACnC,eAAY,KAAK;EAClB;AAGD,QAAM,IAAI,QAAc,CAAC,YAAY;AACnC,OAAI,YAAY,UAAU,YAAY,WAAW;AAC/C,aAAS;AACT;GACD;AACD,eAAY,KAAK,SAAS,QAAQ;EACnC;CACF;AAED,QAAO;AACR"}
1
+ {"version":3,"file":"streamfilesink.js","names":["path: string","options: StreamFileSinkOptions","sink: Sink & AsyncDisposable","record: LogRecord"],"sources":["../src/streamfilesink.ts"],"sourcesContent":["import {\n defaultTextFormatter,\n type LogRecord,\n type Sink,\n type TextFormatter,\n} from \"@logtape/logtape\";\nimport { createWriteStream } from \"node:fs\";\nimport { PassThrough } from \"node:stream\";\n\n/**\n * Options for the {@link getStreamFileSink} function.\n *\n * This interface configures the high-performance stream-based file sink that\n * uses Node.js PassThrough streams for optimal I/O performance with automatic\n * backpressure management.\n *\n * @since 1.0.0\n */\nexport interface StreamFileSinkOptions {\n /**\n * High water mark for the PassThrough stream buffer in bytes.\n *\n * This controls the internal buffer size of the PassThrough stream.\n * Higher values can improve performance for high-volume logging but use\n * more memory. Lower values reduce memory usage but may impact performance.\n *\n * @default 16384\n * @since 1.0.0\n */\n readonly highWaterMark?: number;\n\n /**\n * A custom formatter for log records.\n *\n * If not specified, the default text formatter will be used, which formats\n * records in the standard LogTape format with timestamp, level, category,\n * and message.\n *\n * @default defaultTextFormatter\n * @since 1.0.0\n */\n readonly formatter?: TextFormatter;\n}\n\n/**\n * Create a high-performance stream-based file sink that writes log records to a file.\n *\n * This sink uses Node.js PassThrough streams piped to WriteStreams for optimal\n * I/O performance. It leverages the Node.js stream infrastructure to provide\n * automatic backpressure management, efficient buffering, and asynchronous writes\n * without blocking the main thread.\n *\n * ## Performance Characteristics\n *\n * - **High Performance**: Optimized for high-volume logging scenarios\n * - **Non-blocking**: Uses asynchronous I/O that doesn't block the main thread\n * - **Memory Efficient**: Automatic backpressure prevents memory buildup\n * - **Stream-based**: Leverages Node.js native stream optimizations\n *\n * ## When to Use\n *\n * Use this sink when you need:\n * - High-performance file logging for production applications\n * - Non-blocking I/O behavior for real-time applications\n * - Automatic backpressure handling for high-volume scenarios\n * - Simple file output without complex buffering configuration\n *\n * For more control over buffering behavior, consider using {@link getFileSink}\n * instead, which provides options for buffer size, flush intervals, and\n * non-blocking modes.\n *\n * ## Example\n *\n * ```typescript\n * import { configure } from \"@logtape/logtape\";\n * import { getStreamFileSink } from \"@logtape/file\";\n *\n * await configure({\n * sinks: {\n * file: getStreamFileSink(\"app.log\", {\n * highWaterMark: 32768 // 32KB buffer for high-volume logging\n * })\n * },\n * loggers: [\n * { category: [\"myapp\"], sinks: [\"file\"] }\n * ]\n * });\n * ```\n *\n * @param path The path to the file to write logs to. The file will be created\n * if it doesn't exist, or appended to if it does exist.\n * @param options Configuration options for the stream-based sink.\n * @returns A sink that writes formatted log records to the specified file.\n * The returned sink implements `AsyncDisposable` for proper resource cleanup\n * that waits for all data to be flushed to disk.\n *\n * @since 1.0.0\n */\nexport function getStreamFileSink(\n path: string,\n options: StreamFileSinkOptions = {},\n): Sink & AsyncDisposable {\n const highWaterMark = options.highWaterMark ?? 16384;\n const formatter = options.formatter ?? defaultTextFormatter;\n\n // Create PassThrough stream for optimal performance\n const passThrough = new PassThrough({\n highWaterMark,\n objectMode: false,\n });\n\n // Create WriteStream immediately (not lazy)\n const writeStream = createWriteStream(path, { flags: \"a\" });\n\n // Pipe PassThrough to WriteStream for automatic backpressure handling\n passThrough.pipe(writeStream);\n\n let disposed = false;\n\n // Stream-based sink function for high performance\n const sink: Sink & AsyncDisposable = (record: LogRecord) => {\n if (disposed) return;\n\n // Direct write to PassThrough stream\n passThrough.write(formatter(record));\n };\n\n // Asynchronous disposal with sequential stream closure\n sink[Symbol.asyncDispose] = async () => {\n if (disposed) return;\n disposed = true;\n\n // Wait for PassThrough to drain if needed\n if (passThrough.writableNeedDrain) {\n await new Promise<void>((resolve) => {\n passThrough.once(\"drain\", resolve);\n });\n }\n\n // End the PassThrough stream first and wait for it to finish\n await new Promise<void>((resolve) => {\n passThrough.once(\"finish\", resolve);\n passThrough.end();\n });\n\n // Wait for WriteStream to finish and close (piped streams auto-close)\n await new Promise<void>((resolve) => {\n if (writeStream.closed || writeStream.destroyed) {\n resolve();\n return;\n }\n writeStream.once(\"close\", resolve);\n });\n };\n\n return sink;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkGA,SAAgB,kBACdA,MACAC,UAAiC,CAAE,GACX;CACxB,MAAM,gBAAgB,QAAQ,iBAAiB;CAC/C,MAAM,YAAY,QAAQ,aAAa;CAGvC,MAAM,cAAc,IAAI,YAAY;EAClC;EACA,YAAY;CACb;CAGD,MAAM,cAAc,kBAAkB,MAAM,EAAE,OAAO,IAAK,EAAC;AAG3D,aAAY,KAAK,YAAY;CAE7B,IAAI,WAAW;CAGf,MAAMC,OAA+B,CAACC,WAAsB;AAC1D,MAAI,SAAU;AAGd,cAAY,MAAM,UAAU,OAAO,CAAC;CACrC;AAGD,MAAK,OAAO,gBAAgB,YAAY;AACtC,MAAI,SAAU;AACd,aAAW;AAGX,MAAI,YAAY,kBACd,OAAM,IAAI,QAAc,CAAC,YAAY;AACnC,eAAY,KAAK,SAAS,QAAQ;EACnC;AAIH,QAAM,IAAI,QAAc,CAAC,YAAY;AACnC,eAAY,KAAK,UAAU,QAAQ;AACnC,eAAY,KAAK;EAClB;AAGD,QAAM,IAAI,QAAc,CAAC,YAAY;AACnC,OAAI,YAAY,UAAU,YAAY,WAAW;AAC/C,aAAS;AACT;GACD;AACD,eAAY,KAAK,SAAS,QAAQ;EACnC;CACF;AAED,QAAO;AACR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logtape/file",
3
- "version": "1.2.0-dev.344+834f24a9",
3
+ "version": "1.2.0-dev.354+e11ec186",
4
4
  "description": "File sink and rotating file sink for LogTape",
5
5
  "keywords": [
6
6
  "logging",
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "sideEffects": false,
59
59
  "peerDependencies": {
60
- "@logtape/logtape": "^1.2.0-dev.344+834f24a9"
60
+ "@logtape/logtape": "^1.2.0-dev.354+e11ec186"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@alinea/suite": "^0.6.3",
@@ -138,8 +138,6 @@ test("getStreamFileSink() disposal stops writing", async () => {
138
138
  sink(info);
139
139
  sink(warning);
140
140
 
141
- await delay(50);
142
-
143
141
  const content = fs.readFileSync(path, { encoding: "utf-8" });
144
142
  const lines = content.split("\n").filter((line) => line.length > 0);
145
143
  assertEquals(lines.length, 1); // Only debug record
@@ -91,7 +91,8 @@ export interface StreamFileSinkOptions {
91
91
  * if it doesn't exist, or appended to if it does exist.
92
92
  * @param options Configuration options for the stream-based sink.
93
93
  * @returns A sink that writes formatted log records to the specified file.
94
- * The returned sink implements `Disposable` for proper resource cleanup.
94
+ * The returned sink implements `AsyncDisposable` for proper resource cleanup
95
+ * that waits for all data to be flushed to disk.
95
96
  *
96
97
  * @since 1.0.0
97
98
  */