codejump
MediumPro challengeJavaScriptTypeScript

Node.js — Rotate Log Files

Node.jsBackendFiles

tinyserve appends every request to access.log. Left alone, that file grows until the disk is
full. Log rotation caps it: the current log becomes access.log.1, the previous .1
becomes .2, and so on, and only the newest keep old logs survive.

Your task

Write async rotate(dir, name, keep) with fs/promises (rename, rm, writeFile):

1. If dir/name does not exist, change nothing and return false.
2. Delete name.<keep> if it exists.
3. Rename name.<n> to name.<n+1> for n from keep - 1 down to 1. A missing
number (a gap) is skipped, not an error.
4. Rename name to name.1, create a new empty name, return true.

Other files of the folder are untouched. The test driver calls rotate(dir, 'access.log', keep)
and reports the folder's files and contents.

Example (keep = 3)

before                          after
access.log     "mon"            access.log     ""
access.log.1   "sun"     →      access.log.1   "mon"
access.log.2   "sat"            access.log.2   "sun"
                                access.log.3   "sat"

Order matters

On Linux and macOS, rename silently replaces an existing target. Renaming .1 → .2 before
.2 → .3 destroys a log.

Sample tests

Test #1First rotation
Input: [{"access.log":"today"},3]
Output: {"files":{"access.log":"","access.log.1":"today"},"rotated":true}
Test #2Shift without loss
Input: [{"access.log":"mon","access.log.1":"sun","access.log.2":"sat"},3]
Output: {"files":{"access.log":"","access.log.1":"mon","access.log.2":"sun","access.log.3":"sat"},"rotated":true}
Test #3Oldest log dropped
Input: [{"access.log":"mon","access.log.1":"sun","access.log.2":"sat"},2]
Output: {"files":{"access.log":"","access.log.1":"mon","access.log.2":"sun"},"rotated":true}
Test #4No log yet
Input: [{},3]
Output: {"files":{},"rotated":false}