oofs

10.4.2 • Public • Published

oofs

npm version

A filesystem abstraction that makes directory traversal and other common tasks first-class citizens, representing files and directories as objects, and avoids the need for manipulating file paths as strings or worrying about whether a path is relative or absolute.

Some things you can do with oofs:

  • Rename all files in a directory with a replacement regex/callback function.
  • Work with .json files. Read and write the whole file, and update nested properties in one line.
  • Quickly navigate from node to node with .parent, .child(relativePath) and others.
  • Walk through all files, directories, or both; recursively or at the top level.

All methods have sync and async versions where it makes sense, and you can set sync to be the default to avoid typing the Sync suffix everywhere.

A quick example (full reference below):

// require the library
var oofs = require('oofs');

// create an instance with the 'defaultSync' option
// turned on to avoid "Sync" suffixes
var fs = oofs(true);

// create a Node representing /home/user
var dir = fs('/home/user');

// do something with all the files and directories:
dir.all(function(node) {
	node.isDir(); // boolean
	node.fullPath; // e.g. "/home/user/dir/file.txt"
	node.all; // the same as dir.all (everything is a Node)
	node.pathFrom(dir); // "dir/file.txt"
	node.read(); // the contents of the file
	node.write('new contents');
});

There are some useful variants of all for dealing with only files, only directories, only direct children, etc:

dir.each(function(node) {
	// all files and directories directly under dir
});

dir.allFiles(function(node) {
	// all files recursively
});

Many of the methods from fs are available on nodes, with the only difference being the lack of a path parameter:

var file = fs('/home/user/file.txt');

file.write(data, 'utf8');

You can get the absolute path (as a string) from node.fullPath.

You can get a new Node representing a node's parent directory from node.parent.

You can run functions conditionally using ifDir and ifFile:

node.ifDir(function() {
	// runs if the node is a directory
});

node.ifFile(function() {
	// runs if the node is a file
});

API Reference

####Contents

#####index

#####Node

index

####oofs([options | defaultSync=false])

The package is a function that returns an instance of the library, and accepts an optional config object with the following defaults:

{
	defaultSync: false,
	mkdirs: false,
	mkdirpOptions: {}
}

The mkdirs option uses mkdirp to make sure any parent directories are created before writing to a file with write, writeJson, etc. mkdirpOptions gets passed through to mkdirp.

You can also pass a single boolean, which will be used as the defaultSync option.

var oofs = require("oofs");

var syncApi = oofs(true);
var asyncApi = oofs();

syncApi("file.txt").read(); // returns file contents
asyncApi("file.txt").read(function(contents) { /* calls back with contents \*/ });

oofs({
	mkdirs: true
})("/path/to/non-existent/dir/file.txt").write("data", function() {
	// /path/to/non-existent/dir will be created before writing the file
});

Sync and async versions are always available with a suffix, e.g. readSync or readAsync.

Pre-initialised libraries

To skip the step of calling the package with options to generate a library instance, you can require one or more of the following:

var syncApi = require("oofs/sync");
var asyncApi = require("oofs/async");
var syncApiWithMkdirs = require("oofs/sync-mkdirs");
var asyncApiWithMkdirs = require("oofs/async-mkdirs");

var file = syncApiWithMkdirs("./path/to/file.txt");

file.write("etc");

Node

Some of the methods below have a synchronous version that returns the result, but will also pass it to a callback if one is supplied, so your code doesn't have to know whether defaultSync is on.

###Properties and getters

####fullPath

The full, absolute path to the file or directory.

####name

The full name, e.g. "file.txt".

####basename

The name without the extension e.g. "file".

####extension

The file extension e.g. ".txt", or an empty string if there is no extension.

####isRoot

Whether the node represents the root (/).

####parent

A Node representing the node's parent. If the node is root, parent is a reference back to the same node.

fs('/path/to/file').parent.fullPath; // '/path/to'

####pathFrom(referenceNode | path)

Returns the relative path to the node from the supplied referenceNode or path.

var file = fs('/home/user/dir/file.txt');
var anotherDir = fs('/home/user/another-dir');

file.pathFrom(anotherDir); // "../dir/file.txt"
file.pathFrom('/home'); // "user/dir/file.txt"

####child(relativePath)

Returns a Node representing the path at relativePath, relative to the node's path.

fs('/home/user')
	.child('dir/file.txt').fullPath; // "/home/user/dir/file.txt"

####rel(relativePath)

The same as child but without the implied nesting in the name.

fs('/home/user')
	.rel('dir/file.txt').fullPath; // "/home/user/dir/file.txt"

fs('/home/user')
	.rel('../another-user').fullPath; // "/home/another-user"

####sibling(relativePath)

A child of the node's parent.

fs('/home/user/dir/file.txt')
	.sibling('another-file.txt').fullPath; // "/home/user/dir/another-file.txt"

####within(parentPath|parentNode)

Checks whether the Node is a descendant of the supplied path or Node.

fs('/home/user/dir/file.txt').within('/home/user'); // true

###Directory traversal

These methods all have an identical Sync version -- the signature is the same (allSync, allDirsSync, etc).

####all(callback(node))

Calls callback with all files and directories under the node.

####allDirs(callback(node))

Calls callback with all directories under the node.

####allFiles(callback(node))

Calls callback with all files under the node.

####each(callback(node))

Calls callback with each file and directory directly under the node (not recursive).

####eachDir(callback(node))

Calls callback with each directory directly under the node (not recursive).

####eachFile(callback(node))

Calls callback with each file directly under the node (not recursive).

###Conditionals and checks

####ifDir(callback())

Calls callback if the node is a directory.

####ifFile(callback())

Calls callback if the node is a file.

####isDir(callback(boolean))

Calls callback with a boolean indicating whether the node is a directory.

####isDirSync([callback(boolean)])

Sync version with optional callback.

####isFile(callback(boolean))

Calls callback with a boolean indicating whether the node is a file.

####isFileSync([callback(boolean)])

Sync version with optional callback.

###General utilities

All have Sync versions (e.g. filterSync) with optional callbacks.

####filter(filter(node), callback(nodes))

Calls the supplied filter function on each direct child node, then calls the callback with an array of all the nodes for which the filter returned true.

####readdir(callback(filenames))

Calls the callback with an array of filenames directly under the node.

####ls(callback(nodes))

Calls callback with an array of Nodes representing the files and directories directly under the node.

####lsDirs(callback(nodes))

Calls callback with an array of Nodes representing the directories directly under the node.

####lsFiles(callback(nodes))

Calls callback with an array of Nodes representing the files directly under the node.

####lsAll([callback(nodes)])

Returns an array of Nodes for all files and directories recursively under the node. Synchronous only: there is currently no async version of this method. There are also file- and directory-specific variants lsAllDirs and lsAllFiles that work as expected.

####contains(filename)

Whether the directory contains a file or directory called filename.

fs('site/views').contains('index.pug'); // true

####stat, lstat, statSync & lstatSync([callback(fs.Stats, error)])

These methods wrap the corresponding fs methods, with the arguments to the async callback reversed ((result, error)) for consistency with the optional sync callback.

oofs(true)('/some/file.txt').stat().isFile(); // boolean

oofs()('/some/file.txt').stat(function(stats) {
	stats.isFile(); // boolean
});

###Reading, writing, renaming and deleting

All have async versions with a callback as the last argument, and Sync versions with an optional callback.

####delete([callback])

Deletes the file or directory. Use unlink and rmdir for file- and directory-specific versions, avoiding the need to check which type the node is.

####write(text[, callback])

Writes text to the file, creating it if necessary.

####read([callback(contents)])

Returns or calls back with a string of the contents of the file.

####replace(find, replace[, callback])

Does a find/replace on the contents of the file using String.replace.

####writeJson(object[, callback])

Writes the JSON-stringification of object to the file.

####readJson([callback(object)])

Returns the JSON-parsed contents of the file.

####updateJson(path, value[, callback])

Set the value at path to value, where path is a dot-separated string of object properties and/or array indexes. A value of undefined will delete the object property or splice out the array item at path.

For example, if config.json contains the following:

{
	"db": {
		"host": "localhost"
	}
}

Calling fs('config.json').updateJson('db.host', 'example.com') will change it to:

{
	"db": {
		"host": "example.com"
	}
}

Calling updateJson('db.host', undefined) will change it to:

{
	"db": {}
}

####rename(newPath[, callback])

Renames the file or directory. newPath is calculated as a relative path from the node's parent.

var file = fs('/home/user/dir/file.txt');

file.rename('file2.txt');

file.fullPath; // /home/user/dir/file2.txt

file.rename('../another-dir/file.txt'); // moving to another directory

file.fullPath; // /home/user/another-dir/file.txt

####rename(find, replace[, callback])

Renames the file or directory by calling String.replace on the name (filename with extension).

For example, switching file extensions to migrate from Jade to Pug:

fs('./views').all(function(node) {
	node.rename('.jade', '.pug');
});

Regular expressions and replacement callbacks can be used:

fs('/IMG0001.jpg').rename(/([A-Z]+)0*(\d+)/, function(all, name, n) {
	return name.toLowerCase() + '-' + n;
}).name; // img-1.jpg

####empty()

Synchronous only. Recursively deletes everything in the directory.

Package Sidebar

Install

npm i oofs

Weekly Downloads

3

Version

10.4.2

License

none

Last publish

Collaborators

  • npm