Comparing version 1.2.0 to 1.3.0
'use strict' | ||
const { readdir, stat, unlink } = require('fs/promises') | ||
const { readdir, stat, unlink, symlink, lstat, readlink } = require('fs/promises') | ||
const { dirname, join } = require('path') | ||
@@ -138,5 +138,28 @@ | ||
async function checkSymlink (fileName, linkPath) { | ||
const stats = await lstat(linkPath).then(stats => stats, () => null) | ||
if (stats?.isSymbolicLink()) { | ||
const existingTarget = await readlink(linkPath) | ||
if (existingTarget === fileName) { | ||
return false | ||
} | ||
await unlink(linkPath) | ||
} | ||
return true | ||
} | ||
async function createSymlink (fileVal) { | ||
const fileName = getFileName(fileVal) | ||
const linkPath = join(dirname(fileName), 'current.log') | ||
const shouldCreateSymlink = await checkSymlink(fileName, linkPath) | ||
if (shouldCreateSymlink) { | ||
await symlink(fileName.split(/(\\|\/)/g).pop(), linkPath) | ||
} | ||
} | ||
module.exports = { | ||
buildFileName, | ||
checkFileRemoval, | ||
checkSymlink, | ||
createSymlink, | ||
detectLastNumber, | ||
@@ -143,0 +166,0 @@ parseFrequency, |
{ | ||
"name": "pino-roll", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "A Pino transport that automatically rolls your log files", | ||
@@ -5,0 +5,0 @@ "main": "pino-roll.js", |
@@ -7,2 +7,3 @@ 'use strict' | ||
checkFileRemoval, | ||
createSymlink, | ||
detectLastNumber, | ||
@@ -46,2 +47,4 @@ parseSize, | ||
* | ||
* @property {boolean} symlink? - When specified, creates a symlink to the current log file. | ||
* | ||
* @property {LimitOptions} limit? - strategy used to remove oldest files when rotating them. | ||
@@ -73,2 +76,3 @@ */ | ||
limit, | ||
symlink, | ||
...opts | ||
@@ -88,2 +92,6 @@ } = {}) { | ||
if (symlink) { | ||
createSymlink(fileName) | ||
} | ||
let rollTimeout | ||
@@ -111,2 +119,5 @@ if (frequencySpec) { | ||
destination.reopen(fileName) | ||
if (symlink) { | ||
createSymlink(fileName) | ||
} | ||
if (limit) { | ||
@@ -113,0 +124,0 @@ createdFileNames.push(fileName) |
@@ -60,2 +60,6 @@ # pino-roll | ||
* `symlink?`: creates a symlink to the current log file. | ||
The symlink will be updated to the latest log file upon rotation. | ||
The name of the symlink is always called `current.log`. | ||
* `limit?`: strategy used to remove oldest files when rotating them: | ||
@@ -62,0 +66,0 @@ |
'use strict' | ||
const { addDays, addHours, startOfDay, startOfHour } = require('date-fns') | ||
const { writeFile, rm, stat } = require('fs/promises') | ||
const { writeFile, rm, stat, readlink, symlink } = require('fs/promises') | ||
const { join } = require('path') | ||
@@ -10,2 +10,4 @@ const { test } = require('tap') | ||
buildFileName, | ||
checkSymlink, | ||
createSymlink, | ||
getFileSize, | ||
@@ -151,1 +153,39 @@ detectLastNumber, | ||
}) | ||
test('checkSymlink()', async ({ test, beforeEach }) => { | ||
const folder = join('logs', 'utils') | ||
beforeEach(() => cleanAndCreateFolder(folder)) | ||
test('given a new symlink (should return true)', async ({ equal }) => { | ||
const fileName = join(folder, 'file.log') | ||
const linkPath = join(folder, 'current.log') | ||
await writeFile(fileName, 'test content') | ||
const result = await checkSymlink(fileName, linkPath) | ||
equal(result, true, 'returns true when symlink does not exist') | ||
}) | ||
test('given an existing symlink pointing to the same file (should return false)', async ({ equal }) => { | ||
const fileName = join(folder, 'file.log') | ||
const linkPath = join(folder, 'current.log') | ||
await writeFile(fileName, 'test content') | ||
await symlink(fileName, linkPath) | ||
const result = await checkSymlink(fileName, linkPath) | ||
equal(result, false, 'returns false when symlink points to the same file') | ||
const linkTarget = await readlink(linkPath) | ||
equal(linkTarget, fileName, 'symlink remains unchanged') | ||
}) | ||
}) | ||
test('createSymlink()', async ({ beforeEach }) => { | ||
const folder = join('logs', 'utils') | ||
beforeEach(() => cleanAndCreateFolder(folder)) | ||
test('given a new symlink (should create symlink)', async ({ equal }) => { | ||
const fileName = join(folder, 'file.log') | ||
const linkPath = join(folder, 'current.log') | ||
await writeFile(fileName, 'test content') | ||
await createSymlink(fileName) | ||
const linkTarget = await readlink(linkPath) | ||
equal(linkTarget, fileName, 'creates correct symlink') | ||
}) | ||
}) |
'use strict' | ||
const { once } = require('events') | ||
const { stat, readFile, writeFile, readdir } = require('fs/promises') | ||
const { stat, readFile, writeFile, readdir, lstat, readlink } = require('fs/promises') | ||
const { join } = require('path') | ||
@@ -214,1 +214,33 @@ const { test, beforeEach } = require('tap') | ||
}) | ||
test('creates symlink if prop is set', async ({ equal, resolves }) => { | ||
const file = join(logFolder, 'log') | ||
const linkPath = join(logFolder, 'current.log') | ||
const stream = await buildStream({ file, symlink: true }) | ||
stream.write('test content\n') | ||
stream.end() | ||
await sleep(200) | ||
await resolves(lstat(linkPath), 'symlink was created') | ||
const linkTarget = await readlink(linkPath) | ||
equal(linkTarget, 'log.1', 'symlink points to the correct file') | ||
const content = await readFile(linkPath, 'utf8') | ||
equal(content, 'test content\n', 'symlink contains correct content') | ||
}) | ||
test('symlink rotates on roll', async ({ equal, ok, resolves }) => { | ||
const file = join(logFolder, 'log') | ||
const linkPath = join(logFolder, 'current.log') | ||
const stream = await buildStream({ frequency: 100, file, symlink: true }) | ||
stream.write('logged message #1\n') | ||
stream.write('logged message #2\n') | ||
await sleep(110) | ||
stream.write('logged message #3\n') | ||
stream.write('logged message #4\n') | ||
stream.end() | ||
await sleep(200) | ||
await resolves(lstat(linkPath), 'symlink was created') | ||
const linkTarget = await readlink(linkPath) | ||
equal(linkTarget, 'log.2', 'symlink points to the correct file') | ||
const content = await readFile(linkPath, 'utf8') | ||
ok(content.includes('#4'), 'symlink contains fourth log') | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
30531
676
74