1 | 'use strict';
|
2 |
|
3 | const fs = require('fs');
|
4 | const path = require('path');
|
5 | const increment = require('add-filename-increment');
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 | const write = (filepath, data, options, callback) => {
|
42 | if (typeof options === 'function') {
|
43 | callback = options;
|
44 | options = {};
|
45 | }
|
46 |
|
47 | const opts = { encoding: 'utf8', ...options };
|
48 | const destpath = opts.increment ? incrementName(filepath, options) : filepath;
|
49 | const result = { path: destpath, data };
|
50 |
|
51 | if (opts.overwrite === false && exists(filepath, destpath)) {
|
52 | throw new Error('File already exists: ' + destpath);
|
53 | }
|
54 |
|
55 | const promise = mkdir(path.dirname(destpath), { recursive: true, ...options })
|
56 | .then(() => {
|
57 | return new Promise((resolve, reject) => {
|
58 | fs.createWriteStream(destpath, opts)
|
59 | .on('error', err => reject(err))
|
60 | .on('close', resolve)
|
61 | .end(ensureNewline(data, opts));
|
62 | });
|
63 | });
|
64 |
|
65 | if (typeof callback === 'function') {
|
66 | promise.then(() => callback(null, result)).catch(callback);
|
67 | return;
|
68 | }
|
69 |
|
70 | return promise.then(() => result);
|
71 | };
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | write.sync = (filepath, data, options) => {
|
89 | if (typeof filepath !== 'string') {
|
90 | throw new TypeError('expected filepath to be a string');
|
91 | }
|
92 |
|
93 | const opts = { encoding: 'utf8', ...options };
|
94 | const destpath = opts.increment ? incrementName(filepath, options) : filepath;
|
95 |
|
96 | if (opts.overwrite === false && exists(filepath, destpath)) {
|
97 | throw new Error('File already exists: ' + destpath);
|
98 | }
|
99 |
|
100 | mkdirSync(path.dirname(destpath), { recursive: true, ...options });
|
101 | fs.writeFileSync(destpath, ensureNewline(data, opts), opts);
|
102 | return { path: destpath, data };
|
103 | };
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 | write.stream = (filepath, options) => {
|
128 | if (typeof filepath !== 'string') {
|
129 | throw new TypeError('expected filepath to be a string');
|
130 | }
|
131 |
|
132 | const opts = { encoding: 'utf8', ...options };
|
133 | const destpath = opts.increment ? incrementName(filepath, options) : filepath;
|
134 |
|
135 | if (opts.overwrite === false && exists(filepath, destpath)) {
|
136 | throw new Error('File already exists: ' + filepath);
|
137 | }
|
138 |
|
139 | mkdirSync(path.dirname(destpath), { recursive: true, ...options });
|
140 | return fs.createWriteStream(destpath, opts);
|
141 | };
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 | const incrementName = (destpath, options = {}) => {
|
148 | if (options.increment === true) options.increment = void 0;
|
149 | return increment(destpath, options);
|
150 | };
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 | const ensureNewline = (data, options) => {
|
157 | if (!options || options.newline !== true) return data;
|
158 | if (typeof data !== 'string' && !isBuffer(data)) {
|
159 | return data;
|
160 | }
|
161 |
|
162 |
|
163 |
|
164 |
|
165 | if (String(data.slice(-1)) !== '\n') {
|
166 | if (typeof data === 'string') {
|
167 | return data + '\n';
|
168 | }
|
169 | return data.concat(Buffer.from('\n'));
|
170 | }
|
171 |
|
172 | return data;
|
173 | };
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 | const exists = (filepath, destpath) => {
|
180 | return filepath === destpath && fs.existsSync(filepath);
|
181 | };
|
182 |
|
183 | const mkdir = (dirname, options) => {
|
184 | return new Promise(resolve => fs.mkdir(dirname, options, () => resolve()));
|
185 | };
|
186 |
|
187 | const mkdirSync = (dirname, options) => {
|
188 | try {
|
189 | fs.mkdirSync(dirname, options);
|
190 | } catch (err) { }
|
191 | };
|
192 |
|
193 | const isBuffer = data => {
|
194 | if (data.constructor && typeof data.constructor.isBuffer === 'function') {
|
195 | return data.constructor.isBuffer(data);
|
196 | }
|
197 | return false;
|
198 | };
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 | module.exports = write;
|