@logtape/file 2.2.2 → 2.3.0-dev.783

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.
@@ -54,6 +54,7 @@ const denoTimeDriver = {
54
54
  readdirSync(path) {
55
55
  return [...Deno.readDirSync(path)].map((entry) => entry.name);
56
56
  },
57
+ statSync: globalThis?.Deno.statSync,
57
58
  unlinkSync: globalThis?.Deno.removeSync,
58
59
  mkdirSync(path, options) {
59
60
  Deno.mkdirSync(path, options);
@@ -69,6 +70,7 @@ const denoAsyncTimeDriver = {
69
70
  readdirSync(path) {
70
71
  return [...Deno.readDirSync(path)].map((entry) => entry.name);
71
72
  },
73
+ statSync: globalThis?.Deno.statSync,
72
74
  unlinkSync: globalThis?.Deno.removeSync,
73
75
  mkdirSync(path, options) {
74
76
  Deno.mkdirSync(path, options);
@@ -96,23 +98,13 @@ function getRotatingFileSink(path, options = {}) {
96
98
  });
97
99
  }
98
100
  function getTimeRotatingFileSink(options) {
99
- if (options.nonBlocking) {
100
- const driver$1 = {
101
- ...denoAsyncTimeDriver,
102
- statSync: globalThis?.Deno.statSync
103
- };
104
- return require_timefilesink.getBaseTimeRotatingFileSink({
105
- ...options,
106
- ...driver$1
107
- });
108
- }
109
- const driver = {
110
- ...denoTimeDriver,
111
- statSync: globalThis?.Deno.statSync
112
- };
101
+ if (options.nonBlocking) return require_timefilesink.getBaseTimeRotatingFileSink({
102
+ ...options,
103
+ ...denoAsyncTimeDriver
104
+ });
113
105
  return require_timefilesink.getBaseTimeRotatingFileSink({
114
106
  ...options,
115
- ...driver
107
+ ...denoTimeDriver
116
108
  });
117
109
  }
118
110
 
@@ -1 +1 @@
1
- {"version":3,"file":"filesink.deno.d.cts","names":[],"sources":["../src/filesink.deno.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAoBA;AAuBC,cAvBY,UAuBZ,EAvBwB,sBAuBxB,CAvB+C,IAAA,CAAK,MAuBpD,CAAA;;;AAvB8C;AA6B/C;AAeC,cAfY,eAeZ,EAf6B,2BAe7B,CAfyD,IAAA,CAAK,MAe9D,CAAA;;;AAfwD;AAqBzD;AAUC,cAVY,cAUZ,EAV4B,0BAU5B,CAVuD,IAAA,CAAK,MAU5D,CAAA;;;AAVsD;AAgBvD;AAWG,cAXU,mBAWV,EAX+B,+BAW/B,CAX+D,IAAA,CAAK,MAWpE,CAAA;;;AAX8D;AAwBjE;;;;;AAGoB;AACpB;;AAEW,iBANK,WAAA,CAML,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAJC,eAID,CAAA,EAHR,IAGQ,GAHD,UAGC;AACR,iBAHa,WAAA,CAGb,IAAA,EAAA,MAAA,EAAA,OAAA,EADQ,eACR,GAAA;EAAI,WAAG,EAAA,IAAA;AAAe,CAAA,CAAA,EAAtB,IAAsB,GAAf,eAAe;AA2BzB;;;;;AAGoB;AACpB;;;;;AAGyB;AA0BzB;;;;AAEU,iBAnCM,mBAAA,CAmCN,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAjCE,uBAiCF,CAAA,EAhCP,IAgCO,GAhCA,UAgCA;AAAU,iBA/BJ,mBAAA,CA+BI,IAAA,EAAA,MAAA,EAAA,OAAA,EA7BT,uBA6BS,GAAA;EACJ,WAAA,EAAA,IAAA;CAAuB,CAAA,EA7BpC,IA6BoC,GA7B7B,eA6B6B;;;;AAEd;;;;;;;;;;;;iBALT,uBAAA,UACL,8BACR,OAAO;iBACM,uBAAA,UACL;;IACR,OAAO"}
1
+ {"version":3,"file":"filesink.deno.d.cts","names":[],"sources":["../src/filesink.deno.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAoBA;AAuBC,cAvBY,UAuBZ,EAvBwB,sBAuBxB,CAvB+C,IAAA,CAAK,MAuBpD,CAAA;;;AAvB8C;AA6B/C;AAeC,cAfY,eAeZ,EAf6B,2BAe7B,CAfyD,IAAA,CAAK,MAe9D,CAAA;;;AAfwD;AAqBzD;AAWC,cAXY,cAWZ,EAX4B,0BAW5B,CAXuD,IAAA,CAAK,MAW5D,CAAA;;;AAXsD;AAiBvD;AAYG,cAZU,mBAYV,EAZ+B,+BAY/B,CAZ+D,IAAA,CAAK,MAYpE,CAAA;;;AAZ8D;AAyBjE;;;;;AAGoB;AACpB;;AAEW,iBANK,WAAA,CAML,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAJC,eAID,CAAA,EAHR,IAGQ,GAHD,UAGC;AACR,iBAHa,WAAA,CAGb,IAAA,EAAA,MAAA,EAAA,OAAA,EADQ,eACR,GAAA;EAAI,WAAG,EAAA,IAAA;AAAe,CAAA,CAAA,EAAtB,IAAsB,GAAf,eAAe;AA2BzB;;;;;AAGoB;AACpB;;;;;AAGyB;AA0BzB;;;;AAEU,iBAnCM,mBAAA,CAmCN,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAjCE,uBAiCF,CAAA,EAhCP,IAgCO,GAhCA,UAgCA;AAAU,iBA/BJ,mBAAA,CA+BI,IAAA,EAAA,MAAA,EAAA,OAAA,EA7BT,uBA6BS,GAAA;EACJ,WAAA,EAAA,IAAA;CAAuB,CAAA,EA7BpC,IA6BoC,GA7B7B,eA6B6B;;;;AAEd;;;;;;;;;;;;iBALT,uBAAA,UACL,8BACR,OAAO;iBACM,uBAAA,UACL;;IACR,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"filesink.deno.d.ts","names":[],"sources":["../src/filesink.deno.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAoBA;AAuBC,cAvBY,UAuBZ,EAvBwB,sBAuBxB,CAvB+C,IAAA,CAAK,MAuBpD,CAAA;;;AAvB8C;AA6B/C;AAeC,cAfY,eAeZ,EAf6B,2BAe7B,CAfyD,IAAA,CAAK,MAe9D,CAAA;;;AAfwD;AAqBzD;AAUC,cAVY,cAUZ,EAV4B,0BAU5B,CAVuD,IAAA,CAAK,MAU5D,CAAA;;;AAVsD;AAgBvD;AAWG,cAXU,mBAWV,EAX+B,+BAW/B,CAX+D,IAAA,CAAK,MAWpE,CAAA;;;AAX8D;AAwBjE;;;;;AAGoB;AACpB;;AAEW,iBANK,WAAA,CAML,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAJC,eAID,CAAA,EAHR,IAGQ,GAHD,UAGC;AACR,iBAHa,WAAA,CAGb,IAAA,EAAA,MAAA,EAAA,OAAA,EADQ,eACR,GAAA;EAAI,WAAG,EAAA,IAAA;AAAe,CAAA,CAAA,EAAtB,IAAsB,GAAf,eAAe;AA2BzB;;;;;AAGoB;AACpB;;;;;AAGyB;AA0BzB;;;;AAEU,iBAnCM,mBAAA,CAmCN,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAjCE,uBAiCF,CAAA,EAhCP,IAgCO,GAhCA,UAgCA;AAAU,iBA/BJ,mBAAA,CA+BI,IAAA,EAAA,MAAA,EAAA,OAAA,EA7BT,uBA6BS,GAAA;EACJ,WAAA,EAAA,IAAA;CAAuB,CAAA,EA7BpC,IA6BoC,GA7B7B,eA6B6B;;;;AAEd;;;;;;;;;;;;iBALT,uBAAA,UACL,8BACR,OAAO;iBACM,uBAAA,UACL;;IACR,OAAO"}
1
+ {"version":3,"file":"filesink.deno.d.ts","names":[],"sources":["../src/filesink.deno.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAoBA;AAuBC,cAvBY,UAuBZ,EAvBwB,sBAuBxB,CAvB+C,IAAA,CAAK,MAuBpD,CAAA;;;AAvB8C;AA6B/C;AAeC,cAfY,eAeZ,EAf6B,2BAe7B,CAfyD,IAAA,CAAK,MAe9D,CAAA;;;AAfwD;AAqBzD;AAWC,cAXY,cAWZ,EAX4B,0BAW5B,CAXuD,IAAA,CAAK,MAW5D,CAAA;;;AAXsD;AAiBvD;AAYG,cAZU,mBAYV,EAZ+B,+BAY/B,CAZ+D,IAAA,CAAK,MAYpE,CAAA;;;AAZ8D;AAyBjE;;;;;AAGoB;AACpB;;AAEW,iBANK,WAAA,CAML,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAJC,eAID,CAAA,EAHR,IAGQ,GAHD,UAGC;AACR,iBAHa,WAAA,CAGb,IAAA,EAAA,MAAA,EAAA,OAAA,EADQ,eACR,GAAA;EAAI,WAAG,EAAA,IAAA;AAAe,CAAA,CAAA,EAAtB,IAAsB,GAAf,eAAe;AA2BzB;;;;;AAGoB;AACpB;;;;;AAGyB;AA0BzB;;;;AAEU,iBAnCM,mBAAA,CAmCN,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAjCE,uBAiCF,CAAA,EAhCP,IAgCO,GAhCA,UAgCA;AAAU,iBA/BJ,mBAAA,CA+BI,IAAA,EAAA,MAAA,EAAA,OAAA,EA7BT,uBA6BS,GAAA;EACJ,WAAA,EAAA,IAAA;CAAuB,CAAA,EA7BpC,IA6BoC,GA7B7B,eA6B6B;;;;AAEd;;;;;;;;;;;;iBALT,uBAAA,UACL,8BACR,OAAO;iBACM,uBAAA,UACL;;IACR,OAAO"}
@@ -54,6 +54,7 @@ const denoTimeDriver = {
54
54
  readdirSync(path) {
55
55
  return [...Deno.readDirSync(path)].map((entry) => entry.name);
56
56
  },
57
+ statSync: globalThis?.Deno.statSync,
57
58
  unlinkSync: globalThis?.Deno.removeSync,
58
59
  mkdirSync(path, options) {
59
60
  Deno.mkdirSync(path, options);
@@ -69,6 +70,7 @@ const denoAsyncTimeDriver = {
69
70
  readdirSync(path) {
70
71
  return [...Deno.readDirSync(path)].map((entry) => entry.name);
71
72
  },
73
+ statSync: globalThis?.Deno.statSync,
72
74
  unlinkSync: globalThis?.Deno.removeSync,
73
75
  mkdirSync(path, options) {
74
76
  Deno.mkdirSync(path, options);
@@ -96,23 +98,13 @@ function getRotatingFileSink(path, options = {}) {
96
98
  });
97
99
  }
98
100
  function getTimeRotatingFileSink(options) {
99
- if (options.nonBlocking) {
100
- const driver$1 = {
101
- ...denoAsyncTimeDriver,
102
- statSync: globalThis?.Deno.statSync
103
- };
104
- return getBaseTimeRotatingFileSink({
105
- ...options,
106
- ...driver$1
107
- });
108
- }
109
- const driver = {
110
- ...denoTimeDriver,
111
- statSync: globalThis?.Deno.statSync
112
- };
101
+ if (options.nonBlocking) return getBaseTimeRotatingFileSink({
102
+ ...options,
103
+ ...denoAsyncTimeDriver
104
+ });
113
105
  return getBaseTimeRotatingFileSink({
114
106
  ...options,
115
- ...driver
107
+ ...denoTimeDriver
116
108
  });
117
109
  }
118
110
 
@@ -1 +1 @@
1
- {"version":3,"file":"filesink.deno.js","names":["denoDriver: RotatingFileSinkDriver<Deno.FsFile>","path: string","fd: Deno.FsFile","chunks: Uint8Array[]","denoAsyncDriver: AsyncRotatingFileSinkDriver<Deno.FsFile>","denoTimeDriver: TimeRotatingFileSinkDriver<Deno.FsFile>","options?: { recursive?: boolean }","denoAsyncTimeDriver: AsyncTimeRotatingFileSinkDriver<Deno.FsFile>","options: FileSinkOptions","options: RotatingFileSinkOptions","options: TimeRotatingFileSinkOptions","driver"],"sources":["../src/filesink.deno.ts"],"sourcesContent":["import type { Sink } from \"@logtape/logtape\";\nimport { join } from \"@std/path/join\";\nimport {\n type AsyncRotatingFileSinkDriver,\n type FileSinkOptions,\n getBaseFileSink,\n getBaseRotatingFileSink,\n type RotatingFileSinkDriver,\n type RotatingFileSinkOptions,\n} from \"./filesink.base.ts\";\nimport {\n type AsyncTimeRotatingFileSinkDriver,\n getBaseTimeRotatingFileSink,\n type TimeRotatingFileSinkDriver,\n type TimeRotatingFileSinkOptions,\n} from \"./timefilesink.ts\";\n\n/**\n * A Deno-specific file sink driver.\n */\nexport const denoDriver: RotatingFileSinkDriver<Deno.FsFile> = {\n openSync(path: string) {\n return Deno.openSync(path, { create: true, append: true });\n },\n writeSync(fd, chunk) {\n fd.writeSync(chunk);\n },\n writeManySync(fd: Deno.FsFile, chunks: Uint8Array[]): void {\n // Deno doesn't have writev, but we can optimize by writing all chunks\n // then doing a single sync operation\n for (const chunk of chunks) {\n fd.writeSync(chunk);\n }\n },\n flushSync(fd) {\n fd.syncSync();\n },\n closeSync(fd) {\n fd.close();\n },\n statSync: globalThis?.Deno.statSync,\n renameSync: globalThis?.Deno.renameSync,\n unlinkSync: globalThis?.Deno.removeSync,\n};\n\n/**\n * A Deno-specific async file sink driver.\n * @since 1.0.0\n */\nexport const denoAsyncDriver: AsyncRotatingFileSinkDriver<Deno.FsFile> = {\n ...denoDriver,\n async writeMany(fd: Deno.FsFile, chunks: Uint8Array[]): Promise<void> {\n // Deno doesn't have async writev, but we can write all chunks\n // then do a single async sync\n for (const chunk of chunks) {\n await fd.write(chunk);\n }\n },\n async flush(fd) {\n await fd.sync();\n },\n close(fd) {\n return Promise.resolve(fd.close());\n },\n};\n\n/**\n * A Deno-specific time-rotating file sink driver.\n * @since 2.0.0\n */\nexport const denoTimeDriver: TimeRotatingFileSinkDriver<Deno.FsFile> = {\n ...denoDriver,\n readdirSync(path: string) {\n return [...Deno.readDirSync(path)].map((entry) => entry.name);\n },\n unlinkSync: globalThis?.Deno.removeSync,\n mkdirSync(path: string, options?: { recursive?: boolean }) {\n Deno.mkdirSync(path, options);\n },\n joinPath: join,\n};\n\n/**\n * A Deno-specific async time-rotating file sink driver.\n * @since 2.0.0\n */\nexport const denoAsyncTimeDriver: AsyncTimeRotatingFileSinkDriver<Deno.FsFile> =\n {\n ...denoAsyncDriver,\n readdirSync(path: string) {\n return [...Deno.readDirSync(path)].map((entry) => entry.name);\n },\n unlinkSync: globalThis?.Deno.removeSync,\n mkdirSync(path: string, options?: { recursive?: boolean }) {\n Deno.mkdirSync(path, options);\n },\n joinPath: join,\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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\nexport function getFileSink(\n path: string,\n options?: FileSinkOptions,\n): Sink & Disposable;\nexport function getFileSink(\n path: string,\n options: FileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getFileSink(\n path: string,\n options: FileSinkOptions = {},\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n return getBaseFileSink(path, { ...options, ...denoAsyncDriver });\n }\n return getBaseFileSink(path, { ...options, ...denoDriver });\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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\nexport function getRotatingFileSink(\n path: string,\n options?: RotatingFileSinkOptions,\n): Sink & Disposable;\nexport function getRotatingFileSink(\n path: string,\n options: RotatingFileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getRotatingFileSink(\n path: string,\n options: RotatingFileSinkOptions = {},\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n return getBaseRotatingFileSink(path, { ...options, ...denoAsyncDriver });\n }\n return getBaseRotatingFileSink(path, { ...options, ...denoDriver });\n}\n\n/**\n * Get a time-rotating file sink.\n *\n * This sink writes log records to a file in a directory, rotating to a new\n * file based on time intervals. The filename is generated based on the\n * current date/time and the configured interval.\n *\n * Note that this function is unavailable in the browser.\n *\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. If `nonBlocking` is\n * enabled, returns a sink that also implements {@link AsyncDisposable}.\n * @since 2.0.0\n */\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions,\n): Sink & Disposable;\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions,\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n const driver = {\n ...denoAsyncTimeDriver,\n statSync: globalThis?.Deno.statSync,\n };\n return getBaseTimeRotatingFileSink({ ...options, ...driver });\n }\n const driver = { ...denoTimeDriver, statSync: globalThis?.Deno.statSync };\n return getBaseTimeRotatingFileSink({ ...options, ...driver });\n}\n\n// cSpell: ignore filesink\n"],"mappings":";;;;;;;;AAoBA,MAAaA,aAAkD;CAC7D,SAASC,MAAc;AACrB,SAAO,KAAK,SAAS,MAAM;GAAE,QAAQ;GAAM,QAAQ;EAAM,EAAC;CAC3D;CACD,UAAU,IAAI,OAAO;AACnB,KAAG,UAAU,MAAM;CACpB;CACD,cAAcC,IAAiBC,QAA4B;AAGzD,OAAK,MAAM,SAAS,OAClB,IAAG,UAAU,MAAM;CAEtB;CACD,UAAU,IAAI;AACZ,KAAG,UAAU;CACd;CACD,UAAU,IAAI;AACZ,KAAG,OAAO;CACX;CACD,UAAU,YAAY,KAAK;CAC3B,YAAY,YAAY,KAAK;CAC7B,YAAY,YAAY,KAAK;AAC9B;;;;;AAMD,MAAaC,kBAA4D;CACvE,GAAG;CACH,MAAM,UAAUF,IAAiBC,QAAqC;AAGpE,OAAK,MAAM,SAAS,OAClB,OAAM,GAAG,MAAM,MAAM;CAExB;CACD,MAAM,MAAM,IAAI;AACd,QAAM,GAAG,MAAM;CAChB;CACD,MAAM,IAAI;AACR,SAAO,QAAQ,QAAQ,GAAG,OAAO,CAAC;CACnC;AACF;;;;;AAMD,MAAaE,iBAA0D;CACrE,GAAG;CACH,YAAYJ,MAAc;AACxB,SAAO,CAAC,GAAG,KAAK,YAAY,KAAK,AAAC,EAAC,IAAI,CAAC,UAAU,MAAM,KAAK;CAC9D;CACD,YAAY,YAAY,KAAK;CAC7B,UAAUA,MAAcK,SAAmC;AACzD,OAAK,UAAU,MAAM,QAAQ;CAC9B;CACD,UAAU;AACX;;;;;AAMD,MAAaC,sBACX;CACE,GAAG;CACH,YAAYN,MAAc;AACxB,SAAO,CAAC,GAAG,KAAK,YAAY,KAAK,AAAC,EAAC,IAAI,CAAC,UAAU,MAAM,KAAK;CAC9D;CACD,YAAY,YAAY,KAAK;CAC7B,UAAUA,MAAcK,SAAmC;AACzD,OAAK,UAAU,MAAM,QAAQ;CAC9B;CACD,UAAU;AACX;AAqBH,SAAgB,YACdL,MACAO,UAA2B,CAAE,GACU;AACvC,KAAI,QAAQ,YACV,QAAO,gBAAgB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAiB,EAAC;AAElE,QAAO,gBAAgB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAY,EAAC;AAC5D;AA0BD,SAAgB,oBACdP,MACAQ,UAAmC,CAAE,GACE;AACvC,KAAI,QAAQ,YACV,QAAO,wBAAwB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAiB,EAAC;AAE1E,QAAO,wBAAwB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAY,EAAC;AACpE;AAuBD,SAAgB,wBACdC,SACuC;AACvC,KAAI,QAAQ,aAAa;EACvB,MAAMC,WAAS;GACb,GAAG;GACH,UAAU,YAAY,KAAK;EAC5B;AACD,SAAO,4BAA4B;GAAE,GAAG;GAAS,GAAGA;EAAQ,EAAC;CAC9D;CACD,MAAM,SAAS;EAAE,GAAG;EAAgB,UAAU,YAAY,KAAK;CAAU;AACzE,QAAO,4BAA4B;EAAE,GAAG;EAAS,GAAG;CAAQ,EAAC;AAC9D"}
1
+ {"version":3,"file":"filesink.deno.js","names":["denoDriver: RotatingFileSinkDriver<Deno.FsFile>","path: string","fd: Deno.FsFile","chunks: Uint8Array[]","denoAsyncDriver: AsyncRotatingFileSinkDriver<Deno.FsFile>","denoTimeDriver: TimeRotatingFileSinkDriver<Deno.FsFile>","options?: { recursive?: boolean }","denoAsyncTimeDriver: AsyncTimeRotatingFileSinkDriver<Deno.FsFile>","options: FileSinkOptions","options: RotatingFileSinkOptions","options: TimeRotatingFileSinkOptions"],"sources":["../src/filesink.deno.ts"],"sourcesContent":["import type { Sink } from \"@logtape/logtape\";\nimport { join } from \"@std/path/join\";\nimport {\n type AsyncRotatingFileSinkDriver,\n type FileSinkOptions,\n getBaseFileSink,\n getBaseRotatingFileSink,\n type RotatingFileSinkDriver,\n type RotatingFileSinkOptions,\n} from \"./filesink.base.ts\";\nimport {\n type AsyncTimeRotatingFileSinkDriver,\n getBaseTimeRotatingFileSink,\n type TimeRotatingFileSinkDriver,\n type TimeRotatingFileSinkOptions,\n} from \"./timefilesink.ts\";\n\n/**\n * A Deno-specific file sink driver.\n */\nexport const denoDriver: RotatingFileSinkDriver<Deno.FsFile> = {\n openSync(path: string) {\n return Deno.openSync(path, { create: true, append: true });\n },\n writeSync(fd, chunk) {\n fd.writeSync(chunk);\n },\n writeManySync(fd: Deno.FsFile, chunks: Uint8Array[]): void {\n // Deno doesn't have writev, but we can optimize by writing all chunks\n // then doing a single sync operation\n for (const chunk of chunks) {\n fd.writeSync(chunk);\n }\n },\n flushSync(fd) {\n fd.syncSync();\n },\n closeSync(fd) {\n fd.close();\n },\n statSync: globalThis?.Deno.statSync,\n renameSync: globalThis?.Deno.renameSync,\n unlinkSync: globalThis?.Deno.removeSync,\n};\n\n/**\n * A Deno-specific async file sink driver.\n * @since 1.0.0\n */\nexport const denoAsyncDriver: AsyncRotatingFileSinkDriver<Deno.FsFile> = {\n ...denoDriver,\n async writeMany(fd: Deno.FsFile, chunks: Uint8Array[]): Promise<void> {\n // Deno doesn't have async writev, but we can write all chunks\n // then do a single async sync\n for (const chunk of chunks) {\n await fd.write(chunk);\n }\n },\n async flush(fd) {\n await fd.sync();\n },\n close(fd) {\n return Promise.resolve(fd.close());\n },\n};\n\n/**\n * A Deno-specific time-rotating file sink driver.\n * @since 2.0.0\n */\nexport const denoTimeDriver: TimeRotatingFileSinkDriver<Deno.FsFile> = {\n ...denoDriver,\n readdirSync(path: string) {\n return [...Deno.readDirSync(path)].map((entry) => entry.name);\n },\n statSync: globalThis?.Deno.statSync,\n unlinkSync: globalThis?.Deno.removeSync,\n mkdirSync(path: string, options?: { recursive?: boolean }) {\n Deno.mkdirSync(path, options);\n },\n joinPath: join,\n};\n\n/**\n * A Deno-specific async time-rotating file sink driver.\n * @since 2.0.0\n */\nexport const denoAsyncTimeDriver: AsyncTimeRotatingFileSinkDriver<Deno.FsFile> =\n {\n ...denoAsyncDriver,\n readdirSync(path: string) {\n return [...Deno.readDirSync(path)].map((entry) => entry.name);\n },\n statSync: globalThis?.Deno.statSync,\n unlinkSync: globalThis?.Deno.removeSync,\n mkdirSync(path: string, options?: { recursive?: boolean }) {\n Deno.mkdirSync(path, options);\n },\n joinPath: join,\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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\nexport function getFileSink(\n path: string,\n options?: FileSinkOptions,\n): Sink & Disposable;\nexport function getFileSink(\n path: string,\n options: FileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getFileSink(\n path: string,\n options: FileSinkOptions = {},\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n return getBaseFileSink(path, { ...options, ...denoAsyncDriver });\n }\n return getBaseFileSink(path, { ...options, ...denoDriver });\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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\nexport function getRotatingFileSink(\n path: string,\n options?: RotatingFileSinkOptions,\n): Sink & Disposable;\nexport function getRotatingFileSink(\n path: string,\n options: RotatingFileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getRotatingFileSink(\n path: string,\n options: RotatingFileSinkOptions = {},\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n return getBaseRotatingFileSink(path, { ...options, ...denoAsyncDriver });\n }\n return getBaseRotatingFileSink(path, { ...options, ...denoDriver });\n}\n\n/**\n * Get a time-rotating file sink.\n *\n * This sink writes log records to a file in a directory, rotating to a new\n * file based on time intervals. The filename is generated based on the\n * current date/time and the configured interval.\n *\n * Note that this function is unavailable in the browser.\n *\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. If `nonBlocking` is\n * enabled, returns a sink that also implements {@link AsyncDisposable}.\n * @since 2.0.0\n */\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions,\n): Sink & Disposable;\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions,\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n return getBaseTimeRotatingFileSink({ ...options, ...denoAsyncTimeDriver });\n }\n return getBaseTimeRotatingFileSink({ ...options, ...denoTimeDriver });\n}\n\n// cSpell: ignore filesink\n"],"mappings":";;;;;;;;AAoBA,MAAaA,aAAkD;CAC7D,SAASC,MAAc;AACrB,SAAO,KAAK,SAAS,MAAM;GAAE,QAAQ;GAAM,QAAQ;EAAM,EAAC;CAC3D;CACD,UAAU,IAAI,OAAO;AACnB,KAAG,UAAU,MAAM;CACpB;CACD,cAAcC,IAAiBC,QAA4B;AAGzD,OAAK,MAAM,SAAS,OAClB,IAAG,UAAU,MAAM;CAEtB;CACD,UAAU,IAAI;AACZ,KAAG,UAAU;CACd;CACD,UAAU,IAAI;AACZ,KAAG,OAAO;CACX;CACD,UAAU,YAAY,KAAK;CAC3B,YAAY,YAAY,KAAK;CAC7B,YAAY,YAAY,KAAK;AAC9B;;;;;AAMD,MAAaC,kBAA4D;CACvE,GAAG;CACH,MAAM,UAAUF,IAAiBC,QAAqC;AAGpE,OAAK,MAAM,SAAS,OAClB,OAAM,GAAG,MAAM,MAAM;CAExB;CACD,MAAM,MAAM,IAAI;AACd,QAAM,GAAG,MAAM;CAChB;CACD,MAAM,IAAI;AACR,SAAO,QAAQ,QAAQ,GAAG,OAAO,CAAC;CACnC;AACF;;;;;AAMD,MAAaE,iBAA0D;CACrE,GAAG;CACH,YAAYJ,MAAc;AACxB,SAAO,CAAC,GAAG,KAAK,YAAY,KAAK,AAAC,EAAC,IAAI,CAAC,UAAU,MAAM,KAAK;CAC9D;CACD,UAAU,YAAY,KAAK;CAC3B,YAAY,YAAY,KAAK;CAC7B,UAAUA,MAAcK,SAAmC;AACzD,OAAK,UAAU,MAAM,QAAQ;CAC9B;CACD,UAAU;AACX;;;;;AAMD,MAAaC,sBACX;CACE,GAAG;CACH,YAAYN,MAAc;AACxB,SAAO,CAAC,GAAG,KAAK,YAAY,KAAK,AAAC,EAAC,IAAI,CAAC,UAAU,MAAM,KAAK;CAC9D;CACD,UAAU,YAAY,KAAK;CAC3B,YAAY,YAAY,KAAK;CAC7B,UAAUA,MAAcK,SAAmC;AACzD,OAAK,UAAU,MAAM,QAAQ;CAC9B;CACD,UAAU;AACX;AAqBH,SAAgB,YACdL,MACAO,UAA2B,CAAE,GACU;AACvC,KAAI,QAAQ,YACV,QAAO,gBAAgB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAiB,EAAC;AAElE,QAAO,gBAAgB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAY,EAAC;AAC5D;AA0BD,SAAgB,oBACdP,MACAQ,UAAmC,CAAE,GACE;AACvC,KAAI,QAAQ,YACV,QAAO,wBAAwB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAiB,EAAC;AAE1E,QAAO,wBAAwB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAY,EAAC;AACpE;AAuBD,SAAgB,wBACdC,SACuC;AACvC,KAAI,QAAQ,YACV,QAAO,4BAA4B;EAAE,GAAG;EAAS,GAAG;CAAqB,EAAC;AAE5E,QAAO,4BAA4B;EAAE,GAAG;EAAS,GAAG;CAAgB,EAAC;AACtE"}
@@ -52,6 +52,7 @@ const nodeAsyncDriver = {
52
52
  const nodeTimeDriver = {
53
53
  ...nodeDriver,
54
54
  readdirSync: node_fs.default.readdirSync,
55
+ statSync: node_fs.default.statSync,
55
56
  unlinkSync: node_fs.default.unlinkSync,
56
57
  mkdirSync: node_fs.default.mkdirSync,
57
58
  joinPath: node_path.join
@@ -63,6 +64,7 @@ const nodeTimeDriver = {
63
64
  const nodeAsyncTimeDriver = {
64
65
  ...nodeAsyncDriver,
65
66
  readdirSync: node_fs.default.readdirSync,
67
+ statSync: node_fs.default.statSync,
66
68
  unlinkSync: node_fs.default.unlinkSync,
67
69
  mkdirSync: node_fs.default.mkdirSync,
68
70
  joinPath: node_path.join
@@ -88,23 +90,13 @@ function getRotatingFileSink(path, options = {}) {
88
90
  });
89
91
  }
90
92
  function getTimeRotatingFileSink(options) {
91
- if (options.nonBlocking) {
92
- const driver$1 = {
93
- ...nodeAsyncTimeDriver,
94
- statSync: node_fs.default.statSync
95
- };
96
- return require_timefilesink.getBaseTimeRotatingFileSink({
97
- ...options,
98
- ...driver$1
99
- });
100
- }
101
- const driver = {
102
- ...nodeTimeDriver,
103
- statSync: node_fs.default.statSync
104
- };
93
+ if (options.nonBlocking) return require_timefilesink.getBaseTimeRotatingFileSink({
94
+ ...options,
95
+ ...nodeAsyncTimeDriver
96
+ });
105
97
  return require_timefilesink.getBaseTimeRotatingFileSink({
106
98
  ...options,
107
- ...driver
99
+ ...nodeTimeDriver
108
100
  });
109
101
  }
110
102
 
@@ -1 +1 @@
1
- {"version":3,"file":"filesink.node.d.cts","names":[],"sources":["../src/filesink.node.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAsBA;AAyBa,cAzBA,UAsCZ,EAtCwB,sBAyBK,CAAA,MAA2B,GAAA,IAAA,CAAA;AAmBzD;AAYA;AAqBA;;AAEY,cAtDC,eAsDD,EAtDkB,2BAsDlB,CAAA,MAAA,GAAA,IAAA,CAAA;;;AACQ;AACpB;AAA2B,cArCd,cAqCc,EArCE,0BAqCF,CAAA,MAAA,GAAA,IAAA,CAAA;;;;AAGF;AA2BT,cAvDH,mBAuDsB,EAvDD,+BAuDC,CAAA,MAAA,GAAA,IAAA,CAAA;;;;;AAGf;AACpB;;;;;AAGyB;AA0BT,iBAnEA,WAAA,CAmEuB,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAjE3B,eAiE2B,CAAA,EAhEpC,IAgEoC,GAhE7B,UAgE6B;AAAA,iBA/DvB,WAAA,CA+DuB,IAAA,EAAA,MAAA,EAAA,OAAA,EA7D5B,eA6D4B,GAAA;EAAA,WAC5B,EAAA,IAAA;CAA2B,CAAA,EA7DnC,IA8DA,GA9DO,eA8DP;;AAAiB;AACpB;;;;;AAEyB;;;;;;;;;iBAtCT,mBAAA,yBAEJ,0BACT,OAAO;iBACM,mBAAA,wBAEL;;IACR,OAAO;;;;;;;;;;;;;;;;iBA0BM,uBAAA,UACL,8BACR,OAAO;iBACM,uBAAA,UACL;;IACR,OAAO"}
1
+ {"version":3,"file":"filesink.node.d.cts","names":[],"sources":["../src/filesink.node.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAsBA;AAyBa,cAzBA,UAsCZ,EAtCwB,sBAyBK,CAAA,MAA2B,GAAA,IAAA,CAAA;AAmBzD;AAaA;AAsBA;;AAEY,cAxDC,eAwDD,EAxDkB,2BAwDlB,CAAA,MAAA,GAAA,IAAA,CAAA;;;AACQ;AACpB;AAA2B,cAvCd,cAuCc,EAvCE,0BAuCF,CAAA,MAAA,GAAA,IAAA,CAAA;;;;AAGF;AA2BT,cAxDH,mBAwDsB,EAxDD,+BAwDC,CAAA,MAAA,GAAA,IAAA,CAAA;;;;;AAGf;AACpB;;;;;AAGyB;AA0BT,iBAnEA,WAAA,CAmEuB,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAjE3B,eAiE2B,CAAA,EAhEpC,IAgEoC,GAhE7B,UAgE6B;AAAA,iBA/DvB,WAAA,CA+DuB,IAAA,EAAA,MAAA,EAAA,OAAA,EA7D5B,eA6D4B,GAAA;EAAA,WAC5B,EAAA,IAAA;CAA2B,CAAA,EA7DnC,IA8DA,GA9DO,eA8DP;;AAAiB;AACpB;;;;;AAEyB;;;;;;;;;iBAtCT,mBAAA,yBAEJ,0BACT,OAAO;iBACM,mBAAA,wBAEL;;IACR,OAAO;;;;;;;;;;;;;;;;iBA0BM,uBAAA,UACL,8BACR,OAAO;iBACM,uBAAA,UACL;;IACR,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"filesink.node.d.ts","names":[],"sources":["../src/filesink.node.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAsBA;AAyBa,cAzBA,UAsCZ,EAtCwB,sBAyBK,CAAA,MAA2B,GAAA,IAAA,CAAA;AAmBzD;AAYA;AAqBA;;AAEY,cAtDC,eAsDD,EAtDkB,2BAsDlB,CAAA,MAAA,GAAA,IAAA,CAAA;;;AACQ;AACpB;AAA2B,cArCd,cAqCc,EArCE,0BAqCF,CAAA,MAAA,GAAA,IAAA,CAAA;;;;AAGF;AA2BT,cAvDH,mBAuDsB,EAvDD,+BAuDC,CAAA,MAAA,GAAA,IAAA,CAAA;;;;;AAGf;AACpB;;;;;AAGyB;AA0BT,iBAnEA,WAAA,CAmEuB,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAjE3B,eAiE2B,CAAA,EAhEpC,IAgEoC,GAhE7B,UAgE6B;AAAA,iBA/DvB,WAAA,CA+DuB,IAAA,EAAA,MAAA,EAAA,OAAA,EA7D5B,eA6D4B,GAAA;EAAA,WAC5B,EAAA,IAAA;CAA2B,CAAA,EA7DnC,IA8DA,GA9DO,eA8DP;;AAAiB;AACpB;;;;;AAEyB;;;;;;;;;iBAtCT,mBAAA,yBAEJ,0BACT,OAAO;iBACM,mBAAA,wBAEL;;IACR,OAAO;;;;;;;;;;;;;;;;iBA0BM,uBAAA,UACL,8BACR,OAAO;iBACM,uBAAA,UACL;;IACR,OAAO"}
1
+ {"version":3,"file":"filesink.node.d.ts","names":[],"sources":["../src/filesink.node.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAsBA;AAyBa,cAzBA,UAsCZ,EAtCwB,sBAyBK,CAAA,MAA2B,GAAA,IAAA,CAAA;AAmBzD;AAaA;AAsBA;;AAEY,cAxDC,eAwDD,EAxDkB,2BAwDlB,CAAA,MAAA,GAAA,IAAA,CAAA;;;AACQ;AACpB;AAA2B,cAvCd,cAuCc,EAvCE,0BAuCF,CAAA,MAAA,GAAA,IAAA,CAAA;;;;AAGF;AA2BT,cAxDH,mBAwDsB,EAxDD,+BAwDC,CAAA,MAAA,GAAA,IAAA,CAAA;;;;;AAGf;AACpB;;;;;AAGyB;AA0BT,iBAnEA,WAAA,CAmEuB,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAjE3B,eAiE2B,CAAA,EAhEpC,IAgEoC,GAhE7B,UAgE6B;AAAA,iBA/DvB,WAAA,CA+DuB,IAAA,EAAA,MAAA,EAAA,OAAA,EA7D5B,eA6D4B,GAAA;EAAA,WAC5B,EAAA,IAAA;CAA2B,CAAA,EA7DnC,IA8DA,GA9DO,eA8DP;;AAAiB;AACpB;;;;;AAEyB;;;;;;;;;iBAtCT,mBAAA,yBAEJ,0BACT,OAAO;iBACM,mBAAA,wBAEL;;IACR,OAAO;;;;;;;;;;;;;;;;iBA0BM,uBAAA,UACL,8BACR,OAAO;iBACM,uBAAA,UACL;;IACR,OAAO"}
@@ -51,6 +51,7 @@ const nodeAsyncDriver = {
51
51
  const nodeTimeDriver = {
52
52
  ...nodeDriver,
53
53
  readdirSync: fs.readdirSync,
54
+ statSync: fs.statSync,
54
55
  unlinkSync: fs.unlinkSync,
55
56
  mkdirSync: fs.mkdirSync,
56
57
  joinPath: join
@@ -62,6 +63,7 @@ const nodeTimeDriver = {
62
63
  const nodeAsyncTimeDriver = {
63
64
  ...nodeAsyncDriver,
64
65
  readdirSync: fs.readdirSync,
66
+ statSync: fs.statSync,
65
67
  unlinkSync: fs.unlinkSync,
66
68
  mkdirSync: fs.mkdirSync,
67
69
  joinPath: join
@@ -87,23 +89,13 @@ function getRotatingFileSink(path, options = {}) {
87
89
  });
88
90
  }
89
91
  function getTimeRotatingFileSink(options) {
90
- if (options.nonBlocking) {
91
- const driver$1 = {
92
- ...nodeAsyncTimeDriver,
93
- statSync: fs.statSync
94
- };
95
- return getBaseTimeRotatingFileSink({
96
- ...options,
97
- ...driver$1
98
- });
99
- }
100
- const driver = {
101
- ...nodeTimeDriver,
102
- statSync: fs.statSync
103
- };
92
+ if (options.nonBlocking) return getBaseTimeRotatingFileSink({
93
+ ...options,
94
+ ...nodeAsyncTimeDriver
95
+ });
104
96
  return getBaseTimeRotatingFileSink({
105
97
  ...options,
106
- ...driver
98
+ ...nodeTimeDriver
107
99
  });
108
100
  }
109
101
 
@@ -1 +1 @@
1
- {"version":3,"file":"filesink.node.js","names":["nodeDriver: RotatingFileSinkDriver<number | void>","path: string","fd: number","chunks: Uint8Array[]","nodeAsyncDriver: AsyncRotatingFileSinkDriver<number | void>","nodeTimeDriver: TimeRotatingFileSinkDriver<number | void>","nodeAsyncTimeDriver: AsyncTimeRotatingFileSinkDriver<\n number | void\n>","options: FileSinkOptions","options: RotatingFileSinkOptions","options: TimeRotatingFileSinkOptions","driver"],"sources":["../src/filesink.node.ts"],"sourcesContent":["import type { Sink } from \"@logtape/logtape\";\nimport fs from \"node:fs\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport {\n type AsyncRotatingFileSinkDriver,\n type FileSinkOptions,\n getBaseFileSink,\n getBaseRotatingFileSink,\n type RotatingFileSinkDriver,\n type RotatingFileSinkOptions,\n} from \"./filesink.base.ts\";\nimport {\n type AsyncTimeRotatingFileSinkDriver,\n getBaseTimeRotatingFileSink,\n type TimeRotatingFileSinkDriver,\n type TimeRotatingFileSinkOptions,\n} from \"./timefilesink.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 writeManySync(fd: number, chunks: Uint8Array[]): void {\n if (chunks.length === 0) return;\n if (chunks.length === 1) {\n fs.writeSync(fd, chunks[0]);\n return;\n }\n // Use writev for multiple chunks\n fs.writevSync(fd, chunks);\n },\n flushSync: fs.fsyncSync,\n closeSync: fs.closeSync,\n statSync: fs.statSync,\n renameSync: fs.renameSync,\n unlinkSync: fs.unlinkSync,\n};\n\n/**\n * A Node.js-specific async file sink driver.\n * @since 1.0.0\n */\nexport const nodeAsyncDriver: AsyncRotatingFileSinkDriver<number | void> = {\n ...nodeDriver,\n async writeMany(fd: number, chunks: Uint8Array[]): Promise<void> {\n if (chunks.length === 0) return;\n if (chunks.length === 1) {\n await promisify(fs.write)(fd, chunks[0]);\n return;\n }\n // Use async writev for multiple chunks\n await promisify(fs.writev)(fd, chunks);\n },\n flush: promisify(fs.fsync),\n close: promisify(fs.close),\n};\n\n/**\n * A Node.js-specific time-rotating file sink driver.\n * @since 2.0.0\n */\nexport const nodeTimeDriver: TimeRotatingFileSinkDriver<number | void> = {\n ...nodeDriver,\n readdirSync: fs.readdirSync as (path: string) => string[],\n unlinkSync: fs.unlinkSync,\n mkdirSync: fs.mkdirSync,\n joinPath: join,\n};\n\n/**\n * A Node.js-specific async time-rotating file sink driver.\n * @since 2.0.0\n */\nexport const nodeAsyncTimeDriver: AsyncTimeRotatingFileSinkDriver<\n number | void\n> = {\n ...nodeAsyncDriver,\n readdirSync: fs.readdirSync as (path: string) => string[],\n unlinkSync: fs.unlinkSync,\n mkdirSync: fs.mkdirSync,\n joinPath: join,\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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\nexport function getFileSink(\n path: string,\n options?: FileSinkOptions,\n): Sink & Disposable;\nexport function getFileSink(\n path: string,\n options: FileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getFileSink(\n path: string,\n options: FileSinkOptions = {},\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n return getBaseFileSink(path, { ...options, ...nodeAsyncDriver });\n }\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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\nexport function getRotatingFileSink(\n path: string,\n options?: RotatingFileSinkOptions,\n): Sink & Disposable;\nexport function getRotatingFileSink(\n path: string,\n options: RotatingFileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getRotatingFileSink(\n path: string,\n options: RotatingFileSinkOptions = {},\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n return getBaseRotatingFileSink(path, { ...options, ...nodeAsyncDriver });\n }\n return getBaseRotatingFileSink(path, { ...options, ...nodeDriver });\n}\n\n/**\n * Get a time-rotating file sink.\n *\n * This sink writes log records to a file in a directory, rotating to a new\n * file based on time intervals. The filename is generated based on the\n * current date/time and the configured interval.\n *\n * Note that this function is unavailable in the browser.\n *\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. If `nonBlocking` is\n * enabled, returns a sink that also implements {@link AsyncDisposable}.\n * @since 2.0.0\n */\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions,\n): Sink & Disposable;\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions,\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n const driver = { ...nodeAsyncTimeDriver, statSync: fs.statSync };\n return getBaseTimeRotatingFileSink({ ...options, ...driver });\n }\n const driver = { ...nodeTimeDriver, statSync: fs.statSync };\n return getBaseTimeRotatingFileSink({ ...options, ...driver });\n}\n\n// cSpell: ignore filesink\n"],"mappings":";;;;;;;;;;AAsBA,MAAaA,aAAoD;CAC/D,SAASC,MAAc;AACrB,SAAO,GAAG,SAAS,MAAM,IAAI;CAC9B;CACD,WAAW,GAAG;CACd,cAAcC,IAAYC,QAA4B;AACpD,MAAI,OAAO,WAAW,EAAG;AACzB,MAAI,OAAO,WAAW,GAAG;AACvB,MAAG,UAAU,IAAI,OAAO,GAAG;AAC3B;EACD;AAED,KAAG,WAAW,IAAI,OAAO;CAC1B;CACD,WAAW,GAAG;CACd,WAAW,GAAG;CACd,UAAU,GAAG;CACb,YAAY,GAAG;CACf,YAAY,GAAG;AAChB;;;;;AAMD,MAAaC,kBAA8D;CACzE,GAAG;CACH,MAAM,UAAUF,IAAYC,QAAqC;AAC/D,MAAI,OAAO,WAAW,EAAG;AACzB,MAAI,OAAO,WAAW,GAAG;AACvB,SAAM,UAAU,GAAG,MAAM,CAAC,IAAI,OAAO,GAAG;AACxC;EACD;AAED,QAAM,UAAU,GAAG,OAAO,CAAC,IAAI,OAAO;CACvC;CACD,OAAO,UAAU,GAAG,MAAM;CAC1B,OAAO,UAAU,GAAG,MAAM;AAC3B;;;;;AAMD,MAAaE,iBAA4D;CACvE,GAAG;CACH,aAAa,GAAG;CAChB,YAAY,GAAG;CACf,WAAW,GAAG;CACd,UAAU;AACX;;;;;AAMD,MAAaC,sBAET;CACF,GAAG;CACH,aAAa,GAAG;CAChB,YAAY,GAAG;CACf,WAAW,GAAG;CACd,UAAU;AACX;AAqBD,SAAgB,YACdL,MACAM,UAA2B,CAAE,GACU;AACvC,KAAI,QAAQ,YACV,QAAO,gBAAgB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAiB,EAAC;AAElE,QAAO,gBAAgB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAY,EAAC;AAC5D;AA0BD,SAAgB,oBACdN,MACAO,UAAmC,CAAE,GACE;AACvC,KAAI,QAAQ,YACV,QAAO,wBAAwB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAiB,EAAC;AAE1E,QAAO,wBAAwB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAY,EAAC;AACpE;AAuBD,SAAgB,wBACdC,SACuC;AACvC,KAAI,QAAQ,aAAa;EACvB,MAAMC,WAAS;GAAE,GAAG;GAAqB,UAAU,GAAG;EAAU;AAChE,SAAO,4BAA4B;GAAE,GAAG;GAAS,GAAGA;EAAQ,EAAC;CAC9D;CACD,MAAM,SAAS;EAAE,GAAG;EAAgB,UAAU,GAAG;CAAU;AAC3D,QAAO,4BAA4B;EAAE,GAAG;EAAS,GAAG;CAAQ,EAAC;AAC9D"}
1
+ {"version":3,"file":"filesink.node.js","names":["nodeDriver: RotatingFileSinkDriver<number | void>","path: string","fd: number","chunks: Uint8Array[]","nodeAsyncDriver: AsyncRotatingFileSinkDriver<number | void>","nodeTimeDriver: TimeRotatingFileSinkDriver<number | void>","nodeAsyncTimeDriver: AsyncTimeRotatingFileSinkDriver<\n number | void\n>","options: FileSinkOptions","options: RotatingFileSinkOptions","options: TimeRotatingFileSinkOptions"],"sources":["../src/filesink.node.ts"],"sourcesContent":["import type { Sink } from \"@logtape/logtape\";\nimport fs from \"node:fs\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport {\n type AsyncRotatingFileSinkDriver,\n type FileSinkOptions,\n getBaseFileSink,\n getBaseRotatingFileSink,\n type RotatingFileSinkDriver,\n type RotatingFileSinkOptions,\n} from \"./filesink.base.ts\";\nimport {\n type AsyncTimeRotatingFileSinkDriver,\n getBaseTimeRotatingFileSink,\n type TimeRotatingFileSinkDriver,\n type TimeRotatingFileSinkOptions,\n} from \"./timefilesink.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 writeManySync(fd: number, chunks: Uint8Array[]): void {\n if (chunks.length === 0) return;\n if (chunks.length === 1) {\n fs.writeSync(fd, chunks[0]);\n return;\n }\n // Use writev for multiple chunks\n fs.writevSync(fd, chunks);\n },\n flushSync: fs.fsyncSync,\n closeSync: fs.closeSync,\n statSync: fs.statSync,\n renameSync: fs.renameSync,\n unlinkSync: fs.unlinkSync,\n};\n\n/**\n * A Node.js-specific async file sink driver.\n * @since 1.0.0\n */\nexport const nodeAsyncDriver: AsyncRotatingFileSinkDriver<number | void> = {\n ...nodeDriver,\n async writeMany(fd: number, chunks: Uint8Array[]): Promise<void> {\n if (chunks.length === 0) return;\n if (chunks.length === 1) {\n await promisify(fs.write)(fd, chunks[0]);\n return;\n }\n // Use async writev for multiple chunks\n await promisify(fs.writev)(fd, chunks);\n },\n flush: promisify(fs.fsync),\n close: promisify(fs.close),\n};\n\n/**\n * A Node.js-specific time-rotating file sink driver.\n * @since 2.0.0\n */\nexport const nodeTimeDriver: TimeRotatingFileSinkDriver<number | void> = {\n ...nodeDriver,\n readdirSync: fs.readdirSync as (path: string) => string[],\n statSync: fs.statSync,\n unlinkSync: fs.unlinkSync,\n mkdirSync: fs.mkdirSync,\n joinPath: join,\n};\n\n/**\n * A Node.js-specific async time-rotating file sink driver.\n * @since 2.0.0\n */\nexport const nodeAsyncTimeDriver: AsyncTimeRotatingFileSinkDriver<\n number | void\n> = {\n ...nodeAsyncDriver,\n readdirSync: fs.readdirSync as (path: string) => string[],\n statSync: fs.statSync,\n unlinkSync: fs.unlinkSync,\n mkdirSync: fs.mkdirSync,\n joinPath: join,\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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\nexport function getFileSink(\n path: string,\n options?: FileSinkOptions,\n): Sink & Disposable;\nexport function getFileSink(\n path: string,\n options: FileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getFileSink(\n path: string,\n options: FileSinkOptions = {},\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n return getBaseFileSink(path, { ...options, ...nodeAsyncDriver });\n }\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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\nexport function getRotatingFileSink(\n path: string,\n options?: RotatingFileSinkOptions,\n): Sink & Disposable;\nexport function getRotatingFileSink(\n path: string,\n options: RotatingFileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getRotatingFileSink(\n path: string,\n options: RotatingFileSinkOptions = {},\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n return getBaseRotatingFileSink(path, { ...options, ...nodeAsyncDriver });\n }\n return getBaseRotatingFileSink(path, { ...options, ...nodeDriver });\n}\n\n/**\n * Get a time-rotating file sink.\n *\n * This sink writes log records to a file in a directory, rotating to a new\n * file based on time intervals. The filename is generated based on the\n * current date/time and the configured interval.\n *\n * Note that this function is unavailable in the browser.\n *\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. If `nonBlocking` is\n * enabled, returns a sink that also implements {@link AsyncDisposable}.\n * @since 2.0.0\n */\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions,\n): Sink & Disposable;\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions & { nonBlocking: true },\n): Sink & AsyncDisposable;\nexport function getTimeRotatingFileSink(\n options: TimeRotatingFileSinkOptions,\n): Sink & (Disposable | AsyncDisposable) {\n if (options.nonBlocking) {\n return getBaseTimeRotatingFileSink({ ...options, ...nodeAsyncTimeDriver });\n }\n return getBaseTimeRotatingFileSink({ ...options, ...nodeTimeDriver });\n}\n\n// cSpell: ignore filesink\n"],"mappings":";;;;;;;;;;AAsBA,MAAaA,aAAoD;CAC/D,SAASC,MAAc;AACrB,SAAO,GAAG,SAAS,MAAM,IAAI;CAC9B;CACD,WAAW,GAAG;CACd,cAAcC,IAAYC,QAA4B;AACpD,MAAI,OAAO,WAAW,EAAG;AACzB,MAAI,OAAO,WAAW,GAAG;AACvB,MAAG,UAAU,IAAI,OAAO,GAAG;AAC3B;EACD;AAED,KAAG,WAAW,IAAI,OAAO;CAC1B;CACD,WAAW,GAAG;CACd,WAAW,GAAG;CACd,UAAU,GAAG;CACb,YAAY,GAAG;CACf,YAAY,GAAG;AAChB;;;;;AAMD,MAAaC,kBAA8D;CACzE,GAAG;CACH,MAAM,UAAUF,IAAYC,QAAqC;AAC/D,MAAI,OAAO,WAAW,EAAG;AACzB,MAAI,OAAO,WAAW,GAAG;AACvB,SAAM,UAAU,GAAG,MAAM,CAAC,IAAI,OAAO,GAAG;AACxC;EACD;AAED,QAAM,UAAU,GAAG,OAAO,CAAC,IAAI,OAAO;CACvC;CACD,OAAO,UAAU,GAAG,MAAM;CAC1B,OAAO,UAAU,GAAG,MAAM;AAC3B;;;;;AAMD,MAAaE,iBAA4D;CACvE,GAAG;CACH,aAAa,GAAG;CAChB,UAAU,GAAG;CACb,YAAY,GAAG;CACf,WAAW,GAAG;CACd,UAAU;AACX;;;;;AAMD,MAAaC,sBAET;CACF,GAAG;CACH,aAAa,GAAG;CAChB,UAAU,GAAG;CACb,YAAY,GAAG;CACf,WAAW,GAAG;CACd,UAAU;AACX;AAqBD,SAAgB,YACdL,MACAM,UAA2B,CAAE,GACU;AACvC,KAAI,QAAQ,YACV,QAAO,gBAAgB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAiB,EAAC;AAElE,QAAO,gBAAgB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAY,EAAC;AAC5D;AA0BD,SAAgB,oBACdN,MACAO,UAAmC,CAAE,GACE;AACvC,KAAI,QAAQ,YACV,QAAO,wBAAwB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAiB,EAAC;AAE1E,QAAO,wBAAwB,MAAM;EAAE,GAAG;EAAS,GAAG;CAAY,EAAC;AACpE;AAuBD,SAAgB,wBACdC,SACuC;AACvC,KAAI,QAAQ,YACV,QAAO,4BAA4B;EAAE,GAAG;EAAS,GAAG;CAAqB,EAAC;AAE5E,QAAO,4BAA4B;EAAE,GAAG;EAAS,GAAG;CAAgB,EAAC;AACtE"}
package/dist/mod.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { FileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions } from "./filesink.base.cjs";
2
2
  import { TimeRotatingFileSinkOptions, TimeRotationInterval } from "./timefilesink.cjs";
3
3
  import { StreamFileSinkOptions, getStreamFileSink } from "./streamfilesink.cjs";
4
- import { getFileSink, getRotatingFileSink, getTimeRotatingFileSink } from "./dist/filesink.node.cjs";
4
+ import { getFileSink, getRotatingFileSink, getTimeRotatingFileSink } from "#filesink";
5
5
  export { FileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions, StreamFileSinkOptions, TimeRotatingFileSinkOptions, TimeRotationInterval, getFileSink, getRotatingFileSink, getStreamFileSink, getTimeRotatingFileSink };
@@ -101,6 +101,7 @@ function getBaseTimeRotatingFileSink(options) {
101
101
  const interval = options.interval ?? "daily";
102
102
  const hasCustomFilename = options.filename !== void 0;
103
103
  const filenameGenerator = options.filename ?? getDefaultFilename(interval);
104
+ const parseFilename = options.parseFilename;
104
105
  const maxAgeMs = options.maxAgeMs;
105
106
  const cleanupInterval = maxAgeMs === void 0 ? getRotationIntervalMs(interval) : Math.min(getRotationIntervalMs(interval), maxAgeMs);
106
107
  const bufferSize = options.bufferSize ?? 1024 * 8;
@@ -144,7 +145,8 @@ function getBaseTimeRotatingFileSink(options) {
144
145
  for (const file of files) {
145
146
  if (file === currentFilename) continue;
146
147
  let fileDate = null;
147
- if (hasCustomFilename) {
148
+ if (parseFilename !== void 0) fileDate = parseFilename(file);
149
+ else if (hasCustomFilename) {
148
150
  if (statSync === void 0) continue;
149
151
  try {
150
152
  fileDate = statSync(options.joinPath(directory, file)).mtime;
@@ -23,6 +23,17 @@ interface TimeRotatingFileSinkOptions extends Omit<FileSinkOptions, "lazy"> {
23
23
  * - `"weekly"`: `YYYY-WW.log` (e.g., `2025-W03.log`)
24
24
  */
25
25
  filename?: (date: Date) => string;
26
+ /**
27
+ * A function that extracts the date from a log filename for cleanup.
28
+ * When this returns `null`, the file is skipped during cleanup.
29
+ *
30
+ * If not specified, cleanup parses the default filename patterns when
31
+ * `filename` is not set. When `filename` is set, cleanup uses each file's
32
+ * modification time and checks that `filename(mtime)` matches the file name.
33
+ *
34
+ * @since 2.3.0
35
+ */
36
+ parseFilename?: (filename: string) => Date | null;
26
37
  /**
27
38
  * The rotation interval. Defaults to `"daily"`.
28
39
  */
@@ -31,8 +42,8 @@ interface TimeRotatingFileSinkOptions extends Omit<FileSinkOptions, "lazy"> {
31
42
  * The maximum age of log files in milliseconds. Files older than this
32
43
  * will be deleted. If not specified, old files are not deleted.
33
44
  *
34
- * When using `getTimeRotatingFileSink()` with `filename` set, cleanup uses
35
- * each file's modification time instead of parsing dates from filenames.
45
+ * When `filename` is set and `parseFilename` is not set, cleanup uses each
46
+ * file's modification time instead of parsing dates from filenames.
36
47
  */
37
48
  maxAgeMs?: number;
38
49
  }
@@ -46,6 +57,16 @@ interface TimeRotatingFileSinkDriver<TFile> extends FileSinkDriver<TFile> {
46
57
  * @returns An array of filenames in the directory.
47
58
  */
48
59
  readdirSync(path: string): string[];
60
+ /**
61
+ * Get file information. This is used for cleanup when `filename` is set and
62
+ * `parseFilename` is not set.
63
+ * @param path A path to the file.
64
+ * @returns File information.
65
+ * @since 2.3.0
66
+ */
67
+ statSync?(path: string): {
68
+ mtime: Date | null;
69
+ };
49
70
  /**
50
71
  * Delete a file.
51
72
  * @param path A path to the file to delete.
@@ -77,6 +98,16 @@ interface AsyncTimeRotatingFileSinkDriver<TFile> extends AsyncFileSinkDriver<TFi
77
98
  * @returns An array of filenames in the directory.
78
99
  */
79
100
  readdirSync(path: string): string[];
101
+ /**
102
+ * Get file information. This is used for cleanup when `filename` is set and
103
+ * `parseFilename` is not set.
104
+ * @param path A path to the file.
105
+ * @returns File information.
106
+ * @since 2.3.0
107
+ */
108
+ statSync?(path: string): {
109
+ mtime: Date | null;
110
+ };
80
111
  /**
81
112
  * Delete a file.
82
113
  * @param path A path to the file to delete.
@@ -1 +1 @@
1
- {"version":3,"file":"timefilesink.d.cts","names":[],"sources":["../src/timefilesink.ts"],"sourcesContent":[],"mappings":";;;;;;;AAeA;AAKiB,KALL,oBAAA,GAMV,QAAA,GAAA,OAAA,GAAA,QAAA;;;;AAkBW,UAnBI,2BAAA,SACP,IAkBG,CAlBE,eAkBF,EAAA,MAAA,CAAA,CAAA;EAAoB;AAlBnB;AAiCd;EAA2C,SAAA,EAAA,MAAA;EAAA;;AACnB;AAiCxB;;;;EAC6B,QAAA,CAAA,EAAA,CAAA,IAAA,EAvDT,IAuDS,EAAA,GAAA,MAAA;;;;aAlDhB;;;;;;;;;;;;;UAeI,0CACP,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAiCR,+CACP,oBAAoB"}
1
+ {"version":3,"file":"timefilesink.d.cts","names":[],"sources":["../src/timefilesink.ts"],"sourcesContent":[],"mappings":";;;;;;;AAeA;AAKiB,KALL,oBAAA,GAMV,QAAA,GAAA,OAAA,GAAA,QAAA;;;;AAyBsC,UA1BvB,2BAAA,SACP,IAyB8B,CAzBzB,eAyByB,EAAA,MAAA,CAAA,CAAA;EAAI;;AAzB9B;EA6CG,SAAA,EAAA,MAAA;EAA0B;;;;AACnB;AA0CxB;;EAAgD,QAClB,CAAA,EAAA,CAAA,IAAA,EA5EV,IA4EU,EAAA,GAAA,MAAA;EAAK;;AAAN;;;;;;;;wCAhEW;;;;aAK3B;;;;;;;;;;;;;UAeI,0CACP,eAAe;;;;;;;;;;;;;;;WAeW;;;;;;;;;;;;;;;;;;;;;;;;;;UA2BnB,+CACP,oBAAoB;;;;;;;;;;;;;;;WAeM"}
@@ -23,6 +23,17 @@ interface TimeRotatingFileSinkOptions extends Omit<FileSinkOptions, "lazy"> {
23
23
  * - `"weekly"`: `YYYY-WW.log` (e.g., `2025-W03.log`)
24
24
  */
25
25
  filename?: (date: Date) => string;
26
+ /**
27
+ * A function that extracts the date from a log filename for cleanup.
28
+ * When this returns `null`, the file is skipped during cleanup.
29
+ *
30
+ * If not specified, cleanup parses the default filename patterns when
31
+ * `filename` is not set. When `filename` is set, cleanup uses each file's
32
+ * modification time and checks that `filename(mtime)` matches the file name.
33
+ *
34
+ * @since 2.3.0
35
+ */
36
+ parseFilename?: (filename: string) => Date | null;
26
37
  /**
27
38
  * The rotation interval. Defaults to `"daily"`.
28
39
  */
@@ -31,8 +42,8 @@ interface TimeRotatingFileSinkOptions extends Omit<FileSinkOptions, "lazy"> {
31
42
  * The maximum age of log files in milliseconds. Files older than this
32
43
  * will be deleted. If not specified, old files are not deleted.
33
44
  *
34
- * When using `getTimeRotatingFileSink()` with `filename` set, cleanup uses
35
- * each file's modification time instead of parsing dates from filenames.
45
+ * When `filename` is set and `parseFilename` is not set, cleanup uses each
46
+ * file's modification time instead of parsing dates from filenames.
36
47
  */
37
48
  maxAgeMs?: number;
38
49
  }
@@ -46,6 +57,16 @@ interface TimeRotatingFileSinkDriver<TFile> extends FileSinkDriver<TFile> {
46
57
  * @returns An array of filenames in the directory.
47
58
  */
48
59
  readdirSync(path: string): string[];
60
+ /**
61
+ * Get file information. This is used for cleanup when `filename` is set and
62
+ * `parseFilename` is not set.
63
+ * @param path A path to the file.
64
+ * @returns File information.
65
+ * @since 2.3.0
66
+ */
67
+ statSync?(path: string): {
68
+ mtime: Date | null;
69
+ };
49
70
  /**
50
71
  * Delete a file.
51
72
  * @param path A path to the file to delete.
@@ -77,6 +98,16 @@ interface AsyncTimeRotatingFileSinkDriver<TFile> extends AsyncFileSinkDriver<TFi
77
98
  * @returns An array of filenames in the directory.
78
99
  */
79
100
  readdirSync(path: string): string[];
101
+ /**
102
+ * Get file information. This is used for cleanup when `filename` is set and
103
+ * `parseFilename` is not set.
104
+ * @param path A path to the file.
105
+ * @returns File information.
106
+ * @since 2.3.0
107
+ */
108
+ statSync?(path: string): {
109
+ mtime: Date | null;
110
+ };
80
111
  /**
81
112
  * Delete a file.
82
113
  * @param path A path to the file to delete.
@@ -1 +1 @@
1
- {"version":3,"file":"timefilesink.d.ts","names":[],"sources":["../src/timefilesink.ts"],"sourcesContent":[],"mappings":";;;;;;;AAeA;AAKiB,KALL,oBAAA,GAMV,QAAA,GAAA,OAAA,GAAA,QAAA;;;;AAkBW,UAnBI,2BAAA,SACP,IAkBG,CAlBE,eAkBF,EAAA,MAAA,CAAA,CAAA;EAAoB;AAlBnB;AAiCd;EAA2C,SAAA,EAAA,MAAA;EAAA;;AACnB;AAiCxB;;;;EAC6B,QAAA,CAAA,EAAA,CAAA,IAAA,EAvDT,IAuDS,EAAA,GAAA,MAAA;;;;aAlDhB;;;;;;;;;;;;;UAeI,0CACP,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAiCR,+CACP,oBAAoB"}
1
+ {"version":3,"file":"timefilesink.d.ts","names":[],"sources":["../src/timefilesink.ts"],"sourcesContent":[],"mappings":";;;;;;;AAeA;AAKiB,KALL,oBAAA,GAMV,QAAA,GAAA,OAAA,GAAA,QAAA;;;;AAyBsC,UA1BvB,2BAAA,SACP,IAyB8B,CAzBzB,eAyByB,EAAA,MAAA,CAAA,CAAA;EAAI;;AAzB9B;EA6CG,SAAA,EAAA,MAAA;EAA0B;;;;AACnB;AA0CxB;;EAAgD,QAClB,CAAA,EAAA,CAAA,IAAA,EA5EV,IA4EU,EAAA,GAAA,MAAA;EAAK;;AAAN;;;;;;;;wCAhEW;;;;aAK3B;;;;;;;;;;;;;UAeI,0CACP,eAAe;;;;;;;;;;;;;;;WAeW;;;;;;;;;;;;;;;;;;;;;;;;;;UA2BnB,+CACP,oBAAoB;;;;;;;;;;;;;;;WAeM"}
@@ -100,6 +100,7 @@ function getBaseTimeRotatingFileSink(options) {
100
100
  const interval = options.interval ?? "daily";
101
101
  const hasCustomFilename = options.filename !== void 0;
102
102
  const filenameGenerator = options.filename ?? getDefaultFilename(interval);
103
+ const parseFilename = options.parseFilename;
103
104
  const maxAgeMs = options.maxAgeMs;
104
105
  const cleanupInterval = maxAgeMs === void 0 ? getRotationIntervalMs(interval) : Math.min(getRotationIntervalMs(interval), maxAgeMs);
105
106
  const bufferSize = options.bufferSize ?? 1024 * 8;
@@ -143,7 +144,8 @@ function getBaseTimeRotatingFileSink(options) {
143
144
  for (const file of files) {
144
145
  if (file === currentFilename) continue;
145
146
  let fileDate = null;
146
- if (hasCustomFilename) {
147
+ if (parseFilename !== void 0) fileDate = parseFilename(file);
148
+ else if (hasCustomFilename) {
147
149
  if (statSync === void 0) continue;
148
150
  try {
149
151
  fileDate = statSync(options.joinPath(directory, file)).mtime;
@@ -1 +1 @@
1
- {"version":3,"file":"timefilesink.js","names":["date: Date","interval: TimeRotationInterval","options: object","file: string","options:\n & TimeRotatingFileSinkOptions\n & (\n | TimeRotatingFileSinkDriver<TFile>\n | AsyncTimeRotatingFileSinkDriver<TFile>\n )","currentFilename: string","currentPath: string","currentRotationKey: string","fd: TFile","lastFlushTimestamp: number","lastCleanupTimestamp: number | undefined","buffer: string","files: string[]","fileDate: Date | null","flushBuffer","sink: Sink & Disposable","record: LogRecord","activeFlush: Promise<void> | null","flushTimer: ReturnType<typeof setInterval> | null","nonBlockingSink: Sink & AsyncDisposable"],"sources":["../src/timefilesink.ts"],"sourcesContent":["import {\n defaultTextFormatter,\n type LogRecord,\n type Sink,\n} from \"@logtape/logtape\";\nimport type {\n AsyncFileSinkDriver,\n FileSinkDriver,\n FileSinkOptions,\n} from \"./filesink.base.ts\";\nimport { markSinkAsImmediate } from \"./snapshot.ts\";\n\n/**\n * The rotation interval for time-based file sinks.\n */\nexport type TimeRotationInterval = \"hourly\" | \"daily\" | \"weekly\";\n\n/**\n * Options for the {@link getBaseTimeRotatingFileSink} function.\n */\nexport interface TimeRotatingFileSinkOptions\n extends Omit<FileSinkOptions, \"lazy\"> {\n /**\n * The directory to write log files to.\n */\n directory: string;\n\n /**\n * A function that generates the filename for the log file based on the date.\n * Default depends on `interval`:\n * - `\"daily\"`: `YYYY-MM-DD.log` (e.g., `2025-01-15.log`)\n * - `\"hourly\"`: `YYYY-MM-DD-HH.log` (e.g., `2025-01-15-09.log`)\n * - `\"weekly\"`: `YYYY-WW.log` (e.g., `2025-W03.log`)\n */\n filename?: (date: Date) => string;\n\n /**\n * The rotation interval. Defaults to `\"daily\"`.\n */\n interval?: TimeRotationInterval;\n\n /**\n * The maximum age of log files in milliseconds. Files older than this\n * will be deleted. If not specified, old files are not deleted.\n *\n * When using `getTimeRotatingFileSink()` with `filename` set, cleanup uses\n * each file's modification time instead of parsing dates from filenames.\n */\n maxAgeMs?: number;\n}\n\n/**\n * A platform-specific time-rotating file sink driver.\n */\nexport interface TimeRotatingFileSinkDriver<TFile>\n extends FileSinkDriver<TFile> {\n /**\n * Read the contents of a directory.\n * @param path A path to the directory.\n * @returns An array of filenames in the directory.\n */\n readdirSync(path: string): string[];\n\n /**\n * Delete a file.\n * @param path A path to the file to delete.\n */\n unlinkSync(path: string): void;\n\n /**\n * Create a directory if it doesn't exist.\n * @param path A path to the directory to create.\n * @param options Options for directory creation.\n */\n mkdirSync(path: string, options?: { recursive?: boolean }): void;\n\n /**\n * Join path segments.\n * @param paths Path segments to join.\n * @returns The joined path.\n */\n joinPath(...paths: string[]): string;\n}\n\n/**\n * A platform-specific async time-rotating file sink driver.\n * @since 2.0.0\n */\nexport interface AsyncTimeRotatingFileSinkDriver<TFile>\n extends AsyncFileSinkDriver<TFile> {\n /**\n * Read the contents of a directory.\n * @param path A path to the directory.\n * @returns An array of filenames in the directory.\n */\n readdirSync(path: string): string[];\n\n /**\n * Delete a file.\n * @param path A path to the file to delete.\n */\n unlinkSync(path: string): void;\n\n /**\n * Create a directory if it doesn't exist.\n * @param path A path to the directory to create.\n * @param options Options for directory creation.\n */\n mkdirSync(path: string, options?: { recursive?: boolean }): void;\n\n /**\n * Join path segments.\n * @param paths Path segments to join.\n * @returns The joined path.\n */\n joinPath(...paths: string[]): string;\n}\n\n/**\n * Get the ISO week number of a date.\n * @param date The date to get the week number of.\n * @returns The ISO week number (1-53).\n */\nexport function getISOWeek(date: Date): number {\n const d = new Date(\n Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()),\n );\n const dayNum = d.getUTCDay() || 7;\n d.setUTCDate(d.getUTCDate() + 4 - dayNum);\n const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));\n return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7);\n}\n\n/**\n * Get the ISO week year of a date. This may differ from the calendar year\n * for dates near the start or end of a year.\n * @param date The date to get the ISO week year of.\n * @returns The ISO week year.\n */\nexport function getISOWeekYear(date: Date): number {\n const d = new Date(\n Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()),\n );\n const dayNum = d.getUTCDay() || 7;\n d.setUTCDate(d.getUTCDate() + 4 - dayNum);\n return d.getUTCFullYear();\n}\n\n/**\n * Get the default filename generator for the given interval.\n * @param interval The rotation interval.\n * @returns A function that generates a filename for a given date.\n */\nexport function getDefaultFilename(\n interval: TimeRotationInterval,\n): (date: Date) => string {\n switch (interval) {\n case \"hourly\":\n return (date: Date): string => {\n const yyyy = date.getFullYear();\n const mm = String(date.getMonth() + 1).padStart(2, \"0\");\n const dd = String(date.getDate()).padStart(2, \"0\");\n const hh = String(date.getHours()).padStart(2, \"0\");\n return `${yyyy}-${mm}-${dd}-${hh}.log`;\n };\n case \"daily\":\n return (date: Date): string => {\n const yyyy = date.getFullYear();\n const mm = String(date.getMonth() + 1).padStart(2, \"0\");\n const dd = String(date.getDate()).padStart(2, \"0\");\n return `${yyyy}-${mm}-${dd}.log`;\n };\n case \"weekly\":\n return (date: Date): string => {\n const yyyy = getISOWeekYear(date);\n const week = getISOWeek(date);\n return `${yyyy}-W${String(week).padStart(2, \"0\")}.log`;\n };\n }\n}\n\n/**\n * Get the rotation key for the given date and interval.\n * The key is used to determine when to rotate to a new file.\n * @param date The date to get the rotation key of.\n * @param interval The rotation interval.\n * @returns A string key that changes when rotation should occur.\n */\nfunction getRotationKey(date: Date, interval: TimeRotationInterval): string {\n switch (interval) {\n case \"hourly\":\n return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}-${date.getHours()}`;\n case \"daily\":\n return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;\n case \"weekly\":\n return `${getISOWeekYear(date)}-${getISOWeek(date)}`;\n }\n}\n\nfunction getRotationIntervalMs(interval: TimeRotationInterval): number {\n switch (interval) {\n case \"hourly\":\n return 60 * 60 * 1000;\n case \"daily\":\n return 24 * 60 * 60 * 1000;\n case \"weekly\":\n return 7 * 24 * 60 * 60 * 1000;\n }\n}\n\ninterface StatSyncDriver {\n statSync(path: string): { mtime: Date | null };\n}\n\nfunction hasStatSyncDriver(options: object): options is StatSyncDriver {\n return \"statSync\" in options && typeof options.statSync === \"function\";\n}\n\nfunction parseDefaultFilename(file: string): Date | null {\n const dateMatch = file.match(\n /^(\\d{4})-(\\d{2})-(\\d{2})(?:-(\\d{2}))?\\.log$/,\n );\n const weekMatch = file.match(/^(\\d{4})-W(\\d{2})\\.log$/);\n\n if (dateMatch) {\n const [, year, month, day, hour] = dateMatch;\n return new Date(\n parseInt(year!, 10),\n parseInt(month!, 10) - 1,\n parseInt(day!, 10),\n hour ? parseInt(hour, 10) : 0,\n );\n }\n\n if (weekMatch) {\n const [, year, week] = weekMatch;\n const jan4 = new Date(parseInt(year!, 10), 0, 4);\n const dayOfWeek = jan4.getDay() || 7;\n const fileDate = new Date(jan4);\n fileDate.setDate(\n jan4.getDate() - dayOfWeek + 1 + (parseInt(week!, 10) - 1) * 7,\n );\n return fileDate;\n }\n\n return null;\n}\n\n/**\n * Get a platform-independent time-rotating file sink.\n *\n * This sink writes log records to a file in a directory, rotating to a new\n * file based on time intervals. The filename is generated based on the\n * current date/time and the configured interval.\n *\n * @template TFile The type of the file descriptor.\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. If `nonBlocking` is\n * enabled, returns a sink that also implements {@link AsyncDisposable}.\n */\nexport function getBaseTimeRotatingFileSink<TFile>(\n options: TimeRotatingFileSinkOptions & TimeRotatingFileSinkDriver<TFile>,\n): Sink & Disposable;\nexport function getBaseTimeRotatingFileSink<TFile>(\n options: TimeRotatingFileSinkOptions & AsyncTimeRotatingFileSinkDriver<TFile>,\n): Sink & AsyncDisposable;\nexport function getBaseTimeRotatingFileSink<TFile>(\n options:\n & TimeRotatingFileSinkOptions\n & (\n | TimeRotatingFileSinkDriver<TFile>\n | AsyncTimeRotatingFileSinkDriver<TFile>\n ),\n): Sink & (Disposable | AsyncDisposable) {\n const formatter = options.formatter ?? defaultTextFormatter;\n const encoder = options.encoder ?? new TextEncoder();\n const interval = options.interval ?? \"daily\";\n const hasCustomFilename = options.filename !== undefined;\n const filenameGenerator = options.filename ?? getDefaultFilename(interval);\n const maxAgeMs = options.maxAgeMs;\n const cleanupInterval = maxAgeMs === undefined\n ? getRotationIntervalMs(interval)\n : Math.min(getRotationIntervalMs(interval), maxAgeMs);\n const bufferSize = options.bufferSize ?? 1024 * 8;\n const flushInterval = options.flushInterval ?? 5000;\n const directory = options.directory;\n const statSync = hasStatSyncDriver(options) ? options.statSync : undefined;\n\n // Ensure directory exists\n try {\n options.mkdirSync(directory, { recursive: true });\n } catch {\n // Directory might already exist\n }\n\n let currentFilename: string = filenameGenerator(new Date());\n let currentPath: string = options.joinPath(directory, currentFilename);\n let currentRotationKey: string = getRotationKey(new Date(), interval);\n let fd: TFile = options.openSync(currentPath);\n let lastFlushTimestamp: number = Date.now();\n let lastCleanupTimestamp: number | undefined;\n let buffer: string = \"\";\n\n function shouldRotate(): boolean {\n const now = new Date();\n const newKey = getRotationKey(now, interval);\n return newKey !== currentRotationKey;\n }\n\n function performRotation(): void {\n options.closeSync(fd);\n const now = new Date();\n currentFilename = filenameGenerator(now);\n currentPath = options.joinPath(directory, currentFilename);\n currentRotationKey = getRotationKey(now, interval);\n fd = options.openSync(currentPath);\n }\n\n function cleanupOldFiles(): void {\n if (maxAgeMs === undefined) return;\n\n const now = Date.now();\n if (\n lastCleanupTimestamp !== undefined && cleanupInterval > 0 &&\n now - lastCleanupTimestamp < cleanupInterval\n ) {\n return;\n }\n lastCleanupTimestamp = now;\n\n let files: string[];\n try {\n files = options.readdirSync(directory);\n } catch {\n return;\n }\n\n for (const file of files) {\n if (file === currentFilename) continue;\n\n let fileDate: Date | null = null;\n if (hasCustomFilename) {\n if (statSync === undefined) continue;\n try {\n fileDate = statSync(options.joinPath(directory, file)).mtime;\n } catch {\n continue;\n }\n if (fileDate === null || filenameGenerator(fileDate) !== file) {\n continue;\n }\n } else {\n if (!file.endsWith(\".log\")) continue;\n fileDate = parseDefaultFilename(file);\n }\n\n if (fileDate && now - fileDate.getTime() > maxAgeMs) {\n const filePath = options.joinPath(directory, file);\n try {\n options.unlinkSync(filePath);\n } catch {\n // Ignore errors when deleting files\n }\n }\n }\n }\n\n if (!options.nonBlocking) {\n // Blocking mode implementation\n // deno-lint-ignore no-inner-declarations\n function flushBuffer(): void {\n if (buffer.length > 0) {\n if (shouldRotate()) {\n performRotation();\n }\n const bytes = encoder.encode(buffer);\n buffer = \"\";\n options.writeSync(fd, bytes);\n options.flushSync(fd);\n lastFlushTimestamp = Date.now();\n cleanupOldFiles();\n }\n }\n\n const sink: Sink & Disposable = (record: LogRecord) => {\n buffer += formatter(record);\n\n const shouldFlushBySize = buffer.length >= bufferSize;\n const shouldFlushByTime = flushInterval > 0 &&\n (record.timestamp - lastFlushTimestamp) >= flushInterval;\n\n if (shouldFlushBySize || shouldFlushByTime) {\n flushBuffer();\n }\n };\n\n sink[Symbol.dispose] = () => {\n flushBuffer();\n options.closeSync(fd);\n };\n\n return markSinkAsImmediate(sink);\n }\n\n // Non-blocking mode implementation\n const asyncOptions = options as AsyncTimeRotatingFileSinkDriver<TFile>;\n let disposed = false;\n let activeFlush: Promise<void> | null = null;\n let flushTimer: ReturnType<typeof setInterval> | null = null;\n\n async function flushBuffer(): Promise<void> {\n if (buffer.length === 0) return;\n\n if (shouldRotate()) {\n performRotation();\n }\n\n const data = buffer;\n buffer = \"\";\n try {\n const bytes = encoder.encode(data);\n asyncOptions.writeSync(fd, bytes);\n await asyncOptions.flush(fd);\n lastFlushTimestamp = Date.now();\n cleanupOldFiles();\n } catch {\n // Silently ignore errors in non-blocking mode\n }\n }\n\n function scheduleFlush(): void {\n if (activeFlush || disposed) return;\n\n activeFlush = flushBuffer().finally(() => {\n activeFlush = null;\n });\n }\n\n function startFlushTimer(): void {\n if (flushTimer !== null || disposed) return;\n\n flushTimer = setInterval(() => {\n scheduleFlush();\n }, flushInterval);\n }\n\n const nonBlockingSink: Sink & AsyncDisposable = (record: LogRecord) => {\n if (disposed) return;\n buffer += formatter(record);\n\n const shouldFlushBySize = buffer.length >= bufferSize;\n const shouldFlushByTime = flushInterval > 0 &&\n (record.timestamp - lastFlushTimestamp) >= flushInterval;\n\n if (shouldFlushBySize || shouldFlushByTime) {\n scheduleFlush();\n } else if (flushTimer === null && flushInterval > 0) {\n startFlushTimer();\n }\n };\n\n nonBlockingSink[Symbol.asyncDispose] = async () => {\n disposed = true;\n if (flushTimer !== null) {\n clearInterval(flushTimer);\n flushTimer = null;\n }\n await flushBuffer();\n try {\n await asyncOptions.close(fd);\n } catch {\n // Writer might already be closed or errored\n }\n };\n\n return markSinkAsImmediate(nonBlockingSink);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"timefilesink.js","names":["date: Date","interval: TimeRotationInterval","options: object","file: string","options:\n & TimeRotatingFileSinkOptions\n & (\n | TimeRotatingFileSinkDriver<TFile>\n | AsyncTimeRotatingFileSinkDriver<TFile>\n )","currentFilename: string","currentPath: string","currentRotationKey: string","fd: TFile","lastFlushTimestamp: number","lastCleanupTimestamp: number | undefined","buffer: string","files: string[]","fileDate: Date | null","flushBuffer","sink: Sink & Disposable","record: LogRecord","activeFlush: Promise<void> | null","flushTimer: ReturnType<typeof setInterval> | null","nonBlockingSink: Sink & AsyncDisposable"],"sources":["../src/timefilesink.ts"],"sourcesContent":["import {\n defaultTextFormatter,\n type LogRecord,\n type Sink,\n} from \"@logtape/logtape\";\nimport type {\n AsyncFileSinkDriver,\n FileSinkDriver,\n FileSinkOptions,\n} from \"./filesink.base.ts\";\nimport { markSinkAsImmediate } from \"./snapshot.ts\";\n\n/**\n * The rotation interval for time-based file sinks.\n */\nexport type TimeRotationInterval = \"hourly\" | \"daily\" | \"weekly\";\n\n/**\n * Options for the {@link getBaseTimeRotatingFileSink} function.\n */\nexport interface TimeRotatingFileSinkOptions\n extends Omit<FileSinkOptions, \"lazy\"> {\n /**\n * The directory to write log files to.\n */\n directory: string;\n\n /**\n * A function that generates the filename for the log file based on the date.\n * Default depends on `interval`:\n * - `\"daily\"`: `YYYY-MM-DD.log` (e.g., `2025-01-15.log`)\n * - `\"hourly\"`: `YYYY-MM-DD-HH.log` (e.g., `2025-01-15-09.log`)\n * - `\"weekly\"`: `YYYY-WW.log` (e.g., `2025-W03.log`)\n */\n filename?: (date: Date) => string;\n\n /**\n * A function that extracts the date from a log filename for cleanup.\n * When this returns `null`, the file is skipped during cleanup.\n *\n * If not specified, cleanup parses the default filename patterns when\n * `filename` is not set. When `filename` is set, cleanup uses each file's\n * modification time and checks that `filename(mtime)` matches the file name.\n *\n * @since 2.3.0\n */\n parseFilename?: (filename: string) => Date | null;\n\n /**\n * The rotation interval. Defaults to `\"daily\"`.\n */\n interval?: TimeRotationInterval;\n\n /**\n * The maximum age of log files in milliseconds. Files older than this\n * will be deleted. If not specified, old files are not deleted.\n *\n * When `filename` is set and `parseFilename` is not set, cleanup uses each\n * file's modification time instead of parsing dates from filenames.\n */\n maxAgeMs?: number;\n}\n\n/**\n * A platform-specific time-rotating file sink driver.\n */\nexport interface TimeRotatingFileSinkDriver<TFile>\n extends FileSinkDriver<TFile> {\n /**\n * Read the contents of a directory.\n * @param path A path to the directory.\n * @returns An array of filenames in the directory.\n */\n readdirSync(path: string): string[];\n\n /**\n * Get file information. This is used for cleanup when `filename` is set and\n * `parseFilename` is not set.\n * @param path A path to the file.\n * @returns File information.\n * @since 2.3.0\n */\n statSync?(path: string): { mtime: Date | null };\n\n /**\n * Delete a file.\n * @param path A path to the file to delete.\n */\n unlinkSync(path: string): void;\n\n /**\n * Create a directory if it doesn't exist.\n * @param path A path to the directory to create.\n * @param options Options for directory creation.\n */\n mkdirSync(path: string, options?: { recursive?: boolean }): void;\n\n /**\n * Join path segments.\n * @param paths Path segments to join.\n * @returns The joined path.\n */\n joinPath(...paths: string[]): string;\n}\n\n/**\n * A platform-specific async time-rotating file sink driver.\n * @since 2.0.0\n */\nexport interface AsyncTimeRotatingFileSinkDriver<TFile>\n extends AsyncFileSinkDriver<TFile> {\n /**\n * Read the contents of a directory.\n * @param path A path to the directory.\n * @returns An array of filenames in the directory.\n */\n readdirSync(path: string): string[];\n\n /**\n * Get file information. This is used for cleanup when `filename` is set and\n * `parseFilename` is not set.\n * @param path A path to the file.\n * @returns File information.\n * @since 2.3.0\n */\n statSync?(path: string): { mtime: Date | null };\n\n /**\n * Delete a file.\n * @param path A path to the file to delete.\n */\n unlinkSync(path: string): void;\n\n /**\n * Create a directory if it doesn't exist.\n * @param path A path to the directory to create.\n * @param options Options for directory creation.\n */\n mkdirSync(path: string, options?: { recursive?: boolean }): void;\n\n /**\n * Join path segments.\n * @param paths Path segments to join.\n * @returns The joined path.\n */\n joinPath(...paths: string[]): string;\n}\n\n/**\n * Get the ISO week number of a date.\n * @param date The date to get the week number of.\n * @returns The ISO week number (1-53).\n */\nexport function getISOWeek(date: Date): number {\n const d = new Date(\n Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()),\n );\n const dayNum = d.getUTCDay() || 7;\n d.setUTCDate(d.getUTCDate() + 4 - dayNum);\n const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));\n return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7);\n}\n\n/**\n * Get the ISO week year of a date. This may differ from the calendar year\n * for dates near the start or end of a year.\n * @param date The date to get the ISO week year of.\n * @returns The ISO week year.\n */\nexport function getISOWeekYear(date: Date): number {\n const d = new Date(\n Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()),\n );\n const dayNum = d.getUTCDay() || 7;\n d.setUTCDate(d.getUTCDate() + 4 - dayNum);\n return d.getUTCFullYear();\n}\n\n/**\n * Get the default filename generator for the given interval.\n * @param interval The rotation interval.\n * @returns A function that generates a filename for a given date.\n */\nexport function getDefaultFilename(\n interval: TimeRotationInterval,\n): (date: Date) => string {\n switch (interval) {\n case \"hourly\":\n return (date: Date): string => {\n const yyyy = date.getFullYear();\n const mm = String(date.getMonth() + 1).padStart(2, \"0\");\n const dd = String(date.getDate()).padStart(2, \"0\");\n const hh = String(date.getHours()).padStart(2, \"0\");\n return `${yyyy}-${mm}-${dd}-${hh}.log`;\n };\n case \"daily\":\n return (date: Date): string => {\n const yyyy = date.getFullYear();\n const mm = String(date.getMonth() + 1).padStart(2, \"0\");\n const dd = String(date.getDate()).padStart(2, \"0\");\n return `${yyyy}-${mm}-${dd}.log`;\n };\n case \"weekly\":\n return (date: Date): string => {\n const yyyy = getISOWeekYear(date);\n const week = getISOWeek(date);\n return `${yyyy}-W${String(week).padStart(2, \"0\")}.log`;\n };\n }\n}\n\n/**\n * Get the rotation key for the given date and interval.\n * The key is used to determine when to rotate to a new file.\n * @param date The date to get the rotation key of.\n * @param interval The rotation interval.\n * @returns A string key that changes when rotation should occur.\n */\nfunction getRotationKey(date: Date, interval: TimeRotationInterval): string {\n switch (interval) {\n case \"hourly\":\n return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}-${date.getHours()}`;\n case \"daily\":\n return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;\n case \"weekly\":\n return `${getISOWeekYear(date)}-${getISOWeek(date)}`;\n }\n}\n\nfunction getRotationIntervalMs(interval: TimeRotationInterval): number {\n switch (interval) {\n case \"hourly\":\n return 60 * 60 * 1000;\n case \"daily\":\n return 24 * 60 * 60 * 1000;\n case \"weekly\":\n return 7 * 24 * 60 * 60 * 1000;\n }\n}\n\ninterface StatSyncDriver {\n statSync(path: string): { mtime: Date | null };\n}\n\nfunction hasStatSyncDriver(options: object): options is StatSyncDriver {\n return \"statSync\" in options && typeof options.statSync === \"function\";\n}\n\nfunction parseDefaultFilename(file: string): Date | null {\n const dateMatch = file.match(\n /^(\\d{4})-(\\d{2})-(\\d{2})(?:-(\\d{2}))?\\.log$/,\n );\n const weekMatch = file.match(/^(\\d{4})-W(\\d{2})\\.log$/);\n\n if (dateMatch) {\n const [, year, month, day, hour] = dateMatch;\n return new Date(\n parseInt(year!, 10),\n parseInt(month!, 10) - 1,\n parseInt(day!, 10),\n hour ? parseInt(hour, 10) : 0,\n );\n }\n\n if (weekMatch) {\n const [, year, week] = weekMatch;\n const jan4 = new Date(parseInt(year!, 10), 0, 4);\n const dayOfWeek = jan4.getDay() || 7;\n const fileDate = new Date(jan4);\n fileDate.setDate(\n jan4.getDate() - dayOfWeek + 1 + (parseInt(week!, 10) - 1) * 7,\n );\n return fileDate;\n }\n\n return null;\n}\n\n/**\n * Get a platform-independent time-rotating file sink.\n *\n * This sink writes log records to a file in a directory, rotating to a new\n * file based on time intervals. The filename is generated based on the\n * current date/time and the configured interval.\n *\n * @template TFile The type of the file descriptor.\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. If `nonBlocking` is\n * enabled, returns a sink that also implements {@link AsyncDisposable}.\n */\nexport function getBaseTimeRotatingFileSink<TFile>(\n options: TimeRotatingFileSinkOptions & TimeRotatingFileSinkDriver<TFile>,\n): Sink & Disposable;\nexport function getBaseTimeRotatingFileSink<TFile>(\n options: TimeRotatingFileSinkOptions & AsyncTimeRotatingFileSinkDriver<TFile>,\n): Sink & AsyncDisposable;\nexport function getBaseTimeRotatingFileSink<TFile>(\n options:\n & TimeRotatingFileSinkOptions\n & (\n | TimeRotatingFileSinkDriver<TFile>\n | AsyncTimeRotatingFileSinkDriver<TFile>\n ),\n): Sink & (Disposable | AsyncDisposable) {\n const formatter = options.formatter ?? defaultTextFormatter;\n const encoder = options.encoder ?? new TextEncoder();\n const interval = options.interval ?? \"daily\";\n const hasCustomFilename = options.filename !== undefined;\n const filenameGenerator = options.filename ?? getDefaultFilename(interval);\n const parseFilename = options.parseFilename;\n const maxAgeMs = options.maxAgeMs;\n const cleanupInterval = maxAgeMs === undefined\n ? getRotationIntervalMs(interval)\n : Math.min(getRotationIntervalMs(interval), maxAgeMs);\n const bufferSize = options.bufferSize ?? 1024 * 8;\n const flushInterval = options.flushInterval ?? 5000;\n const directory = options.directory;\n const statSync = hasStatSyncDriver(options) ? options.statSync : undefined;\n\n // Ensure directory exists\n try {\n options.mkdirSync(directory, { recursive: true });\n } catch {\n // Directory might already exist\n }\n\n let currentFilename: string = filenameGenerator(new Date());\n let currentPath: string = options.joinPath(directory, currentFilename);\n let currentRotationKey: string = getRotationKey(new Date(), interval);\n let fd: TFile = options.openSync(currentPath);\n let lastFlushTimestamp: number = Date.now();\n let lastCleanupTimestamp: number | undefined;\n let buffer: string = \"\";\n\n function shouldRotate(): boolean {\n const now = new Date();\n const newKey = getRotationKey(now, interval);\n return newKey !== currentRotationKey;\n }\n\n function performRotation(): void {\n options.closeSync(fd);\n const now = new Date();\n currentFilename = filenameGenerator(now);\n currentPath = options.joinPath(directory, currentFilename);\n currentRotationKey = getRotationKey(now, interval);\n fd = options.openSync(currentPath);\n }\n\n function cleanupOldFiles(): void {\n if (maxAgeMs === undefined) return;\n\n const now = Date.now();\n if (\n lastCleanupTimestamp !== undefined && cleanupInterval > 0 &&\n now - lastCleanupTimestamp < cleanupInterval\n ) {\n return;\n }\n lastCleanupTimestamp = now;\n\n let files: string[];\n try {\n files = options.readdirSync(directory);\n } catch {\n return;\n }\n\n for (const file of files) {\n if (file === currentFilename) continue;\n\n let fileDate: Date | null = null;\n if (parseFilename !== undefined) {\n fileDate = parseFilename(file);\n } else if (hasCustomFilename) {\n if (statSync === undefined) continue;\n try {\n fileDate = statSync(options.joinPath(directory, file)).mtime;\n } catch {\n continue;\n }\n if (fileDate === null || filenameGenerator(fileDate) !== file) {\n continue;\n }\n } else {\n if (!file.endsWith(\".log\")) continue;\n fileDate = parseDefaultFilename(file);\n }\n\n if (fileDate && now - fileDate.getTime() > maxAgeMs) {\n const filePath = options.joinPath(directory, file);\n try {\n options.unlinkSync(filePath);\n } catch {\n // Ignore errors when deleting files\n }\n }\n }\n }\n\n if (!options.nonBlocking) {\n // Blocking mode implementation\n // deno-lint-ignore no-inner-declarations\n function flushBuffer(): void {\n if (buffer.length > 0) {\n if (shouldRotate()) {\n performRotation();\n }\n const bytes = encoder.encode(buffer);\n buffer = \"\";\n options.writeSync(fd, bytes);\n options.flushSync(fd);\n lastFlushTimestamp = Date.now();\n cleanupOldFiles();\n }\n }\n\n const sink: Sink & Disposable = (record: LogRecord) => {\n buffer += formatter(record);\n\n const shouldFlushBySize = buffer.length >= bufferSize;\n const shouldFlushByTime = flushInterval > 0 &&\n (record.timestamp - lastFlushTimestamp) >= flushInterval;\n\n if (shouldFlushBySize || shouldFlushByTime) {\n flushBuffer();\n }\n };\n\n sink[Symbol.dispose] = () => {\n flushBuffer();\n options.closeSync(fd);\n };\n\n return markSinkAsImmediate(sink);\n }\n\n // Non-blocking mode implementation\n const asyncOptions = options as AsyncTimeRotatingFileSinkDriver<TFile>;\n let disposed = false;\n let activeFlush: Promise<void> | null = null;\n let flushTimer: ReturnType<typeof setInterval> | null = null;\n\n async function flushBuffer(): Promise<void> {\n if (buffer.length === 0) return;\n\n if (shouldRotate()) {\n performRotation();\n }\n\n const data = buffer;\n buffer = \"\";\n try {\n const bytes = encoder.encode(data);\n asyncOptions.writeSync(fd, bytes);\n await asyncOptions.flush(fd);\n lastFlushTimestamp = Date.now();\n cleanupOldFiles();\n } catch {\n // Silently ignore errors in non-blocking mode\n }\n }\n\n function scheduleFlush(): void {\n if (activeFlush || disposed) return;\n\n activeFlush = flushBuffer().finally(() => {\n activeFlush = null;\n });\n }\n\n function startFlushTimer(): void {\n if (flushTimer !== null || disposed) return;\n\n flushTimer = setInterval(() => {\n scheduleFlush();\n }, flushInterval);\n }\n\n const nonBlockingSink: Sink & AsyncDisposable = (record: LogRecord) => {\n if (disposed) return;\n buffer += formatter(record);\n\n const shouldFlushBySize = buffer.length >= bufferSize;\n const shouldFlushByTime = flushInterval > 0 &&\n (record.timestamp - lastFlushTimestamp) >= flushInterval;\n\n if (shouldFlushBySize || shouldFlushByTime) {\n scheduleFlush();\n } else if (flushTimer === null && flushInterval > 0) {\n startFlushTimer();\n }\n };\n\n nonBlockingSink[Symbol.asyncDispose] = async () => {\n disposed = true;\n if (flushTimer !== null) {\n clearInterval(flushTimer);\n flushTimer = null;\n }\n await flushBuffer();\n try {\n await asyncOptions.close(fd);\n } catch {\n // Writer might already be closed or errored\n }\n };\n\n return markSinkAsImmediate(nonBlockingSink);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logtape/file",
3
- "version": "2.2.2",
3
+ "version": "2.3.0-dev.783+cb92bb81",
4
4
  "description": "File sink and rotating file sink for LogTape",
5
5
  "keywords": [
6
6
  "logging",
@@ -60,7 +60,7 @@
60
60
  "dist/"
61
61
  ],
62
62
  "peerDependencies": {
63
- "@logtape/logtape": "^2.2.2"
63
+ "@logtape/logtape": "^2.3.0-dev.783+cb92bb81"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@alinea/suite": "^0.6.3",
@@ -1,74 +0,0 @@
1
- import { StreamSinkOptions } from "@logtape/logtape";
2
-
3
- //#region dist/filesink.base.d.ts
4
-
5
- //#region src/filesink.base.d.ts
6
- /**
7
- * Options for the {@link getBaseFileSink} function.
8
- */
9
- interface FileSinkOptions extends StreamSinkOptions {
10
- /**
11
- * If `true`, the file is not opened until the first write. Defaults to `false`.
12
- */
13
- lazy?: boolean;
14
- /**
15
- * The size of the buffer to use when writing to the file. If not specified,
16
- * a default buffer size will be used. If it is less or equal to 0,
17
- * the file will be written directly without buffering.
18
- * @default 8192
19
- * @since 0.12.0
20
- */
21
- bufferSize?: number;
22
- /**
23
- * The maximum time interval in milliseconds between flushes. If this time
24
- * passes since the last flush, the buffer will be flushed regardless of size.
25
- * This helps prevent log loss during unexpected process termination.
26
- * @default 5000
27
- * @since 0.12.0
28
- */
29
- flushInterval?: number;
30
- /**
31
- * Enable non-blocking mode with background flushing.
32
- * When enabled, flush operations are performed asynchronously to prevent
33
- * blocking the main thread during file I/O operations.
34
- *
35
- * @default `false`
36
- * @since 1.0.0
37
- */
38
- nonBlocking?: boolean;
39
- }
40
- /**
41
- * A platform-specific file sink driver.
42
- * @template TFile The type of the file descriptor.
43
- */
44
-
45
- /**
46
- * Get a platform-independent file sink.
47
- *
48
- * @template TFile The type of the file descriptor.
49
- * @param path A path to the file to write to.
50
- * @param options The options for the sink and the file driver.
51
- * @returns A sink that writes to the file. The sink is also a disposable
52
- * object that closes the file when disposed. If `nonBlocking` is enabled,
53
- * returns a sink that also implements {@link AsyncDisposable}.
54
- */
55
-
56
- /**
57
- * Options for the {@link getBaseRotatingFileSink} function.
58
- */
59
- interface RotatingFileSinkOptions extends Omit<FileSinkOptions, "lazy"> {
60
- /**
61
- * The maximum bytes of the file before it is rotated. 1 MiB by default.
62
- */
63
- maxSize?: number;
64
- /**
65
- * The maximum number of files to keep. 5 by default.
66
- */
67
- maxFiles?: number;
68
- }
69
- /**
70
- * A platform-specific rotating file sink driver.
71
- */
72
- //#endregion
73
- export { FileSinkOptions, RotatingFileSinkOptions };
74
- //# sourceMappingURL=filesink.base.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filesink.base.d.cts","names":["Sink","StreamSinkOptions","FileSinkOptions","FileSinkDriver","TFile","Uint8Array","AsyncFileSinkDriver","Promise","RotatingFileSinkOptions","Omit","RotatingFileSinkDriver","AsyncRotatingFileSinkDriver"],"sources":["../filesink.base.d.ts"],"sourcesContent":["import { Sink, StreamSinkOptions } from \"@logtape/logtape\";\n\n//#region src/filesink.base.d.ts\n\n/**\n * Options for the {@link getBaseFileSink} function.\n */\ninterface FileSinkOptions extends StreamSinkOptions {\n /**\n * If `true`, the file is not opened until the first write. Defaults to `false`.\n */\n lazy?: boolean;\n /**\n * The size of the buffer to use when writing to the file. If not specified,\n * a default buffer size will be used. If it is less or equal to 0,\n * the file will be written directly without buffering.\n * @default 8192\n * @since 0.12.0\n */\n bufferSize?: number;\n /**\n * The maximum time interval in milliseconds between flushes. If this time\n * passes since the last flush, the buffer will be flushed regardless of size.\n * This helps prevent log loss during unexpected process termination.\n * @default 5000\n * @since 0.12.0\n */\n flushInterval?: number;\n /**\n * Enable non-blocking mode with background flushing.\n * When enabled, flush operations are performed asynchronously to prevent\n * blocking the main thread during file I/O operations.\n *\n * @default `false`\n * @since 1.0.0\n */\n nonBlocking?: boolean;\n}\n/**\n * A platform-specific file sink driver.\n * @template TFile The type of the file descriptor.\n */\ninterface FileSinkDriver<TFile> {\n /**\n * Open a file for appending and return a file descriptor.\n * @param path A path to the file to open.\n */\n openSync(path: string): TFile;\n /**\n * Write a chunk of data to the file.\n * @param fd The file descriptor.\n * @param chunk The data to write.\n */\n writeSync(fd: TFile, chunk: Uint8Array): void;\n /**\n * Write multiple chunks of data to the file in a single operation.\n * This is optional - if not implemented, falls back to multiple writeSync calls.\n * @param fd The file descriptor.\n * @param chunks Array of data chunks to write.\n */\n writeManySync?(fd: TFile, chunks: Uint8Array[]): void;\n /**\n * Flush the file to ensure that all data is written to the disk.\n * @param fd The file descriptor.\n */\n flushSync(fd: TFile): void;\n /**\n * Close the file.\n * @param fd The file descriptor.\n */\n closeSync(fd: TFile): void;\n}\n/**\n * A platform-specific async file sink driver.\n * @template TFile The type of the file descriptor.\n * @since 1.0.0\n */\ninterface AsyncFileSinkDriver<TFile> extends FileSinkDriver<TFile> {\n /**\n * Asynchronously write multiple chunks of data to the file in a single operation.\n * This is optional - if not implemented, falls back to multiple writeSync calls.\n * @param fd The file descriptor.\n * @param chunks Array of data chunks to write.\n */\n writeMany?(fd: TFile, chunks: Uint8Array[]): Promise<void>;\n /**\n * Asynchronously flush the file to ensure that all data is written to the disk.\n * @param fd The file descriptor.\n */\n flush(fd: TFile): Promise<void>;\n /**\n * Asynchronously close the file.\n * @param fd The file descriptor.\n */\n close(fd: TFile): Promise<void>;\n}\n/**\n * Get a platform-independent file sink.\n *\n * @template TFile The type of the file descriptor.\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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\n\n/**\n * Options for the {@link getBaseRotatingFileSink} function.\n */\ninterface RotatingFileSinkOptions extends Omit<FileSinkOptions, \"lazy\"> {\n /**\n * The maximum bytes of the file before it is rotated. 1 MiB by default.\n */\n maxSize?: number;\n /**\n * The maximum number of files to keep. 5 by default.\n */\n maxFiles?: number;\n}\n/**\n * A platform-specific rotating file sink driver.\n */\ninterface RotatingFileSinkDriver<TFile> extends FileSinkDriver<TFile> {\n /**\n * Get the size of the file.\n * @param path A path to the file.\n * @returns The `size` of the file in bytes, in an object.\n */\n statSync(path: string): {\n size: number;\n };\n /**\n * Rename a file.\n * @param oldPath A path to the file to rename.\n * @param newPath A path to be renamed to.\n */\n renameSync(oldPath: string, newPath: string): void;\n /**\n * Delete a file.\n * @param path A path to the file to delete.\n */\n unlinkSync?(path: string): void;\n}\n/**\n * A platform-specific async rotating file sink driver.\n * @since 1.0.0\n */\ninterface AsyncRotatingFileSinkDriver<TFile> extends AsyncFileSinkDriver<TFile> {\n /**\n * Get the size of the file.\n * @param path A path to the file.\n * @returns The `size` of the file in bytes, in an object.\n */\n statSync(path: string): {\n size: number;\n };\n /**\n * Rename a file.\n * @param oldPath A path to the file to rename.\n * @param newPath A path to be renamed to.\n */\n renameSync(oldPath: string, newPath: string): void;\n /**\n * Delete a file.\n * @param path A path to the file to delete.\n */\n unlinkSync?(path: string): void;\n}\n/**\n * Get a platform-independent 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 * @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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\n//#endregion\nexport { AsyncFileSinkDriver, AsyncRotatingFileSinkDriver, FileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions };\n//# sourceMappingURL=filesink.base.d.ts.map"],"mappings":";;;;;AA6E2D;;;UAtEjDE,eAAAA,SAAwBD,iBAuGQQ,CAAAA;EAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAApCD,uBAAAA,SAAgCC,KAAKP"}
@@ -1,65 +0,0 @@
1
- import { FileSinkOptions, RotatingFileSinkOptions } from "./filesink.base.cjs";
2
- import { TimeRotatingFileSinkOptions } from "./timefilesink.cjs";
3
- import { Sink } from "@logtape/logtape";
4
-
5
- //#region dist/filesink.node.d.ts
6
-
7
- /**
8
- * Get a file sink.
9
- *
10
- * Note that this function is unavailable in the browser.
11
- *
12
- * @param path A path to the file to write to.
13
- * @param options The options for the sink.
14
- * @returns A sink that writes to the file. The sink is also a disposable
15
- * object that closes the file when disposed. If `nonBlocking` is enabled,
16
- * returns a sink that also implements {@link AsyncDisposable}.
17
- */
18
- declare function getFileSink(path: string, options?: FileSinkOptions): Sink & Disposable;
19
- declare function getFileSink(path: string, options: FileSinkOptions & {
20
- nonBlocking: true;
21
- }): Sink & AsyncDisposable;
22
- /**
23
- * Get a rotating file sink.
24
- *
25
- * This sink writes log records to a file, and rotates the file when it reaches
26
- * the `maxSize`. The rotated files are named with the original file name
27
- * followed by a dot and a number, starting from 1. The number is incremented
28
- * for each rotation, and the maximum number of files to keep is `maxFiles`.
29
- *
30
- * Note that this function is unavailable in the browser.
31
- *
32
- * @param path A path to the file to write to.
33
- * @param options The options for the sink and the file driver.
34
- * @returns A sink that writes to the file. The sink is also a disposable
35
- * object that closes the file when disposed. If `nonBlocking` is enabled,
36
- * returns a sink that also implements {@link AsyncDisposable}.
37
- */
38
- declare function getRotatingFileSink(path: string, options?: RotatingFileSinkOptions): Sink & Disposable;
39
- declare function getRotatingFileSink(path: string, options: RotatingFileSinkOptions & {
40
- nonBlocking: true;
41
- }): Sink & AsyncDisposable;
42
- /**
43
- * Get a time-rotating file sink.
44
- *
45
- * This sink writes log records to a file in a directory, rotating to a new
46
- * file based on time intervals. The filename is generated based on the
47
- * current date/time and the configured interval.
48
- *
49
- * Note that this function is unavailable in the browser.
50
- *
51
- * @param options The options for the sink.
52
- * @returns A sink that writes to the file. The sink is also a disposable
53
- * object that closes the file when disposed. If `nonBlocking` is
54
- * enabled, returns a sink that also implements {@link AsyncDisposable}.
55
- * @since 2.0.0
56
- */
57
- declare function getTimeRotatingFileSink(options: TimeRotatingFileSinkOptions): Sink & Disposable;
58
- declare function getTimeRotatingFileSink(options: TimeRotatingFileSinkOptions & {
59
- nonBlocking: true;
60
- }): Sink & AsyncDisposable;
61
- //# sourceMappingURL=filesink.node.d.ts.map
62
- //#endregion
63
- //#endregion
64
- export { getFileSink, getRotatingFileSink, getTimeRotatingFileSink };
65
- //# sourceMappingURL=filesink.node.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filesink.node.d.cts","names":["AsyncRotatingFileSinkDriver","FileSinkOptions","RotatingFileSinkDriver","RotatingFileSinkOptions","AsyncTimeRotatingFileSinkDriver","TimeRotatingFileSinkDriver","TimeRotatingFileSinkOptions","Sink","nodeDriver","nodeAsyncDriver","nodeTimeDriver","nodeAsyncTimeDriver","getFileSink","Disposable","AsyncDisposable","getRotatingFileSink","getTimeRotatingFileSink"],"sources":["../filesink.node.d.ts"],"sourcesContent":["import { AsyncRotatingFileSinkDriver, FileSinkOptions, RotatingFileSinkDriver, RotatingFileSinkOptions } from \"./filesink.base.js\";\nimport { AsyncTimeRotatingFileSinkDriver, TimeRotatingFileSinkDriver, TimeRotatingFileSinkOptions } from \"./timefilesink.js\";\nimport { Sink } from \"@logtape/logtape\";\n\n//#region src/filesink.node.d.ts\n\n/**\n * A Node.js-specific file sink driver.\n */\ndeclare const nodeDriver: RotatingFileSinkDriver<number | void>;\n/**\n * A Node.js-specific async file sink driver.\n * @since 1.0.0\n */\ndeclare const nodeAsyncDriver: AsyncRotatingFileSinkDriver<number | void>;\n/**\n * A Node.js-specific time-rotating file sink driver.\n * @since 2.0.0\n */\ndeclare const nodeTimeDriver: TimeRotatingFileSinkDriver<number | void>;\n/**\n * A Node.js-specific async time-rotating file sink driver.\n * @since 2.0.0\n */\ndeclare const nodeAsyncTimeDriver: AsyncTimeRotatingFileSinkDriver<number | void>;\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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\ndeclare function getFileSink(path: string, options?: FileSinkOptions): Sink & Disposable;\ndeclare function getFileSink(path: string, options: FileSinkOptions & {\n nonBlocking: true;\n}): Sink & AsyncDisposable;\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. If `nonBlocking` is enabled,\n * returns a sink that also implements {@link AsyncDisposable}.\n */\ndeclare function getRotatingFileSink(path: string, options?: RotatingFileSinkOptions): Sink & Disposable;\ndeclare function getRotatingFileSink(path: string, options: RotatingFileSinkOptions & {\n nonBlocking: true;\n}): Sink & AsyncDisposable;\n/**\n * Get a time-rotating file sink.\n *\n * This sink writes log records to a file in a directory, rotating to a new\n * file based on time intervals. The filename is generated based on the\n * current date/time and the configured interval.\n *\n * Note that this function is unavailable in the browser.\n *\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. If `nonBlocking` is\n * enabled, returns a sink that also implements {@link AsyncDisposable}.\n * @since 2.0.0\n */\ndeclare function getTimeRotatingFileSink(options: TimeRotatingFileSinkOptions): Sink & Disposable;\ndeclare function getTimeRotatingFileSink(options: TimeRotatingFileSinkOptions & {\n nonBlocking: true;\n}): Sink & AsyncDisposable;\n//# sourceMappingURL=filesink.node.d.ts.map\n//#endregion\nexport { getFileSink, getRotatingFileSink, getTimeRotatingFileSink, nodeAsyncDriver, nodeAsyncTimeDriver, nodeDriver, nodeTimeDriver };\n//# sourceMappingURL=filesink.node.d.ts.map"],"mappings":";;;;;;;;;AA2D0B;AAAA;;;;;AAgBuE;AAAA;iBAvChFY,WAAAA,CAwCuB,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAxCaX,eAwCb,CAAA,EAxC+BM,IAwC/B,GAxCsCM,UAwCtC;iBAvCvBD,WAAAA,CAuCiCN,IAAAA,EAAAA,MAAAA,EAAAA,OAAAA,EAvCEL,eAuCFK,GAAAA;EAA2B,WAEzEC,EAAAA,IAAAA;CAAI,CAAA,EAvCJA,IAuCOO,GAvCAA,eAuCAA;AAAe;;;;;;;;;;;;;;;;iBAtBTC,mBAAAA,yBAA4CZ,0BAA0BI,OAAOM;iBAC7EE,mBAAAA,wBAA2CZ;;IAExDI,OAAOO;;;;;;;;;;;;;;;;iBAgBME,uBAAAA,UAAiCV,8BAA8BC,OAAOM;iBACtEG,uBAAAA,UAAiCV;;IAE9CC,OAAOO"}
@@ -1,44 +0,0 @@
1
- import { FileSinkOptions } from "./filesink.base.cjs";
2
-
3
- //#region dist/timefilesink.d.ts
4
-
5
- //#region src/timefilesink.d.ts
6
- /**
7
- * The rotation interval for time-based file sinks.
8
- */
9
- type TimeRotationInterval = "hourly" | "daily" | "weekly";
10
- /**
11
- * Options for the {@link getBaseTimeRotatingFileSink} function.
12
- */
13
- interface TimeRotatingFileSinkOptions extends Omit<FileSinkOptions, "lazy"> {
14
- /**
15
- * The directory to write log files to.
16
- */
17
- directory: string;
18
- /**
19
- * A function that generates the filename for the log file based on the date.
20
- * Default depends on `interval`:
21
- * - `"daily"`: `YYYY-MM-DD.log` (e.g., `2025-01-15.log`)
22
- * - `"hourly"`: `YYYY-MM-DD-HH.log` (e.g., `2025-01-15-09.log`)
23
- * - `"weekly"`: `YYYY-WW.log` (e.g., `2025-W03.log`)
24
- */
25
- filename?: (date: Date) => string;
26
- /**
27
- * The rotation interval. Defaults to `"daily"`.
28
- */
29
- interval?: TimeRotationInterval;
30
- /**
31
- * The maximum age of log files in milliseconds. Files older than this
32
- * will be deleted. If not specified, old files are not deleted.
33
- *
34
- * When using `getTimeRotatingFileSink()` with `filename` set, cleanup uses
35
- * each file's modification time instead of parsing dates from filenames.
36
- */
37
- maxAgeMs?: number;
38
- }
39
- /**
40
- * A platform-specific time-rotating file sink driver.
41
- */
42
- //#endregion
43
- export { TimeRotatingFileSinkOptions };
44
- //# sourceMappingURL=timefilesink.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"timefilesink.d.cts","names":["AsyncFileSinkDriver","FileSinkDriver","FileSinkOptions","Sink","TimeRotationInterval","TimeRotatingFileSinkOptions","Date","Omit","TimeRotatingFileSinkDriver","TFile","AsyncTimeRotatingFileSinkDriver"],"sources":["../timefilesink.d.ts"],"sourcesContent":["import { AsyncFileSinkDriver, FileSinkDriver, FileSinkOptions } from \"./filesink.base.js\";\nimport { Sink } from \"@logtape/logtape\";\n\n//#region src/timefilesink.d.ts\n\n/**\n * The rotation interval for time-based file sinks.\n */\ntype TimeRotationInterval = \"hourly\" | \"daily\" | \"weekly\";\n/**\n * Options for the {@link getBaseTimeRotatingFileSink} function.\n */\ninterface TimeRotatingFileSinkOptions extends Omit<FileSinkOptions, \"lazy\"> {\n /**\n * The directory to write log files to.\n */\n directory: string;\n /**\n * A function that generates the filename for the log file based on the date.\n * Default depends on `interval`:\n * - `\"daily\"`: `YYYY-MM-DD.log` (e.g., `2025-01-15.log`)\n * - `\"hourly\"`: `YYYY-MM-DD-HH.log` (e.g., `2025-01-15-09.log`)\n * - `\"weekly\"`: `YYYY-WW.log` (e.g., `2025-W03.log`)\n */\n filename?: (date: Date) => string;\n /**\n * The rotation interval. Defaults to `\"daily\"`.\n */\n interval?: TimeRotationInterval;\n /**\n * The maximum age of log files in milliseconds. Files older than this\n * will be deleted. If not specified, old files are not deleted.\n *\n * When using `getTimeRotatingFileSink()` with `filename` set, cleanup uses\n * each file's modification time instead of parsing dates from filenames.\n */\n maxAgeMs?: number;\n}\n/**\n * A platform-specific time-rotating file sink driver.\n */\ninterface TimeRotatingFileSinkDriver<TFile> extends FileSinkDriver<TFile> {\n /**\n * Read the contents of a directory.\n * @param path A path to the directory.\n * @returns An array of filenames in the directory.\n */\n readdirSync(path: string): string[];\n /**\n * Delete a file.\n * @param path A path to the file to delete.\n */\n unlinkSync(path: string): void;\n /**\n * Create a directory if it doesn't exist.\n * @param path A path to the directory to create.\n * @param options Options for directory creation.\n */\n mkdirSync(path: string, options?: {\n recursive?: boolean;\n }): void;\n /**\n * Join path segments.\n * @param paths Path segments to join.\n * @returns The joined path.\n */\n joinPath(...paths: string[]): string;\n}\n/**\n * A platform-specific async time-rotating file sink driver.\n * @since 2.0.0\n */\ninterface AsyncTimeRotatingFileSinkDriver<TFile> extends AsyncFileSinkDriver<TFile> {\n /**\n * Read the contents of a directory.\n * @param path A path to the directory.\n * @returns An array of filenames in the directory.\n */\n readdirSync(path: string): string[];\n /**\n * Delete a file.\n * @param path A path to the file to delete.\n */\n unlinkSync(path: string): void;\n /**\n * Create a directory if it doesn't exist.\n * @param path A path to the directory to create.\n * @param options Options for directory creation.\n */\n mkdirSync(path: string, options?: {\n recursive?: boolean;\n }): void;\n /**\n * Join path segments.\n * @param paths Path segments to join.\n * @returns The joined path.\n */\n joinPath(...paths: string[]): string;\n}\n/**\n * Get the ISO week number of a date.\n * @param date The date to get the week number of.\n * @returns The ISO week number (1-53).\n */\n//#endregion\nexport { AsyncTimeRotatingFileSinkDriver, TimeRotatingFileSinkDriver, TimeRotatingFileSinkOptions, TimeRotationInterval };\n//# sourceMappingURL=timefilesink.d.ts.map"],"mappings":";;;;AACwC;;;;KAOnCI,oBAAAA,GAoBQA,QAAAA,GAAAA,OAAAA,GAAAA,QAAAA;;AAhBqC;;UAAxCC,2BAAAA,SAAoCE,KAAKL;;;;;;;;;;;;oBAY/BI;;;;aAIPF"}