UNPKG

2.75 kBJavaScriptView Raw
1const fs = require('fs')
2const os = require('os')
3const path = require('path')
4const Readable = require('stream').Readable
5const Writable = require('stream').Writable
6const makePromise = require('makepromise')
7const TEMP_DIR = os.tmpdir()
8
9function openFileForWrite(filepath) {
10 return new Promise((resolve, reject) => {
11 const ws = fs.createWriteStream(filepath, {
12 flags: 'w',
13 defaultEncoding: 'utf8',
14 fd: null,
15 mode: 0o666,
16 autoClose: true,
17 })
18 ws.once('open', () => resolve(ws))
19 ws.once('error', reject)
20 })
21}
22
23function getTempFile() {
24 const rnd = Math.ceil(Math.random() * 100000)
25 const tempFile = path.join(TEMP_DIR, `wrote-${rnd}.data`)
26 return tempFile
27}
28
29function unlink(path) {
30 const promise = makePromise(fs.unlink, path, path)
31 return promise
32}
33
34function endStream(ws) {
35 if (!ws.writable || ws.closed) {
36 return Promise.reject(new Error('stream should be writable'))
37 }
38 const promise = new Promise((resolve, reject) => {
39 ws.once('close', () => resolve(ws))
40 ws.once('error', reject)
41 })
42 return makePromise(ws.close.bind(ws))
43 .then(() => promise)
44}
45
46function erase(ws) {
47 return unlink(ws.path)
48 .then(() => {
49 if (!ws.closed) {
50 return endStream(ws)
51 }
52 return ws
53 })
54}
55
56/**
57 * Open the file for writing and create a write stream.
58 * @param {string} ffile path to the file
59 * @returns {Promise<Writable>} A promise with the stream
60 */
61function wrote(file) {
62 const _file = (typeof file).toLowerCase() === 'string' ?
63 file : getTempFile()
64 return openFileForWrite(_file)
65}
66
67/**
68 * Write data to the stream, and resolve when it's ended.
69 * @param {Writable} ws write stream
70 * @param {string|Readable} source read source
71 * @returns {Promise<Writable>} A promise resolved with the writable stream, or rejected
72 * when an error occurred while reading or writing.
73 */
74function write(ws, source) {
75 if (!(ws instanceof Writable)) {
76 return Promise.reject(new Error('Writable stream expected'))
77 }
78 if (source instanceof Readable) {
79 if (!source.readable) {
80 return Promise.reject(new Error('Stream is not readable'))
81 }
82 return new Promise((resolve, reject) => {
83 ws.on('finish', () => {
84 resolve(ws)
85 })
86 ws.on('error', reject)
87 source.on('error', reject)
88 source.pipe(ws)
89 })
90 }
91 return makePromise(ws.end.bind(ws), source, ws)
92}
93
94Object.defineProperty(wrote, 'write', { get: () => write })
95Object.defineProperty(wrote, 'erase', { get: () => erase })
96
97module.exports = wrote