Skip to content

Commit

Permalink
add option to ensure directory for dest file exists (#79)
Browse files Browse the repository at this point in the history
- mkdir:true ensures the directory exists using fs.mkdir with the recursive option
- mkdir:false does not check for the existence of the directory (default)
  • Loading branch information
mojavelinux authored Jun 30, 2021
1 parent 6ad7674 commit 7032d8e
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 8 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,11 @@ The options are:
* `fd`: a file descriptor, something that is returned by `fs.open` or
`fs.openSync`.
* `dest`: a string that is a path to a file to be written to (mode controlled by the `append` option).
* `minLength`: the minimum lenght of the internal buffer that is
* `minLength`: the minimum length of the internal buffer that is
required to be full before flushing.
* `sync`: perform writes synchronously (similar to `console.log`).
* `append`: appends writes to dest file instead of truncating it (default `true`)
* `append`: appends writes to dest file instead of truncating it (default `true`).
* `mkdir`: ensure directory for dest file exists when `true` (default `false`).

For `sync:false` a `SonicBoom` instance will emit the `'ready'` event when a file descriptor is available.
For `sync:true` this is not relevant because the `'ready'` event will be fired when the `SonicBoom` instance is created, before it can be subscribed to.
Expand Down
18 changes: 13 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const fs = require('fs')
const EventEmitter = require('events')
const inherits = require('util').inherits
const path = require('path')

const BUSY_WRITE_TIMEOUT = 100

Expand Down Expand Up @@ -64,16 +65,23 @@ function openFile (file, sonic) {
}
}

const mode = sonic.append ? 'a' : 'w'
if (sonic.sync) {
try {
const fd = fs.openSync(file, sonic.append ? 'a' : 'w')
if (sonic.mkdir) fs.mkdirSync(path.dirname(file), { recursive: true })
const fd = fs.openSync(file, mode)
fileOpened(null, fd)
} catch (err) {
fileOpened(err)
throw err
}
} else if (sonic.mkdir) {
fs.mkdir(path.dirname(file), { recursive: true }, (err) => {
if (err) return fileOpened(err)
fs.open(file, mode, fileOpened)
})
} else {
fs.open(file, sonic.append ? 'a' : 'w', fileOpened)
fs.open(file, mode, fileOpened)
}
}

Expand All @@ -82,7 +90,7 @@ function SonicBoom (opts) {
return new SonicBoom(opts)
}

let { fd, dest, minLength, sync, append = true } = opts || {}
let { fd, dest, minLength, sync, append = true, mkdir } = opts || {}

fd = fd || dest

Expand All @@ -95,10 +103,10 @@ function SonicBoom (opts) {
this._asyncDrainScheduled = false
this.file = null
this.destroyed = false
this.minLength = minLength || 0
this.sync = sync || false
this.append = append || false

this.minLength = minLength || 0
this.mkdir = mkdir || false

if (typeof fd === 'number') {
this.fd = fd
Expand Down
29 changes: 29 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,35 @@ function buildTests (test, sync) {
})
})

test('mkdir', (t) => {
t.plan(4)

const dest = path.join(file(), 'out.log')
const stream = new SonicBoom({ dest, mkdir: true, sync })

stream.on('ready', () => {
t.pass('ready emitted')
})

t.ok(stream.write('hello world\n'))

stream.flush()

stream.on('drain', () => {
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'hello world\n')
stream.end()
// put file where teardown can access it
const { dir, base } = path.parse(dest)
const tmpDir = dir + '~'
fs.renameSync(dir, tmpDir)
fs.renameSync(path.join(tmpDir, base), dir)
fs.rmdirSync(tmpDir)
})
})
})

test('flush', (t) => {
t.plan(5)

Expand Down
1 change: 1 addition & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type SonicBoomOpts = {
minLength?: number
sync?: boolean
append?: boolean
mkdir?: boolean
}

export class SonicBoom extends EventEmitter {
Expand Down
2 changes: 1 addition & 1 deletion types/index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ sonic.end();

sonic.destroy();

const extraSonic = new SonicBoom({fd: 1, minLength: 0, sync: true, append: true});
const extraSonic = new SonicBoom({fd: 1, minLength: 0, sync: true, append: true, mkdir: true});

extraSonic.write('extra sonic\n');

0 comments on commit 7032d8e

Please sign in to comment.