Package Exports
- nofs
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (nofs) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
nofs
Overview
nofs extends Node's native fs module with some useful methods. It tries
to make your function programming experience better.
Features
- Introduce
mapandreduceto folders. - Recursive
move,copy,remove, etc. - Promise by default.
- Unified API. Support Promise, Sync and Callback paradigms.
Install
npm install nofsAPI Convention
Unix Path Separator
When the system is Windows and process.env.force_unix_sep != 'off', nofs will force all the path separator to /, such as C:\a\b will be transformed to C:/a/b.
Promise, Sync and Callback
Any function that has a Sync version will has a promise version that ends with P.
For example the fs.remove will have fs.removeSync for sync IO, and fs.removeP for Promise.
eachDir
It is the core function for directory manipulation. Other abstract functions
like mapDir, reduceDir, readDirs are built on top of it. You can play
with it if you don't like other functions.
nofs vs Node Native fs
nofs only extends the native module, no pollution will be found. You can
still call nofs.readFile as easy as pie.
Inheritance of Options
A Function's options may inherit other function's, especially the functions it calls internally. Such as the readDirs extends the eachDir's
option, therefore readDirs also has a filter option.
Quick Start
# You can replace "require('fs')" with "require('nofs')"
fs = require 'nofs'
# Callback
fs.outputFile 'x.txt', 'test', (err) ->
console.log 'done'
# Sync
fs.readFileSync 'x.txt'
fs.copySync 'dir/a', 'dir/b'
# Promise
fs.mkdirsP 'deep/dir/path'
.then ->
fs.outputFileP 'a.txt', 'hello world'
.then ->
fs.moveP 'a.txt', 'b.txt'
.then ->
fs.copyP 'b.txt', 'c.js'
.then ->
# Get all txt files.
fs.readDirsP 'deep', { filter: /\.txt$/ }
.then (list) ->
console.log list
.then ->
fs.removeP 'deep'Changelog
Goto changelog
API
No native fs funtion will be listed.
nofs
Overview
I hate to reinvent the wheel. But to purely use promise, I don't have many choices.
Promise
Here I use [Bluebird][Bluebird] only as an ES6 shim for Promise. No APIs other than ES6 spec will be used. In the future it will be removed. [Bluebird]: https://github.com/petkaantonov/bluebird
copyDirP
Copy an empty directory.
param:
src{ String }param:
dest{ String }param:
opts{ Object }{ isForce: false mode: auto }return: { Promise }
copyDirSync
See
copyDirP.copyFileP
Copy a single file.
param:
src{ String }param:
dest{ String }param:
opts{ Object }{ isForce: false mode: auto }return: { Promise }
copyFileSync
See
copyDirP.copyP
Like
cp -r.param:
from{ String }Source path.
param:
to{ String }Destination path.
param:
opts{ Object }Extends the options of
eachDir. Defaults:{ # Overwrite file if exists. isForce: false }return: { Promise }
copySync
See
copyP.dirExistsP
Check if a path exists, and if it is a directory.
param:
path{ String }return: { Promise }
Resolves a boolean value.
dirExistsSync
Check if a path exists, and if it is a directory.
param:
path{ String }return: { boolean }
eachDirP
Walk through a path recursively with a callback. The callback can return a Promise to continue the sequence. The resolving order is also recursive, a directory path resolves after all its children are resolved.
param:
spath{ String }The path may point to a directory or a file.
param:
opts{ Object }Optional. Defaults:
{ # Include entries whose names begin with a dot (.). all: false # To filter paths. It can also be a RegExp or a glob pattern string. # When it's a string, it extends the Minimatch's options. filter: (fileInfo) -> true # The current working directory to search. cwd: '' # Whether to include the root directory or not. isIncludeRoot: true # Whehter to follow symbol links or not. isFollowLink: true # Iterate children first, then parent folder. isReverse: false # When isReverse is false, it will be the previous fn resolve value. val: any # If it return false, sub-entries won't be searched. # When the `filter` option returns false, its children will # still be itered. But when `searchFilter` returns false, children # won't be itered by the fn. searchFilter: (fileInfo) -> true # Such as force `C:\test\path` to `C:/test/path`. # This option only works on Windows. isForceUnixSep: isWin and process.env.force_unix_sep == 'off' }param:
fn{ Function }(fileInfo) -> Promise | Any. ThefileInfoobject has these properties:{ path, isDir, children, stats }. Assume thefnis(f) -> f, the directory object array may look like:{ path: 'dir/path' name: 'path' isDir: true val: 'test' children: [ { path: 'dir/path/a.txt', name: 'a.txt', isDir: false, stats: { ... } } { path: 'dir/path/b.txt', name: 'b.txt', isDir: false, stats: { ... } } ] stats: { size: 527 atime: Mon, 10 Oct 2011 23:24:11 GMT mtime: Mon, 10 Oct 2011 23:24:11 GMT ctime: Mon, 10 Oct 2011 23:24:11 GMT ... } }The
statsis a nativenofs.Statsobject.return: { Promise }
Resolves a directory tree object.
example:
# Print all file and directory names, and the modification time. nofs.eachDirP 'dir/path', (obj, stats) -> console.log obj.path, stats.mtime # Print path name list. nofs.eachDirP 'dir/path', (curr) -> curr .then (tree) -> console.log tree # Find all js files. nofs.eachDirP 'dir/path', { filter: '**/*.js', nocase: true }, ({ path }) -> console.log paths # Find all js files. nofs.eachDirP 'dir/path', { filter: /\.js$/ }, ({ path }) -> console.log paths # Custom filter nofs.eachDirP 'dir/path', { filter: ({ path, stats }) -> path.slice(-1) != '/' and stats.size > 1000 }, (path) -> console.log path
eachDirSync
See
eachDirP.return: { Object | Array }
A tree data structure that represents the files recursively.
fileExistsP
Check if a path exists, and if it is a file.
param:
path{ String }return: { Promise }
Resolves a boolean value.
fileExistsSync
Check if a path exists, and if it is a file.
param:
path{ String }return: { boolean }
globP
Get files by patterns.
param:
pattern{ String | Array }The minimatch pattern.
param:
opts{ Object }Extends the options of
eachDir. But thefilterproperty will be fixed with the pattern. Defaults:{ all: false # The minimatch option object. minimatch: {} }param:
fn{ Function }(fileInfo, list) -> Promise | Any. It will be called after each match. By default it is:(fileInfo, list) -> list.push fileInfo.pathreturn: { Promise }
Resolves the list array.
example:
# Get all js files. nofs.globP('**/*.js').then (paths) -> console.log paths # Custom the iterator. Append '/' to each directory path. nofs.globP('**/*.js', (info, list) -> list.push if info.isDir info.path + '/' else info.path ).then (paths) -> console.log paths
globSync
See
globP.return: { Array }
The list array.
mapDirP
Map file from a directory to another recursively with a callback.
param:
from{ String }The root directory to start with.
param:
to{ String }This directory can be a non-exists path.
param:
opts{ Object }Extends the options of
eachDir. Butcwdis fixed with the same as thefromparameter.param:
fn{ Function }(src, dest, fileInfo) -> Promise | AnyThe callback will be called with each path. The callback can return aPromiseto keep the async sequence go on.return: { Promise }
Resolves a tree object.
example:
# Copy and add license header for each files # from a folder to another. nofs.mapDirP( 'from' 'to' (src, dest, fileInfo) -> return if fileInfo.isDir nofs.readFileP(src).then (buf) -> buf += 'License MIT\n' + buf nofs.writeFileP dest, buf )
mapDirSync
See
mapDirP.return: { Object | Array }
A tree object.
minimatch
The
minimatchlib. Documentation Offline Documentation- type: { Funtion }
mkdirsP
Recursively create directory path, like
mkdir -p.param:
path{ String }param:
mode{ String }Defaults:
0o777 & ~process.umask()return: { Promise }
mkdirsSync
See
mkdirsP.moveP
Moves a file or directory. Also works between partitions. Behaves like the Unix
mv.param:
from{ String }Source path.
param:
to{ String }Destination path.
param:
opts{ Object }Extends the options of
eachDir. Defaults:{ isForce: false }return: { Promise }
It will resolve a boolean value which indicates whether this action is taken between two partitions.
moveSync
See
moveP.outputFileP
Almost the same as
writeFile, except that if its parent directories do not exist, they will be created.param:
path{ String }param:
data{ String | Buffer }param:
opts{ String | Object }Same with the
nofs.writeFile.return: { Promise }
outputFileSync
See
outputFileP.outputJsonP
Write a object to a file, if its parent directory doesn't exists, it will be created.
param:
path{ String }param:
obj{ Any }The data object to save.
param:
opts{ Object | String }Extends the options of
outputFileP. Defaults:{ replacer: null space: null }return: { Promise }
outputJsonSync
See
outputJSONP.readDirsP
Read directory recursively.
param:
root{ String }param:
opts{ Object }Extends the options of
eachDir. Defaults:{ # Don't include the root directory. isIncludeRoot: false isCacheStats: false }If
isCacheStatsis set true, the returned list array will have an extra propertystatsCache, it is something like:{ 'path/to/entity': { dev: 16777220 mode: 33188 ... } }The key is the entity path, the value is the
nofs.Statsobject.return: { Promise }
Resolves an path array.
example:
# Basic nofs.readDirsP 'dir/path' .then (paths) -> console.log paths # output => ['dir/path/a', 'dir/path/b/c'] # Same with the above, but cwd is changed. nofs.readDirsP 'path', { cwd: 'dir' } .then (paths) -> console.log paths # output => ['path/a', 'path/b/c'] # CacheStats nofs.readDirsP 'dir/path', { isCacheStats: true } .then (paths) -> console.log paths.statsCache['path/a']
readDirsSync
See
readDirsP.return: { Array }
Path string array.
readJsonP
Read A Json file and parse it to a object.
param:
path{ String }param:
opts{ Object | String }Same with the native
nofs.readFile.return: { Promise }
Resolves a parsed object.
example:
nofs.readJsonP('a.json').then (obj) -> console.log obj.name, obj.age
readJsonSync
See
readJSONP.return: { Any }
The parsed object.
reduceDirP
Walk through directory recursively with a callback.
param:
path{ String }param:
opts{ Object }Extends the options of
eachDir, with some extra options:{ # The init value of the walk. init: undefined }param:
fn{ Function }(prev, path, isDir, stats) -> Promisereturn: { Promise }
Final resolved value.
example:
# Concat all files. nofs.reduceDirP 'dir/path', { init: '' }, (val, info) -> return val if info.isDir nofs.readFileP(info.path).then (str) -> val += str + '\n' .then (ret) -> console.log ret
reduceDirSync
See
reduceDirPreturn: { Any }
Final value.
removeP
Remove a file or directory peacefully, same with the
rm -rf.param:
path{ String }param:
opts{ Object }Extends the options of
eachDir. But theisReverseis fixed withtrue.return: { Promise }
removeSync
See
removeP.touchP
Change file access and modification times. If the file does not exist, it is created.
param:
path{ String }param:
opts{ Object }Default:
{ atime: Date.now() mtime: Date.now() mode: undefined }return: { Promise }
If new file created, resolves true.
touchSync
See
touchP.return: { Boolean }
Whether a new file is created or not.
watchFileP
Watch a file. If the file changes, the handler will be invoked. You can change the polling interval by using
process.env.pollingWatch. Useprocess.env.watchPersistent = 'off'to disable the persistent. Why not usenofs.watch? Becausenofs.watchis unstable on some file systems, such as Samba or OSX.param:
path{ String }The file path
param:
handler{ Function }Event listener. The handler has these params:
- file path
- current
nofs.Stats - previous
nofs.Stats - if its a deletion
param:
autoUnwatch{ Boolean }Auto unwatch the file while file deletion. Default is true.
return: { Promise }
It resolves the wrapped watch listener.
example:
process.env.watchPersistent = 'off' nofs.watchFileP 'a.js', (path, curr, prev, isDeletion) -> if curr.mtime != prev.mtime console.log path
watchFilesP
Watch files, when file changes, the handler will be invoked. It is build on the top of
nofs.watchFileP.param:
patterns{ Array }String array with minimatch syntax. Such as
['*/**.css', 'lib/**/*.js'].param:
handler{ Function }return: { Promise }
It contains the wrapped watch listeners.
example:
nofs.watchFiles '*.js', (path, curr, prev, isDeletion) -> console.log path
watchDirP
Watch directory and all the files in it. It supports three types of change: create, modify, move, delete. By default,
moveevent is disabled. It is build on the top ofnofs.watchFileP.param:
opts{ Object }Defaults:
{ dir: '.' pattern: '**' # minimatch, string or array # Whether to watch POSIX hidden file. dot: false # If the "path" ends with '/' it's a directory, else a file. handler: (type, path, oldPath) -> # The minimatch options. minimatch: {} isEnableMoveEvent: false }return: { Promise }
Resolves a object that keys are paths, values are listeners.
example:
# Only current folder, and only watch js and css file. nofs.watchDir { dir: 'lib' pattern: '*.+(js|css)' handler: (type, path) -> console.log type console.log path }
writeFileP
A
writeFileshim for< Node v0.10.param:
path{ String }param:
data{ String | Buffer }param:
opts{ String | Object }return: { Promise }
writeFileSync
See
writeFileP
Function Alias
For some naming convention reasons, nofs also uses some common alias for fucntions. See src/alias.coffee.
Benckmark
Lisence
MIT