1 | # wrote
|
2 |
|
3 | [![npm version](https://badge.fury.io/js/wrote.svg)](https://badge.fury.io/js/wrote)
|
4 |
|
5 | Promise-based write and read operations for Node.js
|
6 |
|
7 | ## ES5
|
8 |
|
9 | The package uses some newer language features. For your convenience, it's been
|
10 | transpiled to be compatible with Node 4. You can use the following snippet.
|
11 |
|
12 | ```js
|
13 | const wrote = require('wrote/es5/src/')
|
14 | ```
|
15 |
|
16 | ## `wrote.createWritable(path=: string): Promise.<Writable>`
|
17 |
|
18 | Create an open Writable stream to the file.
|
19 |
|
20 | ```js
|
21 | const { Writable } = require('stream')
|
22 | const path = require('path')
|
23 | const HOME_DIR = require('os').homedir()
|
24 | const { createWritable } = require('wrote')
|
25 |
|
26 | const file = path.join(HOME_DIR, `wrote-${Math.floor(Math.random() * 1e5)}.data`);
|
27 |
|
28 | (async () => {
|
29 | const ws = await createWritable(file)
|
30 | console.log(ws instanceof Writable) // true
|
31 | console.log(ws.path) // ~/wrote-35558.data
|
32 | })()
|
33 | ```
|
34 |
|
35 | If you don't have a file, a new one in the temp directory will be created for you.
|
36 |
|
37 | ```js
|
38 | (async () => {
|
39 | const ws = await createWritable()
|
40 | console.log(ws instanceof Writable) // true
|
41 | console.log(ws.path) // /var/folders/s0/1h2g/T/wrote-48315.data
|
42 | })()
|
43 | ```
|
44 |
|
45 | ## `wrote.exists(path: string): Promise.<boolean>`
|
46 |
|
47 | Check if the path on the filesystem exists. Throws if path is not accessible
|
48 | due to permissions.
|
49 |
|
50 | ```js
|
51 | const { exists } = require('wrote');
|
52 |
|
53 | (async () => {
|
54 | await exists('unknown-path') // false
|
55 | await exists(__filename) // true
|
56 | await exists(__dirname) // true
|
57 | })()
|
58 | ```
|
59 |
|
60 | ## `wrote.assertExists(path: string): Promise`
|
61 |
|
62 | Check if the path on the filesystem exists, and throw if it does not, or cannot
|
63 | be accessed.
|
64 |
|
65 | ```js
|
66 | const { assertExists } = require('wrote');
|
67 |
|
68 | (async () => {
|
69 | try {
|
70 | await assertExists('unknown-path')
|
71 | } catch (err) {
|
72 | console.log(err) // Path unknown-path does not exist.
|
73 | }
|
74 | await assertExists(__filename) // ok
|
75 | })()
|
76 | ```
|
77 |
|
78 | ## `wrote.assertDoesNotExist(path: string): Promise`
|
79 |
|
80 | Check if the path on the filesystem does not exists, and throw if it does, or
|
81 | cannot be accessed.
|
82 |
|
83 | ```js
|
84 | const { assertDoesNotExist } = require('wrote');
|
85 |
|
86 | (async () => {
|
87 | try {
|
88 | await assertDoesNotExist(__filename)
|
89 | } catch (err) {
|
90 | console.log(err) // Path /wrote/examples/assert-does-not-exist.js exists.
|
91 | }
|
92 | await assertDoesNotExist('unknown-file') // ok
|
93 | })()
|
94 | ```
|
95 |
|
96 | ## `wrote.clone({ from: string, to: string, regexes: [] }): Promise`
|
97 |
|
98 | Clone a directory by copying contents of files and creating symlinks. Regular
|
99 | expressions can be used to transform data being copied.
|
100 |
|
101 | ```js
|
102 | const { clone } = require('wrote');
|
103 |
|
104 | (async () => {
|
105 | const from = './directory'
|
106 | const to = './clone'
|
107 |
|
108 | await clone({
|
109 | from,
|
110 | to,
|
111 | regexes: [
|
112 | {
|
113 | re: /{{ name }}/g, // use /g flag for global replacements
|
114 | replacement: 'Garry',
|
115 | },
|
116 | {
|
117 | re: /{{ age }}/,
|
118 | replacement: '30',
|
119 | },
|
120 | ],
|
121 | })
|
122 | // or,
|
123 | // await clone({ to, from })
|
124 | })()
|
125 | ```
|
126 |
|
127 | ## `wrote.erase(ws: Writable): Promise.<Writable>`
|
128 |
|
129 | Erase file and close stream.
|
130 |
|
131 | ```js
|
132 | const { createWritable, erase } = require('wrote')
|
133 | const { Writable } = require('stream')
|
134 | const path = require('path')
|
135 | const HOME_DIR = require('os').homedir()
|
136 |
|
137 | const file = path.join(HOME_DIR, `wrote-${Math.floor(Math.random() * 1e5)}.data`);
|
138 |
|
139 | (async () => {
|
140 | const ws = await createWritable(file)
|
141 | console.log(ws instanceof Writable) // true
|
142 | console.log(ws.writable) // true
|
143 | console.log(ws.path) // ~/wrote-35558.data
|
144 | await erase(ws)
|
145 | console.log(ws.closed) // true
|
146 | })()
|
147 |
|
148 | ```
|
149 |
|
150 | ## `wrote.write(ws: Writable, data?: string|Readable): Promise.<Writable>`
|
151 |
|
152 | Pipe a `Readable` to the `Writable` stream and wait until it is finished, or end
|
153 | `Writable` with given data (pass `null` to end stream without any more data).
|
154 |
|
155 | ```js
|
156 | const { write } = require('wrote')
|
157 | const assert = require('assert')
|
158 | const { Writable } = require('stream')
|
159 |
|
160 | const testString = 'hello world'
|
161 | const buffer = Buffer.from(testString)
|
162 | const allRawData = []
|
163 | const ws = new Writable({
|
164 | write(chunk, encoding, next) {
|
165 | allRawData.push(chunk)
|
166 | next()
|
167 | },
|
168 | });
|
169 |
|
170 | (async () => {
|
171 | await write(ws, buffer)
|
172 | console.log(allRawData.map(d => String(d))) // [ 'hello world' ]
|
173 | assert.deepEqual(allRawData, [
|
174 | buffer,
|
175 | ])
|
176 | })()
|
177 | ```
|
178 |
|
179 | ## `wrote.ensurePath(filePath: string): Promise<string>`
|
180 |
|
181 | Create all required directories for the filepath to exist. If a directory on the way is
|
182 | non-executable, the Promise will be rejected. Resolves with the filepath.
|
183 |
|
184 | ```js
|
185 | const { ensurePath } = require('wrote')
|
186 | const { resolve } = require('path');
|
187 |
|
188 | (async () => {
|
189 | const path = 'path/to/temp/file.data'
|
190 | const res = await ensurePath(path)
|
191 | console.log(res) // path/to/temp/file.data, path/to/temp is created in your cwd
|
192 |
|
193 | const absolutePath = resolve(process.cwd(), 'path/to/temp/file.data')
|
194 | const res2 = await ensurePath(absolutePath)
|
195 | console.log(res2) // $(pwd)/path/to/temp/file.data
|
196 | })()
|
197 | ```
|
198 |
|
199 | ## `wrote.read(path: string, { binary?: boolean }): Promise.<string>`
|
200 |
|
201 | Read a file fully. Returns a Promise resolved with the file contents, and
|
202 | rejects if path is not a string or file not found (`ENOENT`).
|
203 |
|
204 | ```js
|
205 | const { read } = require('wrote');
|
206 |
|
207 | (async () => {
|
208 | const res = await read(__filename)
|
209 | console.log(res)
|
210 | })()
|
211 | ```
|
212 |
|
213 | `examples/read.js`: _this program will print the contents of itself_
|
214 |
|
215 | Pass `{ binary: true }` options to read as a `Buffer`:
|
216 |
|
217 | ```js
|
218 | const { read } = require('wrote');
|
219 |
|
220 | (async () => {
|
221 | const buffer = await read(__filename, { binary: true })
|
222 | console.log(buffer) // // <Buffer 63 6f 6e 73 74 20 7b ... >
|
223 | })()
|
224 | ```
|
225 |
|
226 | ## `wrote.readJSON(path: string): Promise.<object>`
|
227 |
|
228 | Read a json file and parse its contents.
|
229 |
|
230 | ```js
|
231 | const { readJSON } = require('wrote');
|
232 |
|
233 | (async () => {
|
234 | const res = await read('path/to/file.json')
|
235 | console.log(res)
|
236 | })()
|
237 | ```
|
238 |
|
239 | ## `wrote.writeJSON(path: string, object: object, { replacer?: function, space?: string|number }): Promise`
|
240 |
|
241 | Serialise an object with `JSON.stringify` and write it to a file. Pass `space`
|
242 | and `replacer` in the options object.
|
243 |
|
244 | ```js
|
245 | const { writeJSON } = require('wrote');
|
246 |
|
247 | (async () => {
|
248 | const object = {
|
249 | test: 'data',
|
250 | date: new Date(),
|
251 | }
|
252 | await writeJSON('path/to/file.json', object, {
|
253 | space: 2,
|
254 | // replacer: () => {}
|
255 | })
|
256 | })()
|
257 | ```
|
258 |
|
259 | ## `wrote.readDir(dirPath: string, recursive=: boolean): Promise<object>`
|
260 |
|
261 | Read a directory, and return contents of contained files.
|
262 |
|
263 | For example, the following directory structure:
|
264 |
|
265 | ```fs
|
266 | directory
|
267 | - subdirectory
|
268 | - subdirFileA.txt
|
269 | ` subdirFileB.txt
|
270 | - fileA.txt
|
271 | - fileB.txt
|
272 | ` fileC.txt
|
273 | ```
|
274 |
|
275 | can be read either shallowly (by default):
|
276 |
|
277 | ```js
|
278 | const { readDir } = require('wrote')
|
279 | const path = require('path')
|
280 |
|
281 | const dirPath = path.join(__dirname, 'directory');
|
282 |
|
283 | (async () => {
|
284 | const res = await readDir(dirPath)
|
285 | console.log(res)
|
286 | // { 'fileA.txt': 'fileA\n',
|
287 | // 'fileB.txt': 'fileB\n',
|
288 | // 'fileC.txt': 'fileC\n' }
|
289 | })()
|
290 | ```
|
291 |
|
292 | or recursively:
|
293 |
|
294 | ```js
|
295 | (async () => {
|
296 | const res = await readDir(dirPath, true)
|
297 | console.log(res)
|
298 | // { 'fileA.txt': 'fileA\n',
|
299 | // 'fileB.txt': 'fileB\n',
|
300 | // 'fileC.txt': 'fileC\n',
|
301 | // subdirectory:
|
302 | // { 'subdirFileA.txt': 'subdirFileA\n',
|
303 | // 'subdirFileB.txt': 'subdirFileB\n' } }
|
304 | })()
|
305 | ```
|
306 |
|
307 | ## `wrote.readDirStructure(dirPath: string): Promise<DirectoryStructure>`
|
308 |
|
309 | Get the full structure of the directory recursively. An array of either
|
310 | file names as strings, or an object representing all directories of the
|
311 | current one, with keys being their names, and values being arrays similar
|
312 | to the root one.
|
313 |
|
314 | ```js
|
315 | const path = require('path')
|
316 | const { readDirStructure } = require('..')
|
317 |
|
318 | const DIR_PATH = path.join(__dirname, '../test/fixtures/directory');
|
319 |
|
320 | /**
|
321 | * Read directory's structure.
|
322 | */
|
323 |
|
324 | (async () => {
|
325 | const res = await readDirStructure(DIR_PATH)
|
326 | console.log(JSON.stringify(res, null, 2))
|
327 | })()
|
328 | ```
|
329 |
|
330 | ```fs
|
331 | {
|
332 | "type": "Directory",
|
333 | "content": {
|
334 | "subdirectory-ln": {
|
335 | "type": "SymbolicLink"
|
336 | },
|
337 | "test-ln.data": {
|
338 | "type": "SymbolicLink"
|
339 | },
|
340 | "test.data": {
|
341 | "type": "File"
|
342 | },
|
343 | "subdirectory": {
|
344 | "type": "Directory",
|
345 | "content": {
|
346 | "file.data": {
|
347 | "type": "File"
|
348 | },
|
349 | "file2.data": {
|
350 | "type": "File"
|
351 | }
|
352 | }
|
353 | },
|
354 | "subdirectory2": {
|
355 | "type": "Directory",
|
356 | "content": {
|
357 | "file3.data": {
|
358 | "type": "File"
|
359 | },
|
360 | "subsubdir": {
|
361 | "type": "Directory",
|
362 | "content": {
|
363 | "file4.py": {
|
364 | "type": "File"
|
365 | }
|
366 | }
|
367 | },
|
368 | "subsubdir2": {
|
369 | "type": "Directory",
|
370 | "content": {}
|
371 | }
|
372 | }
|
373 | }
|
374 | }
|
375 | }
|
376 | ```
|
377 |
|
378 | ## todo
|
379 |
|
380 | - `eraseDir` to rm -rf
|
381 | - `cloneFile` to clone a single file
|
382 | - `write` with string as path
|
383 | - `erase` with string as path
|
384 | - `clone` with permissions
|
385 | - pass options to `fs.createWriteStream` in `wrote.createWritable`
|
386 |
|
387 | ---
|
388 |
|
389 | Licence: MIT
|
390 |
|
391 | *(c) [Sobesednik-Media](https://sobesednik.media) 2017*
|