pax_global_header00006660000000000000000000000064135336573350014527gustar00rootroot0000000000000052 comment=f537eb68091d0257b5a4ea915aa00a2c46727198 write-2.0.0/000077500000000000000000000000001353365733500126605ustar00rootroot00000000000000write-2.0.0/.editorconfig000066400000000000000000000002531353365733500153350ustar00rootroot00000000000000root = true [*] indent_style = space indent_size = 2 charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.md] trim_trailing_whitespace = false write-2.0.0/.eslintrc.json000066400000000000000000000073251353365733500154630ustar00rootroot00000000000000{ "extends": [ "eslint:recommended" ], "env": { "browser": false, "es6": true, "node": true, "mocha": true }, "parserOptions":{ "ecmaVersion": 9, "sourceType": "module", "ecmaFeatures": { "modules": true, "experimentalObjectRestSpread": true } }, "globals": { "document": false, "navigator": false, "window": false }, "rules": { "accessor-pairs": 2, "arrow-spacing": [2, { "before": true, "after": true }], "block-spacing": [2, "always"], "brace-style": [2, "1tbs", { "allowSingleLine": true }], "comma-dangle": [2, "never"], "comma-spacing": [2, { "before": false, "after": true }], "comma-style": [2, "last"], "constructor-super": 2, "curly": [2, "multi-line"], "dot-location": [2, "property"], "eol-last": 2, "eqeqeq": [2, "allow-null"], "generator-star-spacing": [2, { "before": true, "after": true }], "handle-callback-err": [2, "^(err|error)$" ], "indent": [2, 2, { "SwitchCase": 1 }], "key-spacing": [2, { "beforeColon": false, "afterColon": true }], "keyword-spacing": [2, { "before": true, "after": true }], "new-cap": [2, { "newIsCap": true, "capIsNew": false }], "new-parens": 2, "no-array-constructor": 2, "no-caller": 2, "no-class-assign": 2, "no-cond-assign": 2, "no-const-assign": 2, "no-control-regex": 2, "no-debugger": 2, "no-delete-var": 2, "no-dupe-args": 2, "no-dupe-class-members": 2, "no-dupe-keys": 2, "no-duplicate-case": 2, "no-empty-character-class": 2, "no-eval": 2, "no-ex-assign": 2, "no-extend-native": 2, "no-extra-bind": 2, "no-extra-boolean-cast": 2, "no-extra-parens": [2, "functions"], "no-fallthrough": 2, "no-floating-decimal": 2, "no-func-assign": 2, "no-implied-eval": 2, "no-inner-declarations": [2, "functions"], "no-invalid-regexp": 2, "no-irregular-whitespace": 2, "no-iterator": 2, "no-label-var": 2, "no-labels": 2, "no-lone-blocks": 2, "no-mixed-spaces-and-tabs": 2, "no-multi-spaces": 2, "no-multi-str": 2, "no-multiple-empty-lines": [2, { "max": 1 }], "no-native-reassign": 0, "no-negated-in-lhs": 2, "no-new": 2, "no-new-func": 2, "no-new-object": 2, "no-new-require": 2, "no-new-wrappers": 2, "no-obj-calls": 2, "no-octal": 2, "no-octal-escape": 2, "no-proto": 0, "no-redeclare": 2, "no-regex-spaces": 2, "no-return-assign": 2, "no-self-compare": 2, "no-sequences": 2, "no-shadow-restricted-names": 2, "no-spaced-func": 2, "no-sparse-arrays": 2, "no-this-before-super": 2, "no-throw-literal": 2, "no-trailing-spaces": 0, "no-undef": 2, "no-undef-init": 2, "no-unexpected-multiline": 2, "no-unneeded-ternary": [2, { "defaultAssignment": false }], "no-unreachable": 2, "no-unused-vars": [2, { "vars": "all", "args": "none" }], "no-useless-call": 0, "no-with": 2, "one-var": [0, { "initialized": "never" }], "operator-linebreak": [0, "after", { "overrides": { "?": "before", ":": "before" } }], "padded-blocks": [0, "never"], "quotes": [2, "single", "avoid-escape"], "radix": 2, "semi": [2, "always"], "semi-spacing": [2, { "before": false, "after": true }], "space-before-blocks": [2, "always"], "space-before-function-paren": [2, "never"], "space-in-parens": [2, "never"], "space-infix-ops": 2, "space-unary-ops": [2, { "words": true, "nonwords": false }], "spaced-comment": [0, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }], "use-isnan": 2, "valid-typeof": 2, "wrap-iife": [2, "any"], "yoda": [2, "never"] } } write-2.0.0/.gitattributes000066400000000000000000000000131353365733500155450ustar00rootroot00000000000000* text=autowrite-2.0.0/.gitignore000066400000000000000000000004401353365733500146460ustar00rootroot00000000000000# always ignore files *.DS_Store *.sublime-* # test related, or directories generated by tests test/actual actual coverage .nyc* # npm node_modules npm-debug.log # yarn yarn.lock yarn-error.log # misc _gh_pages _draft _drafts bower_components vendor temp tmp TODO.md package-lock.jsonwrite-2.0.0/.travis.yml000066400000000000000000000001441353365733500147700ustar00rootroot00000000000000sudo: false os: - linux - osx - windows language: node_js node_js: - node - '12' - '10' write-2.0.0/.verb.md000066400000000000000000000031041353365733500142140ustar00rootroot00000000000000## Usage ```js const write = require('write'); ``` ## Options The following options may be used with any method. ### options.newline **Type**: `boolean` **Default**: `undefined` Ensure that contents has a trailing newline before writing it to the file system. ```js write.sync('foo.txt', 'some data...', { newline: true }); ``` ### options.overwrite **Type**: `boolean` **Default**: `undefined` Set to `false` to prevent existing files from being overwritten. See [increment](#optionsincrement) for a less severe alternative. ```js write.sync('foo.txt', 'some data...', { overwrite: false }); ``` ### options.increment **Type**: `boolean` **Default**: `undefined` Set to `true` to automatically rename files by appending an increment, like `foo (2).txt`, to prevent `foo.txt` from being overwritten. This is useful when writing log files, or other information where the file name is less important than the contents being written. ```js write.sync('foo.txt', 'some data...', { increment: true }); // if "foo.txt" exists, the file will be renamed to "foo (2).txt" ``` ## API {%= apidocs("index.js") %} ## Release history See [CHANGELOG.md]. [fs]: https://nodejs.org/api/fs.html [writestream]: https://nodejs.org/api/fs.html#fs_class_fs_writestream [wsoptions]: https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_options [writefile]: https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback [writefilesync]: https://nodejs.org/api/fs.html#fs_fs_writefilesync_file_data_options [writable]: https://nodejs.org/api/stream.html#stream_class_stream_writable write-2.0.0/CHANGELOG.md000066400000000000000000000012731353365733500144740ustar00rootroot00000000000000# Changelog ### v2.0.0 - 2019-08-12 **Changes** - Refactored code - Use `fs.createWriteStream` in the main function to improve performance. **Added** - Added `overwrite` option - Added `increment` option See the [README](readme.md) for more details. **Removed** - Removed support for passing a custom string on `options.newline`. This should be done before passing the contents to `write()` - The `.promise` method was removed since _the main export returns a promise, making the method unnecessary_. ### v1.0.2 - 2017-07-11 - improved documentation ### v1.0.0 - 2017-07-09 **Added** - promise support **Changed** - The main export will now return a promise if no callback is passedwrite-2.0.0/LICENSE000066400000000000000000000021031353365733500136610ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014-present, Jon Schlinkert. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. write-2.0.0/README.md000066400000000000000000000223611353365733500141430ustar00rootroot00000000000000# write [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W8YFZ425KND68) [![NPM version](https://img.shields.io/npm/v/write.svg?style=flat)](https://www.npmjs.com/package/write) [![NPM monthly downloads](https://img.shields.io/npm/dm/write.svg?style=flat)](https://npmjs.org/package/write) [![NPM total downloads](https://img.shields.io/npm/dt/write.svg?style=flat)](https://npmjs.org/package/write) [![Build Status](https://travis-ci.org/jonschlinkert/write.svg?branch=master)](https://travis-ci.org/jonschlinkert/write) > Write data to a file, replacing the file if it already exists and creating any intermediate directories if they don't already exist. Thin wrapper around node's native fs methods. Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. ## Install Install with [npm](https://www.npmjs.com/) (requires [Node.js](https://nodejs.org/en/) >=10): ```sh $ npm install --save write ``` ## Usage ```js const write = require('write'); ``` ## Options The following options may be used with any method. ### options.newline **Type**: `boolean` **Default**: `undefined` Ensure that contents has a trailing newline before writing it to the file system. ```js write.sync('foo.txt', 'some data...', { newline: true }); ``` ### options.overwrite **Type**: `boolean` **Default**: `undefined` Set to `false` to prevent existing files from being overwritten. See [increment](#optionsincrement) for a less severe alternative. ```js write.sync('foo.txt', 'some data...', { overwrite: false }); ``` ### options.increment **Type**: `boolean` **Default**: `undefined` Set to `true` to automatically rename files by appending an increment, like `foo (2).txt`, to prevent `foo.txt` from being overwritten. This is useful when writing log files, or other information where the file name is less important than the contents being written. ```js write.sync('foo.txt', 'some data...', { increment: true }); // if "foo.txt" exists, the file will be renamed to "foo (2).txt" ``` ## API ### [write](index.js#L41) Asynchronously writes data to a file, replacing the file if it already exists and creating any intermediate directories if they don't already exist. Data can be a string or a buffer. Returns a promise if a callback function is not passed. **Params** * `filepath` **{String}**: file path. * `data` **{String|Buffer|Uint8Array}**: Data to write. * `options` **{Object}**: Options to pass to [fs.writeFile](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback) * `callback` **{Function}**: (optional) If no callback is provided, a promise is returned. * `returns` **{Object}**: Returns an object with the `path` and `contents` of the file that was written to the file system. This is useful for debugging when `options.increment` is used and the path might have been modified. **Example** ```js const write = require('write'); // async/await (async () => { await write('foo.txt', 'This is content...'); })(); // promise write('foo.txt', 'This is content...') .then(() => { // do stuff }); // callback write('foo.txt', 'This is content...', err => { // do stuff with err }); ``` ### [.sync](index.js#L88) The synchronous version of [write](#write). Returns undefined. **Params** * `filepath` **{String}**: file path. * `data` **{String|Buffer|Uint8Array}**: Data to write. * `options` **{Object}**: Options to pass to [fs.writeFileSync](https://nodejs.org/api/fs.html#fs_fs_writefilesync_file_data_options) * `returns` **{Object}**: Returns an object with the `path` and `contents` of the file that was written to the file system. This is useful for debugging when `options.increment` is used and the path might have been modified. **Example** ```js const write = require('write'); write.sync('foo.txt', 'This is content...'); ``` ### [.stream](index.js#L127) Returns a new [WriteStream](https://nodejs.org/api/fs.html#fs_class_fs_writestream) object. Uses `fs.createWriteStream` to write data to a file, replacing the file if it already exists and creating any intermediate directories if they don't already exist. Data can be a string or a buffer. **Params** * `filepath` **{String}**: file path. * `options` **{Object}**: Options to pass to [fs.createWriteStream](https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_options) * `returns` **{Stream}**: Returns a new [WriteStream](https://nodejs.org/api/fs.html#fs_class_fs_writestream) object. (See [Writable Stream](https://nodejs.org/api/stream.html#stream_class_stream_writable)). **Example** ```js const fs = require('fs'); const write = require('write'); fs.createReadStream('README.md') .pipe(write.stream('a/b/c/other-file.md')) .on('close', () => { // do stuff }); ``` ## Release history See [CHANGELOG.md]. ## About
Contributing Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
Running Tests Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: ```sh $ npm install && npm test ```
Building docs _(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ To generate the readme, run the following command: ```sh $ npm install -g verbose/verb#dev verb-generate-readme && verb ```
### Related projects You might also be interested in these projects: * [add-filename-increment](https://www.npmjs.com/package/add-filename-increment): When copying or moving files, it's common for operating systems to automatically add an increment… [more](https://github.com/jonschlinkert/add-filename-increment) | [homepage](https://github.com/jonschlinkert/add-filename-increment "When copying or moving files, it's common for operating systems to automatically add an increment or 'copy' to duplicate file names. This does that for Node.js applications, with automatic platform detection and support for Linux, MacOs, and Windows conve") * [delete](https://www.npmjs.com/package/delete): Delete files and folders and any intermediate directories if they exist (sync and async). | [homepage](https://github.com/jonschlinkert/delete "Delete files and folders and any intermediate directories if they exist (sync and async).") * [read-data](https://www.npmjs.com/package/read-data): Read JSON or YAML files. | [homepage](https://github.com/jonschlinkert/read-data "Read JSON or YAML files.") * [read-yaml](https://www.npmjs.com/package/read-yaml): Very thin wrapper around js-yaml for directly reading in YAML files. | [homepage](https://github.com/jonschlinkert/read-yaml "Very thin wrapper around js-yaml for directly reading in YAML files.") * [strip-filename-increment](https://www.npmjs.com/package/strip-filename-increment): Operating systems commonly add a trailing increment, or the word 'copy', or something similar to… [more](https://github.com/jonschlinkert/strip-filename-increment) | [homepage](https://github.com/jonschlinkert/strip-filename-increment "Operating systems commonly add a trailing increment, or the word 'copy', or something similar to duplicate files. This strips those increments. Tested on Windows, MacOS, and Linux.") * [write-data](https://www.npmjs.com/package/write-data): Write a YAML or JSON file to disk. Automatically detects the format to write based… [more](https://github.com/jonschlinkert/write-data) | [homepage](https://github.com/jonschlinkert/write-data "Write a YAML or JSON file to disk. Automatically detects the format to write based on extension. Or pass `ext` on the options.") * [write-json](https://www.npmjs.com/package/write-json): Write a JSON file to disk, also creates intermediate directories in the destination path if… [more](https://github.com/jonschlinkert/write-json) | [homepage](https://github.com/jonschlinkert/write-json "Write a JSON file to disk, also creates intermediate directories in the destination path if they don't already exist.") * [write-yaml](https://www.npmjs.com/package/write-yaml): Write YAML. Converts JSON to YAML writes it to the specified file. | [homepage](https://github.com/jonschlinkert/write-yaml "Write YAML. Converts JSON to YAML writes it to the specified file.") ### Contributors | **Commits** | **Contributor** | | --- | --- | | 42 | [jonschlinkert](https://github.com/jonschlinkert) | | 2 | [jpetitcolas](https://github.com/jpetitcolas) | | 1 | [tunnckoCore](https://github.com/tunnckoCore) | ### Author **Jon Schlinkert** * [GitHub Profile](https://github.com/jonschlinkert) * [Twitter Profile](https://twitter.com/jonschlinkert) * [LinkedIn Profile](https://linkedin.com/in/jonschlinkert) ### License Copyright © 2019, [Jon Schlinkert](https://github.com/jonschlinkert). Released under the [MIT License](LICENSE). *** _This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.8.0, on September 04, 2019._write-2.0.0/example.js000066400000000000000000000004661353365733500146570ustar00rootroot00000000000000'use strict'; const { Readable } = require('stream'); const write = require('./'); const toStream = data => { const stream = new Readable(); stream.push(data); stream.push(null); return stream; }; toStream('fooo') .pipe(write.stream('tmp/a/b/c/foo.md')) .on('close', () => console.log('done')); write-2.0.0/index.js000066400000000000000000000141371353365733500143330ustar00rootroot00000000000000'use strict'; const fs = require('fs'); const path = require('path'); const increment = require('add-filename-increment'); /** * Asynchronously writes data to a file, replacing the file if it already * exists and creating any intermediate directories if they don't already * exist. Data can be a string or a buffer. Returns a promise if a callback * function is not passed. * * ```js * const write = require('write'); * * // async/await * (async () => { * await write('foo.txt', 'This is content...'); * })(); * * // promise * write('foo.txt', 'This is content...') * .then(() => { * // do stuff * }); * * // callback * write('foo.txt', 'This is content...', err => { * // do stuff with err * }); * ``` * @name write * @param {String} `filepath` file path. * @param {String|Buffer|Uint8Array} `data` Data to write. * @param {Object} `options` Options to pass to [fs.writeFile][writefile] * @param {Function} `callback` (optional) If no callback is provided, a promise is returned. * @returns {Object} Returns an object with the `path` and `contents` of the file that was written to the file system. This is useful for debugging when `options.increment` is used and the path might have been modified. * @api public */ const write = (filepath, data, options, callback) => { if (typeof options === 'function') { callback = options; options = {}; } const opts = { encoding: 'utf8', ...options }; const destpath = opts.increment ? incrementName(filepath, options) : filepath; const result = { path: destpath, data }; if (opts.overwrite === false && exists(filepath, destpath)) { throw new Error('File already exists: ' + destpath); } const promise = mkdir(path.dirname(destpath), { recursive: true, ...options }) .then(() => { return new Promise((resolve, reject) => { fs.createWriteStream(destpath, opts) .on('error', err => reject(err)) .on('close', resolve) .end(ensureNewline(data, opts)); }); }); if (typeof callback === 'function') { promise.then(() => callback(null, result)).catch(callback); return; } return promise.then(() => result); }; /** * The synchronous version of [write](#write). Returns undefined. * * ```js * const write = require('write'); * write.sync('foo.txt', 'This is content...'); * ``` * @name .sync * @param {String} `filepath` file path. * @param {String|Buffer|Uint8Array} `data` Data to write. * @param {Object} `options` Options to pass to [fs.writeFileSync][writefilesync] * @returns {Object} Returns an object with the `path` and `contents` of the file that was written to the file system. This is useful for debugging when `options.increment` is used and the path might have been modified. * @api public */ write.sync = (filepath, data, options) => { if (typeof filepath !== 'string') { throw new TypeError('expected filepath to be a string'); } const opts = { encoding: 'utf8', ...options }; const destpath = opts.increment ? incrementName(filepath, options) : filepath; if (opts.overwrite === false && exists(filepath, destpath)) { throw new Error('File already exists: ' + destpath); } mkdirSync(path.dirname(destpath), { recursive: true, ...options }); fs.writeFileSync(destpath, ensureNewline(data, opts), opts); return { path: destpath, data }; }; /** * Returns a new [WriteStream][writestream] object. Uses `fs.createWriteStream` * to write data to a file, replacing the file if it already exists and creating * any intermediate directories if they don't already exist. Data can be a string * or a buffer. * * ```js * const fs = require('fs'); * const write = require('write'); * fs.createReadStream('README.md') * .pipe(write.stream('a/b/c/other-file.md')) * .on('close', () => { * // do stuff * }); * ``` * @name .stream * @param {String} `filepath` file path. * @param {Object} `options` Options to pass to [fs.createWriteStream][wsoptions] * @return {Stream} Returns a new [WriteStream][writestream] object. (See [Writable Stream][writable]). * @api public */ write.stream = (filepath, options) => { if (typeof filepath !== 'string') { throw new TypeError('expected filepath to be a string'); } const opts = { encoding: 'utf8', ...options }; const destpath = opts.increment ? incrementName(filepath, options) : filepath; if (opts.overwrite === false && exists(filepath, destpath)) { throw new Error('File already exists: ' + filepath); } mkdirSync(path.dirname(destpath), { recursive: true, ...options }); return fs.createWriteStream(destpath, opts); }; /** * Increment the filename if the file already exists and enabled by the user */ const incrementName = (destpath, options = {}) => { if (options.increment === true) options.increment = void 0; return increment(destpath, options); }; /** * Ensure newline at EOF if defined on options */ const ensureNewline = (data, options) => { if (!options || options.newline !== true) return data; if (typeof data !== 'string' && !isBuffer(data)) { return data; } // Only call `.toString()` on the last character. This way, // if data is a buffer, we don't need to stringify the entire // buffer just to append a newline. if (String(data.slice(-1)) !== '\n') { if (typeof data === 'string') { return data + '\n'; } return data.concat(Buffer.from('\n')); } return data; }; // if filepath !== destpath, that means the user has enabled // "increment", which has already checked the file system and // renamed the file to avoid conflicts, so we don't need to // check again. const exists = (filepath, destpath) => { return filepath === destpath && fs.existsSync(filepath); }; const mkdir = (dirname, options) => { return new Promise(resolve => fs.mkdir(dirname, options, () => resolve())); }; const mkdirSync = (dirname, options) => { try { fs.mkdirSync(dirname, options); } catch (err) { /* do nothing */ } }; const isBuffer = data => { if (data.constructor && typeof data.constructor.isBuffer === 'function') { return data.constructor.isBuffer(data); } return false; }; /** * Expose `write` */ module.exports = write; write-2.0.0/package.json000066400000000000000000000033051353365733500151470ustar00rootroot00000000000000{ "name": "write", "description": "Write data to a file, replacing the file if it already exists and creating any intermediate directories if they don't already exist. Thin wrapper around node's native fs methods.", "version": "2.0.0", "homepage": "https://github.com/jonschlinkert/write", "author": "Jon Schlinkert (https://github.com/jonschlinkert)", "contributors": [ "Charlike Mike Reagent (https://i.am.charlike.online)", "Jon Schlinkert (http://twitter.com/jonschlinkert)" ], "repository": "jonschlinkert/write", "bugs": { "url": "https://github.com/jonschlinkert/write/issues" }, "license": "MIT", "files": [ "index.js" ], "main": "index.js", "engines": { "node": ">=10" }, "scripts": { "test": "mocha" }, "dependencies": { "add-filename-increment": "^1.0.0" }, "devDependencies": { "gulp-format-md": "^2.0.0", "mocha": "^6.2.0", "rimraf": "^2.6.3" }, "keywords": [ "async", "file path", "file system", "file", "filepath", "files", "filesystem", "folder", "fs", "fs.writeFile", "fs.writeFileSync", "path", "promise", "streams", "write file", "write-file", "writefile", "write" ], "verb": { "run": true, "toc": false, "layout": "default", "tasks": [ "readme" ], "plugins": [ "gulp-format-md" ], "related": { "list": [ "add-filename-increment", "strip-filename-increment", "delete", "read-data", "read-yaml", "write-data", "write-json", "write-yaml" ] }, "reflinks": [ "verb" ], "lint": { "reflinks": true } } } write-2.0.0/test/000077500000000000000000000000001353365733500136375ustar00rootroot00000000000000write-2.0.0/test/test.js000066400000000000000000000106231353365733500151560ustar00rootroot00000000000000/*! * write * * Copyright (c) 2014-present, Jon Schlinkert. * Licensed under the MIT License. */ 'use strict'; require('mocha'); const { Readable } = require('stream'); const fs = require('fs'); const path = require('path'); const assert = require('assert').strict; const rimraf = require('rimraf'); const write = require('..'); const tmp = path.resolve.bind(path, __dirname, 'fixtures'); const files = ['a.md', 'b.md', 'c.md', 'd.md', 'e.md'].map(n => tmp(n)); const toStream = str => { let stream = new Readable(); stream.push(str); stream.push(null); return stream; }; describe('write', () => { afterEach(cb => { rimraf(tmp(), { glob: false }, cb); }); describe('async', () => { it('should write files', async () => { for (let file of files) { await write(file, 'content...'); assert(fs.existsSync(file)); } }); it('should not overwrite files when specified', async () => { for (let file of files) { write.sync(file, 'content...'); await assert.rejects(async () => { return write(file, 'content...', { overwrite: false }); }); } }); it('should automatically rename files to avoid conflicts', async () => { for (let file of files) { write.sync(file, 'content...'); const result = await write(file, 'content...', { increment: true }); assert.notEqual(file, result.path); assert(fs.existsSync(result.path)); } }); it('should take a callback', cb => { let fp = tmp('a.txt'); write(fp, 'content...', err => { if (err) { cb(err); return; } assert(fs.existsSync(fp)); cb(); }); }); it('should just write given data by default', cb => { write(tmp('a.txt'), 'Hello!', err => { if (err) { cb(err); return; } fs.readFile(tmp('a.txt'), (err, buf) => { if (err) { cb(err); } assert.equal('Hello!', buf.toString()); cb(); }); }); }); it('should add a new line at the end of the file if none', async() => { for (let file of files) { await write(file, 'Hello!', { newline: true }); let contents = fs.readFileSync(file, 'utf8'); assert.equal('Hello!\n', contents.toString()); } }); }); describe('sync', () => { it('should write files using .sync', () => { files.forEach(file => { write.sync(file, 'content...'); assert(fs.existsSync(file)); }); }); it('should not overwrite existing files when specified', () => { files.forEach(file => { write.sync(file, 'content...'); assert(fs.existsSync(file)); assert.throws(() => { write.sync(file, 'content...', { overwrite: false }); }); }); }); it('should not overwrite existing files when specified', () => { files.forEach(file => { write.sync(file, 'content...'); assert(fs.existsSync(file)); const result = write.sync(file, 'content...', { increment: true }); assert.notEqual(file, result.path); assert(fs.existsSync(result.path)); }); }); }); describe('stream', () => { it('should write files using .stream', async() => { const promise = file => { return new Promise((resolve, reject) => { toStream('this is content...') .pipe(write.stream(file)) .on('close', resolve) .on('error', reject); }); }; for (let file of files) { await promise(file); assert(fs.existsSync(file)); let contents = fs.readFileSync(file, 'utf8'); assert.equal('this is content...', contents.toString()); } }); it('should overwrite an existing file', async() => { const fixtures = [...files, 'e.md', 'e.md'].map(n => tmp(n)); const promise = file => { return new Promise((resolve, reject) => { toStream('this is content...') .pipe(write.stream(file)) .on('close', resolve) .on('error', reject); }); }; for (let file of fixtures) { await promise(file); assert(fs.existsSync(file)); let contents = fs.readFileSync(file, 'utf8'); assert.equal('this is content...', contents.toString()); } }); }); });