kriskowal / q-io

Interfaces for IO using Q promises in JavaScript on Node
http://documentup.com/kriskowal/q-io
MIT License
317 stars 73 forks source link

Q-IO

npm version

Build Status

Interfaces for IO that make use of promises.

Q-IO now subsumes all of Q-HTTP and Q-FS.

The Q-IO package does not export a main module. You must reach in directly for q-io/fs, q-io/http, and q-io/http-apps.

Filesystem

var FS = require("q-io/fs");

File system API for Q promises with method signatures patterned after CommonJS/Fileystem/A but returning promises and promise streams.

open(path, options)

Open returns a promise for either a buffer or string Reader or a Writer depending on the flags.

The options can be omitted, abbreviated to a flags string, or expanded to an options object.

read(path, options)

read is a shortcut for opening a file and reading the entire contents into memory. It returns a promise for the whole file contents. By default, read provides a string decoded from UTF-8. With the bytewise mode flag, provides a Buffer.

The options argument is identical to that of open.

return FS.read(__filename, "b")
.then(function (content) {
    // ...
})
return FS.read(__filename, {
    flags: "b"
})

write(path, content, options)

write is a shortcut for opening a file and writing its entire content from a single string or buffer.

The options are identical to that of open, but the "w" flag is implied, and the "b" flag is implied if the content is a buffer.

return FS.write("hello.txt", "Hello, World!\n")
.then(function () {
    return FS.read("hello.txt")
})
.then(function (hello) {
    expect(hello).toBe("Hello, World!\n")
})

append(path, content, options)

append is a shorthand for opening a file for writing from the end of the existing content from a single string or buffer.

The options are identical to that of open, but the "w+" flags are implied, and the "b" flag is implied if the content is a buffer.

copy(source, target)

Copies a single file from one path to another. The target must be the full path, including the file name. Unlike at the shell, the file name is not inferred from the source path if the target turns out to be a directory.

Returns a promise for the completion of the operation.

copyTree(source, target)

Copies a file or tree of files from one path to another. Symbolic links are copied but not followed.

Returns a promise for the completion of the operation.

list(path)

Returns a promise for a list of file names in a directory. The file names are relative to the given path.

listTree(path, guard(path, stat))

Returns a promise for a list of files in a directory and all the directories it contains. Does not follow symbolic links.

The second argument is an optional guard function that determines what files to include and whether to traverse into another directory. It receives the path of the file, relative to the starting path, and also the stats object for that file. The guard must return a value like:

listDirectoryTree(path)

Returns a promise for a deep list of directories.

makeDirectory(path, mode)

Makes a directory at a given path. Fails if the parent directory does not exist. Returns a promise for the completion of the operation.

The mode is an optional Unix mode as an integer or string of octal digits.

makeTree(path, mode)

Finishes a path of directories. For any branch of the path that does not exist, creates a directory. Fails if any branch of the path already exists but is not a directory.

Makes any directories with the given Unix mode.

remove(path)

Removes a file at the given path. Fails if a directory exists at the given path or if no file exists at the path.

removeTree(path)

Removes a file or directory at a given path, recursively removing any contained files and directories, without following symbolic links.

rename(source, target)

Moves a file or directory from one path to another using the underlying rename(2) implementation, thus it cannot move a file across devices.

move(source, target)

Moves a file or directory from one path to another. If the source and target are on different devices, falls back to copying and removing, using copyTree(source, target) and, if completely successful, removeTree(source).

link(source, target)

Creates a hard link from the source

symbolicCopy(source, target, type)

Creates a relative symbolic link from the target to the source with an effect that resembles copying a file.

The type is important for Windows. It is "file" by default, but may be "directory" or "junction".

symbolicLink(target, link, type)

Creates a symbolic link at the target path. The link may be absolute or relative. The type must be "file", "directory", or "junction" and is mandatory to encourage Windows portability.

chown(path, uid, gid)

Changes the owner for a path using Unix user-id and group-id numbers.

chmod(path, mode)

Changes the Unix mode for a path. Returns a promise.

stat(path)

Follows all symbolic links along a path and returns a promise for the metadata about a path as a Stats object. The Stats object implements:

statLink(path)

Returns a promise for the Stats for a path without following symbolic links.

statFd(fd)

Returns a promise for the Stats for a Unix file descriptor number.

exists(path)

Follows symbolic links and returns a promise for whether an entry exists at a given path.

isFile(path)

Follows symbolic links and returns a promise for whether a file exists at a given path and does not cause an exception if nothing exists at that path.

isDirectory(path)

Follows symbolic links and returns a promise for whether a directory exists at a given path and does not cause an exception if nothing exists at that path.

isSymbolicLink(path)

Returns a promise for whether a symbolic link exists at a given path and does not cause an exception if nothing exists at that path.

lastModified(path)

Follows symbolic links and returns a promise for the Date when the entry at the given path was last opened for writing, but causes an exception if no file exists at that path.

lastAccessed(path)

Follows symbolic links and returns a promise for the Date when the entry at the given path was last opened for reading or writing, but causes an exception if no file exists at that path.

split(path)

Splits a path into the names of entries along the path. If the path is absolute, the first component is either a drive (with a colon) on Windows or an empty string for the root of a Unix file system.

join(paths) or join(...paths)

Joins a sequence of paths into a single normalized path. All but the last path are assumed to refer to directories.

resolve(...paths)

Like join but treats each path like a relative URL, so a terminating slash indicates that a path is to a directory and the next path begins at that directory.

normal(...paths)

Takes a single path or sequence of paths and joins them into a single path, eliminating self . and parent .. entries when possible.

absolute(path)

Joins and normalizes a path from the current working directory, returning a string.

canonical(path)

Returns a promise for the absolute, canonical location of a given path, following symbolic links and normalizing path components. An entry does not need to exist at the end of the path.

readLink(path)

Returns a promise for the path string of a symbolic link at a given path.

contains(parent, child)

For any two absolute or relative paths, computes whether the parent path is an ancestor of the child path.

relative(source, target)

Returns a promise for the relative path from one path to another using .. parent links where necessary. This operation is asynchronous because it is necessary to determine whether the source path refers to a directory or a file.

relativeFromFile(source, target)

Assuming that the source path refers to a file, returns a string for the relative path from the source to the target path.

relativeFromDirectory(source, target)

Assuming that the source path refers to a directory, returns a string for the relative path from the source to the target path.

isAbsolute(path)

Returns whether a path begins at the root of a Unix file system or a Windows drive.

isRelative(path)

Returns whether a path does not begin at the root of a Unix file system or Windows drive.

isRoot(path)

Returns whether a path is to the root of a Unix file system or a Windows drive.

root(path)

Returns the Windows drive that contains a given path, or the root of a Unix file system.

directory(path)

Returns the path to the directory containing the given path.

base(path, extension)

Returns the last entry of a path. If an extension is provided and matches the extension of the path, removes that extension.

extension(path)

Returns the extension for a path (everything following the last dot . in a path, unless that dot is at the beginning of the entry).

reroot(path)

Returns an attenuated file system that uses the given path as its root. The resulting file system object is identical to the parent except that the child cannot open any file that is not within the root. Hard links are effectively inside the root regardless, but symbolic links cannot be followed outside of the jail.

toObject(path)

Reads every file in the file system under a given path and returns a promise for an object that contains the absolute path and a Buffer for each of those files.

glob(pattern)

Not yet implemented

match(pattern, path)

Not yet implemented

Mock Filesystem

Q-IO provides a mock filesystem interface. The mock filesystem has the same interface as the real one and has most of the same features, but operates on a purely in-memory, in-process, in-javascript filesystem.

A mock filesystem can be created from a data structure. Objects are directories. Keys are paths. A buffer is a file’s contents. Anything else is coerced to a string, then to a buffer in the UTF-8 encoding.

var MockFs = require("q-io/fs-mock");
var mockFs = MockFs({
    "a": {
        "b": {
            "c.txt": "Content of a/b/c.txt"
        }
    },
    "a/b/d.txt": new Buffer("Content of a/b/d.txt", "utf-8")
})

You can also instantiate a mock file system with the content of a subtree of a real file system. You receive a promise for the mock filesystem.

var FS = require("q-io/fs");
FS.mock(__dirname)
.then(function (fs) {
    //
})
.done();

HTTP

The HTTP module resembles CommonJS/JSGI.

var HTTP = require("q-io/http");

Server(app)

The http module exports a Server constructor.

request(request object or url)

The http module exports a request function that returns a promise for a response.

read(request object or url)

The http module exports a read function, analogous to Fs.read(path), but returning a promise for the content of an OK HTTP response.

normalizeRequest(request object or url)

normalizeResponse(response)

Request

A complete request object has the following properties.

Response

A complete response object has the following properties.

headers

Headers are an object mapping lower-case header-names to corresponding values, possibly an array for multiple headers of the same name, for both requests and responses.

body

body is a representation of a readable stream, either for the content of a request or a response. It is implemented as a Q-IO reader.

application

An HTTP application is a function that accepts a request and returns a response. The request function itself is an application. Applications can be chained and combined to make advanced servers and clients.

Streams

Reader

Reader instances have the following methods:

Additionally, the Reader constructor has the following methods:

The reader module exports a function that accepts a Node reader and returns a Q reader.

Writer

Writer instances have the following methods:

The writer module exports a function that accepts a Node writer and returns a Q writer.

Buffer

var BufferStream = require("q-io/buffer-stream");
var stream = BufferStream(new Buffer("Hello, World!\n", "utf-8"), "utf-8")

HTTP Applications

The HTTP applications module provides a comprehensive set of JSGI-alike applications and application factories, suitable for use with the http server and client.

var Apps = require("q-io/http-apps");

ok(content, contentType, status) : Response

Creates an HTTP 200 Ok response with the given content, content type, and status.

The content may be a string, buffer, array of strings, array of buffers, a readable stream of strings or buffers, or (generally) anything that implements forEach.

The default content type is text/plain.

The default status is 200.

badRequest(request) : Response

An application that returns an HTTP 400 Bad request response for any request.

notFound(request) : Response

An application that returns an HTTP 404 Not found response for any request.

methodNotAllowed(request) : Response

An application that returns an HTTP 405 Method not allowed response for any request. This is suitable for any endpoint where there is no viable handler for the request method.

notAcceptable(request) : Response

An application that returns an HTTP 406 Not acceptable response for any request. This is suitable for any situation where content negotiation has failed, for example, if you cannot response with any of the accepted encoding, charset, or language.

redirect(request, location, status, tree) : Response

Not to be confused with an HTTP application, this is a utility that generates redirect responses.

The returns response issues a redirect to the given location. The utility fully qualifies the location.

This particular method should be used directly to generate an HTTP 301 Temporary redirect response, but passing 307 in the status argument turns it into an HTTP 307 Permanent redirect response.

This particular method should be used to send all requests to a specific location, but setting the tree argument to true causes the redirect to follow the remaining unrouted path from the redirect location, so if you move an entire directory tree from one location to another, this redirect can forward to all of them.

redirectTree(request, location) : Response

Produces an HTTP 301 Temporary redirect from one directory tree to another, using redirect.

permanentRedirect(request, location) : Response

Produces an HTTP 307 Permanent redirect to a given location, using redirect.

permanentRedirectTree(request, location) : Response

Produces an HTTP 307 Permanent redirect from one directory tree to another, using redirect.

file(request, path, contentType) : Response

Produces an HTTP response with the file at a given path. By default, it infers the content type from the extension of the path.

The file utility produces an e-tag header suitable for cache control, and may produce an HTTP 304 Not modified if the requested resource has the same entity tag.

The file utility may produce an HTTP 206 Partial content response with a content-range header if the request has a range header. If the partial range request cannot be satisified, it may respond HTTP 416 Not satisfiable.

In all cases, the response body is streamed from the file system.

etag(stat)

Computes an entity tag for a file system Stats object, using the node.ino, size, and last modification time.

directory(request, path)

This is not yet implemented.

json(object, visitor, tabs) : Response

Returns an HTTP 200 Ok response from some JSON, using the same argumensts as JSON.stringify.

Content(body, contentType, status) : Application

A factory that produces an HTTP application that will always respond with the given content, content type, and status. The default content type is text/plain and the default status is 200.

The body may be a string, array of strings or buffers, or a readable stream of strings or buffers.

File(path, contentType) : Application

A factory that produces an HTTP application that will always respond with the file at the given path. The content type is inferred from the path extension by default, but can be overridden with contentType.

FileTree(path, options) : Application

A factory that produces an HTTP application that responds to all requests with files within a branch of the file system starting at the given path and using any unprocessed portion of the request location.

Options include:

Redirect(path) : Application

A factory that produces an HTTP application that temporarily redirects to the given path.

RedirectTree(path) : Application

A factory that produces an HTTP application that redirects all requests under the requested path to parallel locations at the given path.

PermanentRedirect(path) : Application

A factory that produces an HTTP application that redirects all requests to an exact location and instructs the requester's cache never to ask again.

PermanentRedirectTree(path) : Application

A factory that produces an HTTP application that redirects all requests under the request path to a parallel location under the given path and instructs the requester's cache never to ask again.

Cap(app, notFound) : Application

A factory that produces an HTTP application that will cause an HTTP 404 Not found response if the request has not reached the end of its route (meaning pathInfo is not "" or "/"), or will forward to the given application.

Routing

Several routing application factories have the same form. They all take an object as their first argument and an optional fallback application as their second. The object maps each of the supported options for keys to an HTTP application for handling that option.

Select(selector) : Application

Produces an HTTP application that uses a function to determine the next application to route. The selector is a function that accepts the request and returns an HTTP application.

FirstFound(apps)

Returns an HTTP application that attempts to respond with each of a series of applications and returns the first response that does not have a 404 Not found status, or whatever response comes last.

Error(application, debug) : Application

Wraps an application such that any exceptions get converted into HTTP 500 Server error responses. If debug is enabled, produces the exception and stack traces in the body of the response.

Log(application, log, stamp) : Application

Wraps an application such that request and response times are logged. The log function reports to console.log by default. The stamp(message) function prefixes an ISO time stamp by default.

Time(application) : Application

Adds an x-response-time header to the response, with the time from receiving starting the request to starting the response in miliseconds.

Date(application) : Application

Adds a date header to the response with the current date for cache control purposes.

Tap(app, tap) : Application

Wraps an application such that the tap function receives the request first. If the tap returns nothing, the request goes to the app. If the tap returns a response, the app never gets called.

Trap(app, trap) : Application

Wraps an application such that the trap function receives the response. If it returns nothing, the response if forwarded. If the trap returns a response, the original response is discarded.

ParseQuery(application)

Wraps an application such that the query string is parsed and placed in request.parse.

Coverage

Use npm run cover to generate and view a coverage report of Q-IO.

File Percentage Missing
fs-boot.js 87% 41
fs.js 72% 100
reader.js 94% 8
writer.js 91% 8
fs-common.js 87% 52
fs-root.js 88% 11
fs-mock.js 91% 46
buffer-stream.js 89% 6
http.js 93% 25
http-apps.js 80% 286
http-cookie.js 79% 15

Copyright 2009–2013 Kristopher Michael Kowal MIT License (enclosed)