@logtape/file 0.11.0-dev.175 → 0.12.0-dev.181

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 (77) hide show
  1. package/deno.json +37 -0
  2. package/dist/_virtual/rolldown_runtime.cjs +30 -0
  3. package/dist/filesink.base.cjs +81 -0
  4. package/dist/filesink.base.d.cts +98 -0
  5. package/dist/filesink.base.d.cts.map +1 -0
  6. package/dist/filesink.base.d.ts +98 -0
  7. package/dist/filesink.base.d.ts.map +1 -0
  8. package/dist/filesink.base.js +80 -0
  9. package/dist/filesink.base.js.map +1 -0
  10. package/dist/filesink.deno.cjs +67 -0
  11. package/dist/filesink.deno.d.cts +40 -0
  12. package/dist/filesink.deno.d.cts.map +1 -0
  13. package/dist/filesink.deno.d.ts +40 -0
  14. package/dist/filesink.deno.d.ts.map +1 -0
  15. package/dist/filesink.deno.js +66 -0
  16. package/dist/filesink.deno.js.map +1 -0
  17. package/dist/filesink.node.cjs +60 -0
  18. package/{esm/file/filesink.node.js → dist/filesink.node.d.cts} +12 -19
  19. package/dist/filesink.node.d.cts.map +1 -0
  20. package/{types/file → dist}/filesink.node.d.ts +11 -5
  21. package/dist/filesink.node.d.ts.map +1 -0
  22. package/dist/filesink.node.js +58 -0
  23. package/dist/filesink.node.js.map +1 -0
  24. package/dist/mod.cjs +15 -0
  25. package/dist/mod.d.cts +3 -0
  26. package/dist/mod.d.ts +3 -0
  27. package/dist/mod.js +3 -0
  28. package/filesink.base.ts +170 -0
  29. package/filesink.deno.ts +69 -0
  30. package/filesink.jsr.ts +52 -0
  31. package/filesink.node.ts +64 -0
  32. package/filesink.test.ts +224 -0
  33. package/mod.ts +7 -0
  34. package/package.json +37 -25
  35. package/tsdown.config.ts +22 -0
  36. package/esm/file/filesink.base.js +0 -85
  37. package/esm/file/mod.js +0 -1
  38. package/esm/package.json +0 -3
  39. package/script/file/filesink.base.js +0 -89
  40. package/script/file/filesink.node.js +0 -55
  41. package/script/file/mod.js +0 -6
  42. package/script/package.json +0 -3
  43. package/types/_dnt.test_shims.d.ts.map +0 -1
  44. package/types/deps/jsr.io/@david/which-runtime/0.2.1/mod.d.ts.map +0 -1
  45. package/types/deps/jsr.io/@std/assert/0.222.1/_constants.d.ts.map +0 -1
  46. package/types/deps/jsr.io/@std/assert/0.222.1/_diff.d.ts.map +0 -1
  47. package/types/deps/jsr.io/@std/assert/0.222.1/_format.d.ts.map +0 -1
  48. package/types/deps/jsr.io/@std/assert/0.222.1/assert_equals.d.ts.map +0 -1
  49. package/types/deps/jsr.io/@std/assert/0.222.1/assert_is_error.d.ts.map +0 -1
  50. package/types/deps/jsr.io/@std/assert/0.222.1/assert_throws.d.ts.map +0 -1
  51. package/types/deps/jsr.io/@std/assert/0.222.1/assertion_error.d.ts.map +0 -1
  52. package/types/deps/jsr.io/@std/assert/0.222.1/equal.d.ts.map +0 -1
  53. package/types/deps/jsr.io/@std/fmt/0.222.1/colors.d.ts.map +0 -1
  54. package/types/deps/jsr.io/@std/path/1.1.0/_common/assert_path.d.ts.map +0 -1
  55. package/types/deps/jsr.io/@std/path/1.1.0/_common/constants.d.ts.map +0 -1
  56. package/types/deps/jsr.io/@std/path/1.1.0/_common/from_file_url.d.ts.map +0 -1
  57. package/types/deps/jsr.io/@std/path/1.1.0/_common/normalize.d.ts.map +0 -1
  58. package/types/deps/jsr.io/@std/path/1.1.0/_common/normalize_string.d.ts.map +0 -1
  59. package/types/deps/jsr.io/@std/path/1.1.0/_os.d.ts.map +0 -1
  60. package/types/deps/jsr.io/@std/path/1.1.0/join.d.ts.map +0 -1
  61. package/types/deps/jsr.io/@std/path/1.1.0/posix/_util.d.ts.map +0 -1
  62. package/types/deps/jsr.io/@std/path/1.1.0/posix/from_file_url.d.ts.map +0 -1
  63. package/types/deps/jsr.io/@std/path/1.1.0/posix/join.d.ts.map +0 -1
  64. package/types/deps/jsr.io/@std/path/1.1.0/posix/normalize.d.ts.map +0 -1
  65. package/types/deps/jsr.io/@std/path/1.1.0/windows/_util.d.ts.map +0 -1
  66. package/types/deps/jsr.io/@std/path/1.1.0/windows/from_file_url.d.ts.map +0 -1
  67. package/types/deps/jsr.io/@std/path/1.1.0/windows/join.d.ts.map +0 -1
  68. package/types/deps/jsr.io/@std/path/1.1.0/windows/normalize.d.ts.map +0 -1
  69. package/types/file/filesink.base.d.ts +0 -94
  70. package/types/file/filesink.base.d.ts.map +0 -1
  71. package/types/file/filesink.node.d.ts.map +0 -1
  72. package/types/file/filesink.test.d.ts.map +0 -1
  73. package/types/file/mod.d.ts +0 -3
  74. package/types/file/mod.d.ts.map +0 -1
  75. package/types/logtape/fixtures.d.ts.map +0 -1
  76. package/types/logtape/level.d.ts.map +0 -1
  77. package/types/logtape/record.d.ts.map +0 -1
@@ -0,0 +1,60 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ const require_filesink_base = require('./filesink.base.cjs');
3
+ const node_fs = require_rolldown_runtime.__toESM(require("node:fs"));
4
+
5
+ //#region filesink.node.ts
6
+ /**
7
+ * A Node.js-specific file sink driver.
8
+ */
9
+ const nodeDriver = {
10
+ openSync(path) {
11
+ return node_fs.default.openSync(path, "a");
12
+ },
13
+ writeSync: node_fs.default.writeSync,
14
+ flushSync: node_fs.default.fsyncSync,
15
+ closeSync: node_fs.default.closeSync,
16
+ statSync: node_fs.default.statSync,
17
+ renameSync: node_fs.default.renameSync
18
+ };
19
+ /**
20
+ * Get a file sink.
21
+ *
22
+ * Note that this function is unavailable in the browser.
23
+ *
24
+ * @param path A path to the file to write to.
25
+ * @param options The options for the sink.
26
+ * @returns A sink that writes to the file. The sink is also a disposable
27
+ * object that closes the file when disposed.
28
+ */
29
+ function getFileSink(path, options = {}) {
30
+ return require_filesink_base.getBaseFileSink(path, {
31
+ ...options,
32
+ ...nodeDriver
33
+ });
34
+ }
35
+ /**
36
+ * Get a rotating file sink.
37
+ *
38
+ * This sink writes log records to a file, and rotates the file when it reaches
39
+ * the `maxSize`. The rotated files are named with the original file name
40
+ * followed by a dot and a number, starting from 1. The number is incremented
41
+ * for each rotation, and the maximum number of files to keep is `maxFiles`.
42
+ *
43
+ * Note that this function is unavailable in the browser.
44
+ *
45
+ * @param path A path to the file to write to.
46
+ * @param options The options for the sink and the file driver.
47
+ * @returns A sink that writes to the file. The sink is also a disposable
48
+ * object that closes the file when disposed.
49
+ */
50
+ function getRotatingFileSink(path, options = {}) {
51
+ return require_filesink_base.getBaseRotatingFileSink(path, {
52
+ ...options,
53
+ ...nodeDriver
54
+ });
55
+ }
56
+
57
+ //#endregion
58
+ exports.getFileSink = getFileSink;
59
+ exports.getRotatingFileSink = getRotatingFileSink;
60
+ exports.nodeDriver = nodeDriver;
@@ -1,18 +1,12 @@
1
- import fs from "node:fs";
2
- import { getBaseFileSink, getBaseRotatingFileSink, } from "./filesink.base.js";
1
+ import { FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions } from "./filesink.base.cjs";
2
+ import { Sink } from "@logtape/logtape";
3
+
4
+ //#region filesink.node.d.ts
5
+
3
6
  /**
4
7
  * A Node.js-specific file sink driver.
5
8
  */
6
- export const nodeDriver = {
7
- openSync(path) {
8
- return fs.openSync(path, "a");
9
- },
10
- writeSync: fs.writeSync,
11
- flushSync: fs.fsyncSync,
12
- closeSync: fs.closeSync,
13
- statSync: fs.statSync,
14
- renameSync: fs.renameSync,
15
- };
9
+ declare const nodeDriver: RotatingFileSinkDriver<number | void>;
16
10
  /**
17
11
  * Get a file sink.
18
12
  *
@@ -23,9 +17,7 @@ export const nodeDriver = {
23
17
  * @returns A sink that writes to the file. The sink is also a disposable
24
18
  * object that closes the file when disposed.
25
19
  */
26
- export function getFileSink(path, options = {}) {
27
- return getBaseFileSink(path, { ...options, ...nodeDriver });
28
- }
20
+ declare function getFileSink(path: string, options?: FileSinkOptions): Sink & Disposable;
29
21
  /**
30
22
  * Get a rotating file sink.
31
23
  *
@@ -41,7 +33,8 @@ export function getFileSink(path, options = {}) {
41
33
  * @returns A sink that writes to the file. The sink is also a disposable
42
34
  * object that closes the file when disposed.
43
35
  */
44
- export function getRotatingFileSink(path, options = {}) {
45
- return getBaseRotatingFileSink(path, { ...options, ...nodeDriver });
46
- }
47
- // cSpell: ignore filesink
36
+ declare function getRotatingFileSink(path: string, options?: RotatingFileSinkOptions): Sink & Disposable;
37
+ //# sourceMappingURL=filesink.node.d.ts.map
38
+ //#endregion
39
+ export { getFileSink, getRotatingFileSink, nodeDriver };
40
+ //# sourceMappingURL=filesink.node.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesink.node.d.cts","names":[],"sources":["../filesink.node.ts"],"sourcesContent":[],"mappings":";;;;;;;AAaA;AAqBgB,cArBH,UAqBc,EArBF,sBAqBE,CAAA,MAAA,GAAA,IAAA,CAAA;;;;;AAGP;AAmBpB;;;;;AAGoB,iBAzBJ,WAAA,CAyBI,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAvBT,eAuBS,CAAA,EAtBjB,IAsBiB,GAtBV,UAsBU;;;;;;;;;;;;;;;;iBAHJ,mBAAA,yBAEL,0BACR,OAAO"}
@@ -1,9 +1,12 @@
1
- import type { Sink } from "@logtape/logtape";
2
- import { type FileSinkOptions, type RotatingFileSinkDriver, type RotatingFileSinkOptions } from "./filesink.base.js";
1
+ import { FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions } from "./filesink.base.js";
2
+ import { Sink } from "@logtape/logtape";
3
+
4
+ //#region filesink.node.d.ts
5
+
3
6
  /**
4
7
  * A Node.js-specific file sink driver.
5
8
  */
6
- export declare const nodeDriver: RotatingFileSinkDriver<number | void>;
9
+ declare const nodeDriver: RotatingFileSinkDriver<number | void>;
7
10
  /**
8
11
  * Get a file sink.
9
12
  *
@@ -14,7 +17,7 @@ export declare const nodeDriver: RotatingFileSinkDriver<number | void>;
14
17
  * @returns A sink that writes to the file. The sink is also a disposable
15
18
  * object that closes the file when disposed.
16
19
  */
17
- export declare function getFileSink(path: string, options?: FileSinkOptions): Sink & Disposable;
20
+ declare function getFileSink(path: string, options?: FileSinkOptions): Sink & Disposable;
18
21
  /**
19
22
  * Get a rotating file sink.
20
23
  *
@@ -30,5 +33,8 @@ export declare function getFileSink(path: string, options?: FileSinkOptions): Si
30
33
  * @returns A sink that writes to the file. The sink is also a disposable
31
34
  * object that closes the file when disposed.
32
35
  */
33
- export declare function getRotatingFileSink(path: string, options?: RotatingFileSinkOptions): Sink & Disposable;
36
+ declare function getRotatingFileSink(path: string, options?: RotatingFileSinkOptions): Sink & Disposable;
37
+ //# sourceMappingURL=filesink.node.d.ts.map
38
+ //#endregion
39
+ export { getFileSink, getRotatingFileSink, nodeDriver };
34
40
  //# sourceMappingURL=filesink.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesink.node.d.ts","names":[],"sources":["../filesink.node.ts"],"sourcesContent":[],"mappings":";;;;;;;AAaA;AAqBgB,cArBH,UAqBc,EArBF,sBAqBE,CAAA,MAAA,GAAA,IAAA,CAAA;;;;;AAGP;AAmBpB;;;;;AAGoB,iBAzBJ,WAAA,CAyBI,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAvBT,eAuBS,CAAA,EAtBjB,IAsBiB,GAtBV,UAsBU;;;;;;;;;;;;;;;;iBAHJ,mBAAA,yBAEL,0BACR,OAAO"}
@@ -0,0 +1,58 @@
1
+ import { getBaseFileSink, getBaseRotatingFileSink } from "./filesink.base.js";
2
+ import fs from "node:fs";
3
+
4
+ //#region filesink.node.ts
5
+ /**
6
+ * A Node.js-specific file sink driver.
7
+ */
8
+ const nodeDriver = {
9
+ openSync(path) {
10
+ return fs.openSync(path, "a");
11
+ },
12
+ writeSync: fs.writeSync,
13
+ flushSync: fs.fsyncSync,
14
+ closeSync: fs.closeSync,
15
+ statSync: fs.statSync,
16
+ renameSync: fs.renameSync
17
+ };
18
+ /**
19
+ * Get a file sink.
20
+ *
21
+ * Note that this function is unavailable in the browser.
22
+ *
23
+ * @param path A path to the file to write to.
24
+ * @param options The options for the sink.
25
+ * @returns A sink that writes to the file. The sink is also a disposable
26
+ * object that closes the file when disposed.
27
+ */
28
+ function getFileSink(path, options = {}) {
29
+ return getBaseFileSink(path, {
30
+ ...options,
31
+ ...nodeDriver
32
+ });
33
+ }
34
+ /**
35
+ * Get a rotating file sink.
36
+ *
37
+ * This sink writes log records to a file, and rotates the file when it reaches
38
+ * the `maxSize`. The rotated files are named with the original file name
39
+ * followed by a dot and a number, starting from 1. The number is incremented
40
+ * for each rotation, and the maximum number of files to keep is `maxFiles`.
41
+ *
42
+ * Note that this function is unavailable in the browser.
43
+ *
44
+ * @param path A path to the file to write to.
45
+ * @param options The options for the sink and the file driver.
46
+ * @returns A sink that writes to the file. The sink is also a disposable
47
+ * object that closes the file when disposed.
48
+ */
49
+ function getRotatingFileSink(path, options = {}) {
50
+ return getBaseRotatingFileSink(path, {
51
+ ...options,
52
+ ...nodeDriver
53
+ });
54
+ }
55
+
56
+ //#endregion
57
+ export { getFileSink, getRotatingFileSink, nodeDriver };
58
+ //# sourceMappingURL=filesink.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesink.node.js","names":["nodeDriver: RotatingFileSinkDriver<number | void>","path: string","options: FileSinkOptions","options: RotatingFileSinkOptions"],"sources":["../filesink.node.ts"],"sourcesContent":["import type { Sink } from \"@logtape/logtape\";\nimport fs from \"node:fs\";\nimport {\n type FileSinkOptions,\n getBaseFileSink,\n getBaseRotatingFileSink,\n type RotatingFileSinkDriver,\n type RotatingFileSinkOptions,\n} from \"./filesink.base.ts\";\n\n/**\n * A Node.js-specific file sink driver.\n */\nexport const nodeDriver: RotatingFileSinkDriver<number | void> = {\n openSync(path: string) {\n return fs.openSync(path, \"a\");\n },\n writeSync: fs.writeSync,\n flushSync: fs.fsyncSync,\n closeSync: fs.closeSync,\n statSync: fs.statSync,\n renameSync: fs.renameSync,\n};\n\n/**\n * Get a file sink.\n *\n * Note that this function is unavailable in the browser.\n *\n * @param path A path to the file to write to.\n * @param options The options for the sink.\n * @returns A sink that writes to the file. The sink is also a disposable\n * object that closes the file when disposed.\n */\nexport function getFileSink(\n path: string,\n options: FileSinkOptions = {},\n): Sink & Disposable {\n return getBaseFileSink(path, { ...options, ...nodeDriver });\n}\n\n/**\n * Get a rotating file sink.\n *\n * This sink writes log records to a file, and rotates the file when it reaches\n * the `maxSize`. The rotated files are named with the original file name\n * followed by a dot and a number, starting from 1. The number is incremented\n * for each rotation, and the maximum number of files to keep is `maxFiles`.\n *\n * Note that this function is unavailable in the browser.\n *\n * @param path A path to the file to write to.\n * @param options The options for the sink and the file driver.\n * @returns A sink that writes to the file. The sink is also a disposable\n * object that closes the file when disposed.\n */\nexport function getRotatingFileSink(\n path: string,\n options: RotatingFileSinkOptions = {},\n): Sink & Disposable {\n return getBaseRotatingFileSink(path, { ...options, ...nodeDriver });\n}\n\n// cSpell: ignore filesink\n"],"mappings":";;;;;;;AAaA,MAAaA,aAAoD;CAC/D,SAASC,MAAc;AACrB,SAAO,GAAG,SAAS,MAAM,IAAI;CAC9B;CACD,WAAW,GAAG;CACd,WAAW,GAAG;CACd,WAAW,GAAG;CACd,UAAU,GAAG;CACb,YAAY,GAAG;AAChB;;;;;;;;;;;AAYD,SAAgB,YACdA,MACAC,UAA2B,CAAE,GACV;AACnB,QAAO,gBAAgB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAY,EAAC;AAC5D;;;;;;;;;;;;;;;;AAiBD,SAAgB,oBACdD,MACAE,UAAmC,CAAE,GAClB;AACnB,QAAO,wBAAwB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAY,EAAC;AACpE"}
package/dist/mod.cjs ADDED
@@ -0,0 +1,15 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ const __filesink = require_rolldown_runtime.__toESM(require("#filesink"));
3
+
4
+ Object.defineProperty(exports, 'getFileSink', {
5
+ enumerable: true,
6
+ get: function () {
7
+ return __filesink.getFileSink;
8
+ }
9
+ });
10
+ Object.defineProperty(exports, 'getRotatingFileSink', {
11
+ enumerable: true,
12
+ get: function () {
13
+ return __filesink.getRotatingFileSink;
14
+ }
15
+ });
package/dist/mod.d.cts ADDED
@@ -0,0 +1,3 @@
1
+ import { FileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions } from "./filesink.base.cjs";
2
+ import { getFileSink, getRotatingFileSink } from "#filesink";
3
+ export { FileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions, getFileSink, getRotatingFileSink };
package/dist/mod.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { FileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions } from "./filesink.base.js";
2
+ import { getFileSink, getRotatingFileSink } from "#filesink";
3
+ export { FileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions, getFileSink, getRotatingFileSink };
package/dist/mod.js ADDED
@@ -0,0 +1,3 @@
1
+ import { getFileSink, getRotatingFileSink } from "#filesink";
2
+
3
+ export { getFileSink, getRotatingFileSink };
@@ -0,0 +1,170 @@
1
+ import {
2
+ defaultTextFormatter,
3
+ type LogRecord,
4
+ type Sink,
5
+ type StreamSinkOptions,
6
+ } from "@logtape/logtape";
7
+
8
+ /**
9
+ * Options for the {@link getBaseFileSink} function.
10
+ */
11
+ export type FileSinkOptions = StreamSinkOptions & {
12
+ /**
13
+ * If `true`, the file is not opened until the first write. Defaults to `false`.
14
+ */
15
+ lazy?: boolean;
16
+ };
17
+
18
+ /**
19
+ * A platform-specific file sink driver.
20
+ * @typeParam TFile The type of the file descriptor.
21
+ */
22
+ export interface FileSinkDriver<TFile> {
23
+ /**
24
+ * Open a file for appending and return a file descriptor.
25
+ * @param path A path to the file to open.
26
+ */
27
+ openSync(path: string): TFile;
28
+
29
+ /**
30
+ * Write a chunk of data to the file.
31
+ * @param fd The file descriptor.
32
+ * @param chunk The data to write.
33
+ */
34
+ writeSync(fd: TFile, chunk: Uint8Array): void;
35
+
36
+ /**
37
+ * Flush the file to ensure that all data is written to the disk.
38
+ * @param fd The file descriptor.
39
+ */
40
+ flushSync(fd: TFile): void;
41
+
42
+ /**
43
+ * Close the file.
44
+ * @param fd The file descriptor.
45
+ */
46
+ closeSync(fd: TFile): void;
47
+ }
48
+
49
+ /**
50
+ * Get a platform-independent file sink.
51
+ *
52
+ * @typeParam TFile The type of the file descriptor.
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
+ */
58
+ export function getBaseFileSink<TFile>(
59
+ path: string,
60
+ options: FileSinkOptions & FileSinkDriver<TFile>,
61
+ ): Sink & Disposable {
62
+ const formatter = options.formatter ?? defaultTextFormatter;
63
+ const encoder = options.encoder ?? new TextEncoder();
64
+ let fd = options.lazy ? null : options.openSync(path);
65
+ const sink: Sink & Disposable = (record: LogRecord) => {
66
+ if (fd === null) {
67
+ fd = options.openSync(path);
68
+ }
69
+ options.writeSync(fd, encoder.encode(formatter(record)));
70
+ options.flushSync(fd);
71
+ };
72
+ sink[Symbol.dispose] = () => {
73
+ if (fd !== null) {
74
+ options.closeSync(fd);
75
+ }
76
+ };
77
+ return sink;
78
+ }
79
+
80
+ /**
81
+ * Options for the {@link getBaseRotatingFileSink} function.
82
+ */
83
+ export interface RotatingFileSinkOptions extends Omit<FileSinkOptions, "lazy"> {
84
+ /**
85
+ * The maximum bytes of the file before it is rotated. 1 MiB by default.
86
+ */
87
+ maxSize?: number;
88
+
89
+ /**
90
+ * The maximum number of files to keep. 5 by default.
91
+ */
92
+ maxFiles?: number;
93
+ }
94
+
95
+ /**
96
+ * A platform-specific rotating file sink driver.
97
+ */
98
+ export interface RotatingFileSinkDriver<TFile> extends FileSinkDriver<TFile> {
99
+ /**
100
+ * Get the size of the file.
101
+ * @param path A path to the file.
102
+ * @returns The `size` of the file in bytes, in an object.
103
+ */
104
+ statSync(path: string): { size: number };
105
+
106
+ /**
107
+ * Rename a file.
108
+ * @param oldPath A path to the file to rename.
109
+ * @param newPath A path to be renamed to.
110
+ */
111
+ renameSync(oldPath: string, newPath: string): void;
112
+ }
113
+
114
+ /**
115
+ * Get a platform-independent rotating file sink.
116
+ *
117
+ * This sink writes log records to a file, and rotates the file when it reaches
118
+ * the `maxSize`. The rotated files are named with the original file name
119
+ * followed by a dot and a number, starting from 1. The number is incremented
120
+ * for each rotation, and the maximum number of files to keep is `maxFiles`.
121
+ *
122
+ * @param path A path to the file to write to.
123
+ * @param options The options for the sink and the file driver.
124
+ * @returns A sink that writes to the file. The sink is also a disposable
125
+ * object that closes the file when disposed.
126
+ */
127
+ export function getBaseRotatingFileSink<TFile>(
128
+ path: string,
129
+ options: RotatingFileSinkOptions & RotatingFileSinkDriver<TFile>,
130
+ ): Sink & Disposable {
131
+ const formatter = options.formatter ?? defaultTextFormatter;
132
+ const encoder = options.encoder ?? new TextEncoder();
133
+ const maxSize = options.maxSize ?? 1024 * 1024;
134
+ const maxFiles = options.maxFiles ?? 5;
135
+ let offset: number = 0;
136
+ try {
137
+ const stat = options.statSync(path);
138
+ offset = stat.size;
139
+ } catch {
140
+ // Continue as the offset is already 0.
141
+ }
142
+ let fd = options.openSync(path);
143
+ function shouldRollover(bytes: Uint8Array): boolean {
144
+ return offset + bytes.length > maxSize;
145
+ }
146
+ function performRollover(): void {
147
+ options.closeSync(fd);
148
+ for (let i = maxFiles - 1; i > 0; i--) {
149
+ const oldPath = `${path}.${i}`;
150
+ const newPath = `${path}.${i + 1}`;
151
+ try {
152
+ options.renameSync(oldPath, newPath);
153
+ } catch (_) {
154
+ // Continue if the file does not exist.
155
+ }
156
+ }
157
+ options.renameSync(path, `${path}.1`);
158
+ offset = 0;
159
+ fd = options.openSync(path);
160
+ }
161
+ const sink: Sink & Disposable = (record: LogRecord) => {
162
+ const bytes = encoder.encode(formatter(record));
163
+ if (shouldRollover(bytes)) performRollover();
164
+ options.writeSync(fd, bytes);
165
+ options.flushSync(fd);
166
+ offset += bytes.length;
167
+ };
168
+ sink[Symbol.dispose] = () => options.closeSync(fd);
169
+ return sink;
170
+ }
@@ -0,0 +1,69 @@
1
+ import type { Sink } from "@logtape/logtape";
2
+ import {
3
+ type FileSinkOptions,
4
+ getBaseFileSink,
5
+ getBaseRotatingFileSink,
6
+ type RotatingFileSinkDriver,
7
+ type RotatingFileSinkOptions,
8
+ } from "./filesink.base.ts";
9
+
10
+ /**
11
+ * A Deno-specific file sink driver.
12
+ */
13
+ export const denoDriver: RotatingFileSinkDriver<Deno.FsFile> = {
14
+ openSync(path: string) {
15
+ return Deno.openSync(path, { create: true, append: true });
16
+ },
17
+ writeSync(fd, chunk) {
18
+ fd.writeSync(chunk);
19
+ },
20
+ flushSync(fd) {
21
+ fd.syncSync();
22
+ },
23
+ closeSync(fd) {
24
+ fd.close();
25
+ },
26
+ statSync: globalThis?.Deno.statSync,
27
+ renameSync: globalThis?.Deno.renameSync,
28
+ };
29
+
30
+ /**
31
+ * Get a file sink.
32
+ *
33
+ * Note that this function is unavailable in the browser.
34
+ *
35
+ * @param path A path to the file to write to.
36
+ * @param options The options for the sink.
37
+ * @returns A sink that writes to the file. The sink is also a disposable
38
+ * object that closes the file when disposed.
39
+ */
40
+ export function getFileSink(
41
+ path: string,
42
+ options: FileSinkOptions = {},
43
+ ): Sink & Disposable {
44
+ return getBaseFileSink(path, { ...options, ...denoDriver });
45
+ }
46
+
47
+ /**
48
+ * Get a rotating file sink.
49
+ *
50
+ * This sink writes log records to a file, and rotates the file when it reaches
51
+ * the `maxSize`. The rotated files are named with the original file name
52
+ * followed by a dot and a number, starting from 1. The number is incremented
53
+ * for each rotation, and the maximum number of files to keep is `maxFiles`.
54
+ *
55
+ * Note that this function is unavailable in the browser.
56
+ *
57
+ * @param path A path to the file to write to.
58
+ * @param options The options for the sink and the file driver.
59
+ * @returns A sink that writes to the file. The sink is also a disposable
60
+ * object that closes the file when disposed.
61
+ */
62
+ export function getRotatingFileSink(
63
+ path: string,
64
+ options: RotatingFileSinkOptions = {},
65
+ ): Sink & Disposable {
66
+ return getBaseRotatingFileSink(path, { ...options, ...denoDriver });
67
+ }
68
+
69
+ // cSpell: ignore filesink
@@ -0,0 +1,52 @@
1
+ import type { Sink } from "@logtape/logtape";
2
+ import type {
3
+ FileSinkOptions,
4
+ RotatingFileSinkOptions,
5
+ } from "./filesink.base.ts";
6
+
7
+ const filesink: Omit<typeof import("./filesink.deno.ts"), "denoDriver"> =
8
+ // dnt-shim-ignore
9
+ await ("Deno" in globalThis
10
+ ? import("./filesink.deno.ts")
11
+ : import("./filesink.node.ts"));
12
+
13
+ /**
14
+ * Get a file sink.
15
+ *
16
+ * Note that this function is unavailable in the browser.
17
+ *
18
+ * @param path A path to the file to write to.
19
+ * @param options The options for the sink.
20
+ * @returns A sink that writes to the file. The sink is also a disposable
21
+ * object that closes the file when disposed.
22
+ */
23
+ export function getFileSink(
24
+ path: string,
25
+ options: FileSinkOptions = {},
26
+ ): Sink & Disposable {
27
+ return filesink.getFileSink(path, options);
28
+ }
29
+
30
+ /**
31
+ * Get a rotating file sink.
32
+ *
33
+ * This sink writes log records to a file, and rotates the file when it reaches
34
+ * the `maxSize`. The rotated files are named with the original file name
35
+ * followed by a dot and a number, starting from 1. The number is incremented
36
+ * for each rotation, and the maximum number of files to keep is `maxFiles`.
37
+ *
38
+ * Note that this function is unavailable in the browser.
39
+ *
40
+ * @param path A path to the file to write to.
41
+ * @param options The options for the sink and the file driver.
42
+ * @returns A sink that writes to the file. The sink is also a disposable
43
+ * object that closes the file when disposed.
44
+ */
45
+ export function getRotatingFileSink(
46
+ path: string,
47
+ options: RotatingFileSinkOptions = {},
48
+ ): Sink & Disposable {
49
+ return filesink.getRotatingFileSink(path, options);
50
+ }
51
+
52
+ // cSpell: ignore filesink
@@ -0,0 +1,64 @@
1
+ import type { Sink } from "@logtape/logtape";
2
+ import fs from "node:fs";
3
+ import {
4
+ type FileSinkOptions,
5
+ getBaseFileSink,
6
+ getBaseRotatingFileSink,
7
+ type RotatingFileSinkDriver,
8
+ type RotatingFileSinkOptions,
9
+ } from "./filesink.base.ts";
10
+
11
+ /**
12
+ * A Node.js-specific file sink driver.
13
+ */
14
+ export const nodeDriver: RotatingFileSinkDriver<number | void> = {
15
+ openSync(path: string) {
16
+ return fs.openSync(path, "a");
17
+ },
18
+ writeSync: fs.writeSync,
19
+ flushSync: fs.fsyncSync,
20
+ closeSync: fs.closeSync,
21
+ statSync: fs.statSync,
22
+ renameSync: fs.renameSync,
23
+ };
24
+
25
+ /**
26
+ * Get a file sink.
27
+ *
28
+ * Note that this function is unavailable in the browser.
29
+ *
30
+ * @param path A path to the file to write to.
31
+ * @param options The options for the sink.
32
+ * @returns A sink that writes to the file. The sink is also a disposable
33
+ * object that closes the file when disposed.
34
+ */
35
+ export function getFileSink(
36
+ path: string,
37
+ options: FileSinkOptions = {},
38
+ ): Sink & Disposable {
39
+ return getBaseFileSink(path, { ...options, ...nodeDriver });
40
+ }
41
+
42
+ /**
43
+ * Get a rotating file sink.
44
+ *
45
+ * This sink writes log records to a file, and rotates the file when it reaches
46
+ * the `maxSize`. The rotated files are named with the original file name
47
+ * followed by a dot and a number, starting from 1. The number is incremented
48
+ * for each rotation, and the maximum number of files to keep is `maxFiles`.
49
+ *
50
+ * Note that this function is unavailable in the browser.
51
+ *
52
+ * @param path A path to the file to write to.
53
+ * @param options The options for the sink and the file driver.
54
+ * @returns A sink that writes to the file. The sink is also a disposable
55
+ * object that closes the file when disposed.
56
+ */
57
+ export function getRotatingFileSink(
58
+ path: string,
59
+ options: RotatingFileSinkOptions = {},
60
+ ): Sink & Disposable {
61
+ return getBaseRotatingFileSink(path, { ...options, ...nodeDriver });
62
+ }
63
+
64
+ // cSpell: ignore filesink