docs: add usage example

This commit is contained in:
zkochan
2017-07-15 16:39:04 +03:00
parent f37129027e
commit b021e2044a
76 changed files with 5110 additions and 13 deletions

5
example/node_modules/.modules.yaml generated vendored Normal file
View File

@@ -0,0 +1,5 @@
independentLeaves: false
layoutVersion: 1
packageManager: pnpm@1.4.0
skipped: []
store: /home/zkochan/.pnpm-store/2

View File

@@ -0,0 +1,122 @@
'use strict';
// detect either spaces or tabs but not both to properly handle tabs
// for indentation and spaces for alignment
const INDENT_RE = /^(?:( )+|\t+)/;
function getMostUsed(indents) {
let result = 0;
let maxUsed = 0;
let maxWeight = 0;
for (const entry of indents) {
// TODO: use destructuring when targeting Node.js 6
const key = entry[0];
const val = entry[1];
const u = val[0];
const w = val[1];
if (u > maxUsed || (u === maxUsed && w > maxWeight)) {
maxUsed = u;
maxWeight = w;
result = Number(key);
}
}
return result;
}
module.exports = str => {
if (typeof str !== 'string') {
throw new TypeError('Expected a string');
}
// used to see if tabs or spaces are the most used
let tabs = 0;
let spaces = 0;
// remember the size of previous line's indentation
let prev = 0;
// remember how many indents/unindents as occurred for a given size
// and how much lines follow a given indentation
//
// indents = {
// 3: [1, 0],
// 4: [1, 5],
// 5: [1, 0],
// 12: [1, 0],
// }
const indents = new Map();
// pointer to the array of last used indent
let current;
// whether the last action was an indent (opposed to an unindent)
let isIndent;
for (const line of str.split(/\n/g)) {
if (!line) {
// ignore empty lines
continue;
}
let indent;
const matches = line.match(INDENT_RE);
if (matches) {
indent = matches[0].length;
if (matches[1]) {
spaces++;
} else {
tabs++;
}
} else {
indent = 0;
}
const diff = indent - prev;
prev = indent;
if (diff) {
// an indent or unindent has been detected
isIndent = diff > 0;
current = indents.get(isIndent ? diff : -diff);
if (current) {
current[0]++;
} else {
current = [1, 0];
indents.set(diff, current);
}
} else if (current) {
// if the last action was an indent, increment the weight
current[1] += Number(isIndent);
}
}
const amount = getMostUsed(indents);
let type;
let indent;
if (!amount) {
type = null;
indent = '';
} else if (spaces >= tabs) {
type = 'space';
indent = ' '.repeat(amount);
} else {
type = 'tab';
indent = '\t'.repeat(amount);
}
return {
amount,
type,
indent
};
};

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,41 @@
{
"name": "detect-indent",
"version": "5.0.0",
"description": "Detect the indentation of code",
"license": "MIT",
"repository": "sindresorhus/detect-indent",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=4"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js"
],
"keywords": [
"indent",
"indentation",
"detect",
"infer",
"identify",
"code",
"string",
"text",
"source",
"space",
"tab"
],
"devDependencies": {
"ava": "*",
"xo": "*"
},
"xo": {
"esnext": true
}
}

View File

@@ -0,0 +1,111 @@
# detect-indent [![Build Status](https://travis-ci.org/sindresorhus/detect-indent.svg?branch=master)](https://travis-ci.org/sindresorhus/detect-indent)
> Detect the indentation of code
Pass in a string of any kind of text and get the indentation.
## Use cases
- Persisting the indentation when modifying a file.
- Have new content match the existing indentation.
- Setting the right indentation in your editor.
## Install
```
$ npm install --save detect-indent
```
## Usage
Here we modify a JSON file while persisting the indentation:
```js
const fs = require('fs');
const detectIndent = require('detect-indent');
/*
{
"ilove": "pizza"
}
*/
const file = fs.readFileSync('foo.json', 'utf8');
// tries to detect the indentation and falls back to a default if it can't
const indent = detectIndent(file).indent || ' ';
const json = JSON.parse(file);
json.ilove = 'unicorns';
fs.writeFileSync('foo.json', JSON.stringify(json, null, indent));
/*
{
"ilove": "unicorns"
}
*/
```
## API
Accepts a string and returns an object with stats about the indentation:
* `amount` {number} - Amount of indentation, for example `2`
* `type` {string|null} - Type of indentation. Possible values are `tab`, `space` or `null` if no indentation is detected
* `indent` {string} - Actual indentation
## Algorithm
The current algorithm looks for the most common difference between two consecutive non-empty lines.
In the following example, even if the 4-space indentation is used 3 times whereas the 2-space one is used 2 times, it is detected as less used because there were only 2 differences with this value instead of 4 for the 2-space indentation:
```css
html {
box-sizing: border-box;
}
body {
background: gray;
}
p {
line-height: 1.3em;
margin-top: 1em;
text-indent: 2em;
}
```
[Source.](https://medium.com/@heatherarthur/detecting-code-indentation-eff3ed0fb56b#3918)
Furthermore, if there are more than one most used difference, the indentation with the most lines is selected.
In the following example, the indentation is detected as 4-spaces:
```css
body {
background: gray;
}
p {
line-height: 1.3em;
margin-top: 1em;
text-indent: 2em;
}
```
## Related
- [detect-indent-cli](https://github.com/sindresorhus/detect-indent-cli) - CLI for this module
- [detect-newline](https://github.com/sindresorhus/detect-newline) - Detect the dominant newline character of a string
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)

View File

@@ -0,0 +1,15 @@
The ISC License
Copyright (c) Isaac Z. Schlueter, Ben Noordhuis, and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@@ -0,0 +1,133 @@
# graceful-fs
graceful-fs functions as a drop-in replacement for the fs module,
making various improvements.
The improvements are meant to normalize behavior across different
platforms and environments, and to make filesystem access more
resilient to errors.
## Improvements over [fs module](https://nodejs.org/api/fs.html)
* Queues up `open` and `readdir` calls, and retries them once
something closes if there is an EMFILE error from too many file
descriptors.
* fixes `lchmod` for Node versions prior to 0.6.2.
* implements `fs.lutimes` if possible. Otherwise it becomes a noop.
* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or
`lchown` if the user isn't root.
* makes `lchmod` and `lchown` become noops, if not available.
* retries reading a file if `read` results in EAGAIN error.
On Windows, it retries renaming a file for up to one second if `EACCESS`
or `EPERM` error occurs, likely because antivirus software has locked
the directory.
## USAGE
```javascript
// use just like fs
var fs = require('graceful-fs')
// now go and do stuff with it...
fs.readFileSync('some-file-or-whatever')
```
## Global Patching
If you want to patch the global fs module (or any other fs-like
module) you can do this:
```javascript
// Make sure to read the caveat below.
var realFs = require('fs')
var gracefulFs = require('graceful-fs')
gracefulFs.gracefulify(realFs)
```
This should only ever be done at the top-level application layer, in
order to delay on EMFILE errors from any fs-using dependencies. You
should **not** do this in a library, because it can cause unexpected
delays in other parts of the program.
## Changes
This module is fairly stable at this point, and used by a lot of
things. That being said, because it implements a subtle behavior
change in a core part of the node API, even modest changes can be
extremely breaking, and the versioning is thus biased towards
bumping the major when in doubt.
The main change between major versions has been switching between
providing a fully-patched `fs` module vs monkey-patching the node core
builtin, and the approach by which a non-monkey-patched `fs` was
created.
The goal is to trade `EMFILE` errors for slower fs operations. So, if
you try to open a zillion files, rather than crashing, `open`
operations will be queued up and wait for something else to `close`.
There are advantages to each approach. Monkey-patching the fs means
that no `EMFILE` errors can possibly occur anywhere in your
application, because everything is using the same core `fs` module,
which is patched. However, it can also obviously cause undesirable
side-effects, especially if the module is loaded multiple times.
Implementing a separate-but-identical patched `fs` module is more
surgical (and doesn't run the risk of patching multiple times), but
also imposes the challenge of keeping in sync with the core module.
The current approach loads the `fs` module, and then creates a
lookalike object that has all the same methods, except a few that are
patched. It is safe to use in all versions of Node from 0.8 through
7.0.
### v4
* Do not monkey-patch the fs module. This module may now be used as a
drop-in dep, and users can opt into monkey-patching the fs builtin
if their app requires it.
### v3
* Monkey-patch fs, because the eval approach no longer works on recent
node.
* fixed possible type-error throw if rename fails on windows
* verify that we *never* get EMFILE errors
* Ignore ENOSYS from chmod/chown
* clarify that graceful-fs must be used as a drop-in
### v2.1.0
* Use eval rather than monkey-patching fs.
* readdir: Always sort the results
* win32: requeue a file if error has an OK status
### v2.0
* A return to monkey patching
* wrap process.cwd
### v1.1
* wrap readFile
* Wrap fs.writeFile.
* readdir protection
* Don't clobber the fs builtin
* Handle fs.read EAGAIN errors by trying again
* Expose the curOpen counter
* No-op lchown/lchmod if not implemented
* fs.rename patch only for win32
* Patch fs.rename to handle AV software on Windows
* Close #4 Chown should not fail on einval or eperm if non-root
* Fix isaacs/fstream#1 Only wrap fs one time
* Fix #3 Start at 1024 max files, then back off on EMFILE
* lutimes that doens't blow up on Linux
* A full on-rewrite using a queue instead of just swallowing the EMFILE error
* Wrap Read/Write streams as well
### 1.0
* Update engines for node 0.6
* Be lstat-graceful on Windows
* first

View File

@@ -0,0 +1,21 @@
'use strict'
var fs = require('fs')
module.exports = clone(fs)
function clone (obj) {
if (obj === null || typeof obj !== 'object')
return obj
if (obj instanceof Object)
var copy = { __proto__: obj.__proto__ }
else
var copy = Object.create(null)
Object.getOwnPropertyNames(obj).forEach(function (key) {
Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key))
})
return copy
}

View File

@@ -0,0 +1,262 @@
var fs = require('fs')
var polyfills = require('./polyfills.js')
var legacy = require('./legacy-streams.js')
var queue = []
var util = require('util')
function noop () {}
var debug = noop
if (util.debuglog)
debug = util.debuglog('gfs4')
else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || ''))
debug = function() {
var m = util.format.apply(util, arguments)
m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ')
console.error(m)
}
if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
process.on('exit', function() {
debug(queue)
require('assert').equal(queue.length, 0)
})
}
module.exports = patch(require('./fs.js'))
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH) {
module.exports = patch(fs)
}
// Always patch fs.close/closeSync, because we want to
// retry() whenever a close happens *anywhere* in the program.
// This is essential when multiple graceful-fs instances are
// in play at the same time.
module.exports.close =
fs.close = (function (fs$close) { return function (fd, cb) {
return fs$close.call(fs, fd, function (err) {
if (!err)
retry()
if (typeof cb === 'function')
cb.apply(this, arguments)
})
}})(fs.close)
module.exports.closeSync =
fs.closeSync = (function (fs$closeSync) { return function (fd) {
// Note that graceful-fs also retries when fs.closeSync() fails.
// Looks like a bug to me, although it's probably a harmless one.
var rval = fs$closeSync.apply(fs, arguments)
retry()
return rval
}})(fs.closeSync)
function patch (fs) {
// Everything that references the open() function needs to be in here
polyfills(fs)
fs.gracefulify = patch
fs.FileReadStream = ReadStream; // Legacy name.
fs.FileWriteStream = WriteStream; // Legacy name.
fs.createReadStream = createReadStream
fs.createWriteStream = createWriteStream
var fs$readFile = fs.readFile
fs.readFile = readFile
function readFile (path, options, cb) {
if (typeof options === 'function')
cb = options, options = null
return go$readFile(path, options, cb)
function go$readFile (path, options, cb) {
return fs$readFile(path, options, function (err) {
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
enqueue([go$readFile, [path, options, cb]])
else {
if (typeof cb === 'function')
cb.apply(this, arguments)
retry()
}
})
}
}
var fs$writeFile = fs.writeFile
fs.writeFile = writeFile
function writeFile (path, data, options, cb) {
if (typeof options === 'function')
cb = options, options = null
return go$writeFile(path, data, options, cb)
function go$writeFile (path, data, options, cb) {
return fs$writeFile(path, data, options, function (err) {
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
enqueue([go$writeFile, [path, data, options, cb]])
else {
if (typeof cb === 'function')
cb.apply(this, arguments)
retry()
}
})
}
}
var fs$appendFile = fs.appendFile
if (fs$appendFile)
fs.appendFile = appendFile
function appendFile (path, data, options, cb) {
if (typeof options === 'function')
cb = options, options = null
return go$appendFile(path, data, options, cb)
function go$appendFile (path, data, options, cb) {
return fs$appendFile(path, data, options, function (err) {
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
enqueue([go$appendFile, [path, data, options, cb]])
else {
if (typeof cb === 'function')
cb.apply(this, arguments)
retry()
}
})
}
}
var fs$readdir = fs.readdir
fs.readdir = readdir
function readdir (path, options, cb) {
var args = [path]
if (typeof options !== 'function') {
args.push(options)
} else {
cb = options
}
args.push(go$readdir$cb)
return go$readdir(args)
function go$readdir$cb (err, files) {
if (files && files.sort)
files.sort()
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
enqueue([go$readdir, [args]])
else {
if (typeof cb === 'function')
cb.apply(this, arguments)
retry()
}
}
}
function go$readdir (args) {
return fs$readdir.apply(fs, args)
}
if (process.version.substr(0, 4) === 'v0.8') {
var legStreams = legacy(fs)
ReadStream = legStreams.ReadStream
WriteStream = legStreams.WriteStream
}
var fs$ReadStream = fs.ReadStream
ReadStream.prototype = Object.create(fs$ReadStream.prototype)
ReadStream.prototype.open = ReadStream$open
var fs$WriteStream = fs.WriteStream
WriteStream.prototype = Object.create(fs$WriteStream.prototype)
WriteStream.prototype.open = WriteStream$open
fs.ReadStream = ReadStream
fs.WriteStream = WriteStream
function ReadStream (path, options) {
if (this instanceof ReadStream)
return fs$ReadStream.apply(this, arguments), this
else
return ReadStream.apply(Object.create(ReadStream.prototype), arguments)
}
function ReadStream$open () {
var that = this
open(that.path, that.flags, that.mode, function (err, fd) {
if (err) {
if (that.autoClose)
that.destroy()
that.emit('error', err)
} else {
that.fd = fd
that.emit('open', fd)
that.read()
}
})
}
function WriteStream (path, options) {
if (this instanceof WriteStream)
return fs$WriteStream.apply(this, arguments), this
else
return WriteStream.apply(Object.create(WriteStream.prototype), arguments)
}
function WriteStream$open () {
var that = this
open(that.path, that.flags, that.mode, function (err, fd) {
if (err) {
that.destroy()
that.emit('error', err)
} else {
that.fd = fd
that.emit('open', fd)
}
})
}
function createReadStream (path, options) {
return new ReadStream(path, options)
}
function createWriteStream (path, options) {
return new WriteStream(path, options)
}
var fs$open = fs.open
fs.open = open
function open (path, flags, mode, cb) {
if (typeof mode === 'function')
cb = mode, mode = null
return go$open(path, flags, mode, cb)
function go$open (path, flags, mode, cb) {
return fs$open(path, flags, mode, function (err, fd) {
if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
enqueue([go$open, [path, flags, mode, cb]])
else {
if (typeof cb === 'function')
cb.apply(this, arguments)
retry()
}
})
}
}
return fs
}
function enqueue (elem) {
debug('ENQUEUE', elem[0].name, elem[1])
queue.push(elem)
}
function retry () {
var elem = queue.shift()
if (elem) {
debug('RETRY', elem[0].name, elem[1])
elem[0].apply(null, elem[1])
}
}

View File

@@ -0,0 +1,118 @@
var Stream = require('stream').Stream
module.exports = legacy
function legacy (fs) {
return {
ReadStream: ReadStream,
WriteStream: WriteStream
}
function ReadStream (path, options) {
if (!(this instanceof ReadStream)) return new ReadStream(path, options);
Stream.call(this);
var self = this;
this.path = path;
this.fd = null;
this.readable = true;
this.paused = false;
this.flags = 'r';
this.mode = 438; /*=0666*/
this.bufferSize = 64 * 1024;
options = options || {};
// Mixin options into this
var keys = Object.keys(options);
for (var index = 0, length = keys.length; index < length; index++) {
var key = keys[index];
this[key] = options[key];
}
if (this.encoding) this.setEncoding(this.encoding);
if (this.start !== undefined) {
if ('number' !== typeof this.start) {
throw TypeError('start must be a Number');
}
if (this.end === undefined) {
this.end = Infinity;
} else if ('number' !== typeof this.end) {
throw TypeError('end must be a Number');
}
if (this.start > this.end) {
throw new Error('start must be <= end');
}
this.pos = this.start;
}
if (this.fd !== null) {
process.nextTick(function() {
self._read();
});
return;
}
fs.open(this.path, this.flags, this.mode, function (err, fd) {
if (err) {
self.emit('error', err);
self.readable = false;
return;
}
self.fd = fd;
self.emit('open', fd);
self._read();
})
}
function WriteStream (path, options) {
if (!(this instanceof WriteStream)) return new WriteStream(path, options);
Stream.call(this);
this.path = path;
this.fd = null;
this.writable = true;
this.flags = 'w';
this.encoding = 'binary';
this.mode = 438; /*=0666*/
this.bytesWritten = 0;
options = options || {};
// Mixin options into this
var keys = Object.keys(options);
for (var index = 0, length = keys.length; index < length; index++) {
var key = keys[index];
this[key] = options[key];
}
if (this.start !== undefined) {
if ('number' !== typeof this.start) {
throw TypeError('start must be a Number');
}
if (this.start < 0) {
throw new Error('start must be >= zero');
}
this.pos = this.start;
}
this.busy = false;
this._queue = [];
if (this.fd === null) {
this._open = fs.open;
this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
this.flush();
}
}
}

View File

@@ -0,0 +1,47 @@
{
"name": "graceful-fs",
"description": "A drop-in replacement for fs, making various improvements.",
"version": "4.1.11",
"repository": {
"type": "git",
"url": "https://github.com/isaacs/node-graceful-fs"
},
"main": "graceful-fs.js",
"engines": {
"node": ">=0.4.0"
},
"directories": {
"test": "test"
},
"scripts": {
"test": "node test.js | tap -"
},
"keywords": [
"fs",
"module",
"reading",
"retry",
"retries",
"queue",
"error",
"errors",
"handling",
"EMFILE",
"EAGAIN",
"EINVAL",
"EPERM",
"EACCESS"
],
"license": "ISC",
"devDependencies": {
"mkdirp": "^0.5.0",
"rimraf": "^2.2.8",
"tap": "^5.4.2"
},
"files": [
"fs.js",
"graceful-fs.js",
"legacy-streams.js",
"polyfills.js"
]
}

View File

@@ -0,0 +1,330 @@
var fs = require('./fs.js')
var constants = require('constants')
var origCwd = process.cwd
var cwd = null
var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform
process.cwd = function() {
if (!cwd)
cwd = origCwd.call(process)
return cwd
}
try {
process.cwd()
} catch (er) {}
var chdir = process.chdir
process.chdir = function(d) {
cwd = null
chdir.call(process, d)
}
module.exports = patch
function patch (fs) {
// (re-)implement some things that are known busted or missing.
// lchmod, broken prior to 0.6.2
// back-port the fix here.
if (constants.hasOwnProperty('O_SYMLINK') &&
process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
patchLchmod(fs)
}
// lutimes implementation, or no-op
if (!fs.lutimes) {
patchLutimes(fs)
}
// https://github.com/isaacs/node-graceful-fs/issues/4
// Chown should not fail on einval or eperm if non-root.
// It should not fail on enosys ever, as this just indicates
// that a fs doesn't support the intended operation.
fs.chown = chownFix(fs.chown)
fs.fchown = chownFix(fs.fchown)
fs.lchown = chownFix(fs.lchown)
fs.chmod = chmodFix(fs.chmod)
fs.fchmod = chmodFix(fs.fchmod)
fs.lchmod = chmodFix(fs.lchmod)
fs.chownSync = chownFixSync(fs.chownSync)
fs.fchownSync = chownFixSync(fs.fchownSync)
fs.lchownSync = chownFixSync(fs.lchownSync)
fs.chmodSync = chmodFixSync(fs.chmodSync)
fs.fchmodSync = chmodFixSync(fs.fchmodSync)
fs.lchmodSync = chmodFixSync(fs.lchmodSync)
fs.stat = statFix(fs.stat)
fs.fstat = statFix(fs.fstat)
fs.lstat = statFix(fs.lstat)
fs.statSync = statFixSync(fs.statSync)
fs.fstatSync = statFixSync(fs.fstatSync)
fs.lstatSync = statFixSync(fs.lstatSync)
// if lchmod/lchown do not exist, then make them no-ops
if (!fs.lchmod) {
fs.lchmod = function (path, mode, cb) {
if (cb) process.nextTick(cb)
}
fs.lchmodSync = function () {}
}
if (!fs.lchown) {
fs.lchown = function (path, uid, gid, cb) {
if (cb) process.nextTick(cb)
}
fs.lchownSync = function () {}
}
// on Windows, A/V software can lock the directory, causing this
// to fail with an EACCES or EPERM if the directory contains newly
// created files. Try again on failure, for up to 60 seconds.
// Set the timeout this long because some Windows Anti-Virus, such as Parity
// bit9, may lock files for up to a minute, causing npm package install
// failures. Also, take care to yield the scheduler. Windows scheduling gives
// CPU to a busy looping process, which can cause the program causing the lock
// contention to be starved of CPU by node, so the contention doesn't resolve.
if (platform === "win32") {
fs.rename = (function (fs$rename) { return function (from, to, cb) {
var start = Date.now()
var backoff = 0;
fs$rename(from, to, function CB (er) {
if (er
&& (er.code === "EACCES" || er.code === "EPERM")
&& Date.now() - start < 60000) {
setTimeout(function() {
fs.stat(to, function (stater, st) {
if (stater && stater.code === "ENOENT")
fs$rename(from, to, CB);
else
cb(er)
})
}, backoff)
if (backoff < 100)
backoff += 10;
return;
}
if (cb) cb(er)
})
}})(fs.rename)
}
// if read() returns EAGAIN, then just try it again.
fs.read = (function (fs$read) { return function (fd, buffer, offset, length, position, callback_) {
var callback
if (callback_ && typeof callback_ === 'function') {
var eagCounter = 0
callback = function (er, _, __) {
if (er && er.code === 'EAGAIN' && eagCounter < 10) {
eagCounter ++
return fs$read.call(fs, fd, buffer, offset, length, position, callback)
}
callback_.apply(this, arguments)
}
}
return fs$read.call(fs, fd, buffer, offset, length, position, callback)
}})(fs.read)
fs.readSync = (function (fs$readSync) { return function (fd, buffer, offset, length, position) {
var eagCounter = 0
while (true) {
try {
return fs$readSync.call(fs, fd, buffer, offset, length, position)
} catch (er) {
if (er.code === 'EAGAIN' && eagCounter < 10) {
eagCounter ++
continue
}
throw er
}
}
}})(fs.readSync)
}
function patchLchmod (fs) {
fs.lchmod = function (path, mode, callback) {
fs.open( path
, constants.O_WRONLY | constants.O_SYMLINK
, mode
, function (err, fd) {
if (err) {
if (callback) callback(err)
return
}
// prefer to return the chmod error, if one occurs,
// but still try to close, and report closing errors if they occur.
fs.fchmod(fd, mode, function (err) {
fs.close(fd, function(err2) {
if (callback) callback(err || err2)
})
})
})
}
fs.lchmodSync = function (path, mode) {
var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)
// prefer to return the chmod error, if one occurs,
// but still try to close, and report closing errors if they occur.
var threw = true
var ret
try {
ret = fs.fchmodSync(fd, mode)
threw = false
} finally {
if (threw) {
try {
fs.closeSync(fd)
} catch (er) {}
} else {
fs.closeSync(fd)
}
}
return ret
}
}
function patchLutimes (fs) {
if (constants.hasOwnProperty("O_SYMLINK")) {
fs.lutimes = function (path, at, mt, cb) {
fs.open(path, constants.O_SYMLINK, function (er, fd) {
if (er) {
if (cb) cb(er)
return
}
fs.futimes(fd, at, mt, function (er) {
fs.close(fd, function (er2) {
if (cb) cb(er || er2)
})
})
})
}
fs.lutimesSync = function (path, at, mt) {
var fd = fs.openSync(path, constants.O_SYMLINK)
var ret
var threw = true
try {
ret = fs.futimesSync(fd, at, mt)
threw = false
} finally {
if (threw) {
try {
fs.closeSync(fd)
} catch (er) {}
} else {
fs.closeSync(fd)
}
}
return ret
}
} else {
fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) }
fs.lutimesSync = function () {}
}
}
function chmodFix (orig) {
if (!orig) return orig
return function (target, mode, cb) {
return orig.call(fs, target, mode, function (er) {
if (chownErOk(er)) er = null
if (cb) cb.apply(this, arguments)
})
}
}
function chmodFixSync (orig) {
if (!orig) return orig
return function (target, mode) {
try {
return orig.call(fs, target, mode)
} catch (er) {
if (!chownErOk(er)) throw er
}
}
}
function chownFix (orig) {
if (!orig) return orig
return function (target, uid, gid, cb) {
return orig.call(fs, target, uid, gid, function (er) {
if (chownErOk(er)) er = null
if (cb) cb.apply(this, arguments)
})
}
}
function chownFixSync (orig) {
if (!orig) return orig
return function (target, uid, gid) {
try {
return orig.call(fs, target, uid, gid)
} catch (er) {
if (!chownErOk(er)) throw er
}
}
}
function statFix (orig) {
if (!orig) return orig
// Older versions of Node erroneously returned signed integers for
// uid + gid.
return function (target, cb) {
return orig.call(fs, target, function (er, stats) {
if (!stats) return cb.apply(this, arguments)
if (stats.uid < 0) stats.uid += 0x100000000
if (stats.gid < 0) stats.gid += 0x100000000
if (cb) cb.apply(this, arguments)
})
}
}
function statFixSync (orig) {
if (!orig) return orig
// Older versions of Node erroneously returned signed integers for
// uid + gid.
return function (target) {
var stats = orig.call(fs, target)
if (stats.uid < 0) stats.uid += 0x100000000
if (stats.gid < 0) stats.gid += 0x100000000
return stats;
}
}
// ENOSYS means that the fs doesn't support the op. Just ignore
// that, because it doesn't matter.
//
// if there's no getuid, or if getuid() is something other
// than 0, and the error is EINVAL or EPERM, then just ignore
// it.
//
// This specific case is a silent failure in cp, install, tar,
// and most other unix tools that manage permissions.
//
// When running as root, or if other types of errors are
// encountered, then it's strict.
function chownErOk (er) {
if (!er)
return true
if (er.code === "ENOSYS")
return true
var nonroot = !process.getuid || process.getuid() !== 0
if (nonroot) {
if (er.code === "EINVAL" || er.code === "EPERM")
return true
}
return false
}

View File

@@ -0,0 +1,122 @@
iMurmurHash.js
==============
An incremental implementation of the MurmurHash3 (32-bit) hashing algorithm for JavaScript based on [Gary Court's implementation](https://github.com/garycourt/murmurhash-js) with [kazuyukitanimura's modifications](https://github.com/kazuyukitanimura/murmurhash-js).
This version works significantly faster than the non-incremental version if you need to hash many small strings into a single hash, since string concatenation (to build the single string to pass the non-incremental version) is fairly costly. In one case tested, using the incremental version was about 50% faster than concatenating 5-10 strings and then hashing.
Installation
------------
To use iMurmurHash in the browser, [download the latest version](https://raw.github.com/jensyt/imurmurhash-js/master/imurmurhash.min.js) and include it as a script on your site.
```html
<script type="text/javascript" src="/scripts/imurmurhash.min.js"></script>
<script>
// Your code here, access iMurmurHash using the global object MurmurHash3
</script>
```
---
To use iMurmurHash in Node.js, install the module using NPM:
```bash
npm install imurmurhash
```
Then simply include it in your scripts:
```javascript
MurmurHash3 = require('imurmurhash');
```
Quick Example
-------------
```javascript
// Create the initial hash
var hashState = MurmurHash3('string');
// Incrementally add text
hashState.hash('more strings');
hashState.hash('even more strings');
// All calls can be chained if desired
hashState.hash('and').hash('some').hash('more');
// Get a result
hashState.result();
// returns 0xe4ccfe6b
```
Functions
---------
### MurmurHash3 ([string], [seed])
Get a hash state object, optionally initialized with the given _string_ and _seed_. _Seed_ must be a positive integer if provided. Calling this function without the `new` keyword will return a cached state object that has been reset. This is safe to use as long as the object is only used from a single thread and no other hashes are created while operating on this one. If this constraint cannot be met, you can use `new` to create a new state object. For example:
```javascript
// Use the cached object, calling the function again will return the same
// object (but reset, so the current state would be lost)
hashState = MurmurHash3();
...
// Create a new object that can be safely used however you wish. Calling the
// function again will simply return a new state object, and no state loss
// will occur, at the cost of creating more objects.
hashState = new MurmurHash3();
```
Both methods can be mixed however you like if you have different use cases.
---
### MurmurHash3.prototype.hash (string)
Incrementally add _string_ to the hash. This can be called as many times as you want for the hash state object, including after a call to `result()`. Returns `this` so calls can be chained.
---
### MurmurHash3.prototype.result ()
Get the result of the hash as a 32-bit positive integer. This performs the tail and finalizer portions of the algorithm, but does not store the result in the state object. This means that it is perfectly safe to get results and then continue adding strings via `hash`.
```javascript
// Do the whole string at once
MurmurHash3('this is a test string').result();
// 0x70529328
// Do part of the string, get a result, then the other part
var m = MurmurHash3('this is a');
m.result();
// 0xbfc4f834
m.hash(' test string').result();
// 0x70529328 (same as above)
```
---
### MurmurHash3.prototype.reset ([seed])
Reset the state object for reuse, optionally using the given _seed_ (defaults to 0 like the constructor). Returns `this` so calls can be chained.
---
License (MIT)
-------------
Copyright (c) 2013 Gary Court, Jens Taylor
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,138 @@
/**
* @preserve
* JS Implementation of incremental MurmurHash3 (r150) (as of May 10, 2013)
*
* @author <a href="mailto:jensyt@gmail.com">Jens Taylor</a>
* @see http://github.com/homebrewing/brauhaus-diff
* @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
* @see http://github.com/garycourt/murmurhash-js
* @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
* @see http://sites.google.com/site/murmurhash/
*/
(function(){
var cache;
// Call this function without `new` to use the cached object (good for
// single-threaded environments), or with `new` to create a new object.
//
// @param {string} key A UTF-16 or ASCII string
// @param {number} seed An optional positive integer
// @return {object} A MurmurHash3 object for incremental hashing
function MurmurHash3(key, seed) {
var m = this instanceof MurmurHash3 ? this : cache;
m.reset(seed)
if (typeof key === 'string' && key.length > 0) {
m.hash(key);
}
if (m !== this) {
return m;
}
};
// Incrementally add a string to this hash
//
// @param {string} key A UTF-16 or ASCII string
// @return {object} this
MurmurHash3.prototype.hash = function(key) {
var h1, k1, i, top, len;
len = key.length;
this.len += len;
k1 = this.k1;
i = 0;
switch (this.rem) {
case 0: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) : 0;
case 1: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) << 8 : 0;
case 2: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) << 16 : 0;
case 3:
k1 ^= len > i ? (key.charCodeAt(i) & 0xff) << 24 : 0;
k1 ^= len > i ? (key.charCodeAt(i++) & 0xff00) >> 8 : 0;
}
this.rem = (len + this.rem) & 3; // & 3 is same as % 4
len -= this.rem;
if (len > 0) {
h1 = this.h1;
while (1) {
k1 = (k1 * 0x2d51 + (k1 & 0xffff) * 0xcc9e0000) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (k1 * 0x3593 + (k1 & 0xffff) * 0x1b870000) & 0xffffffff;
h1 ^= k1;
h1 = (h1 << 13) | (h1 >>> 19);
h1 = (h1 * 5 + 0xe6546b64) & 0xffffffff;
if (i >= len) {
break;
}
k1 = ((key.charCodeAt(i++) & 0xffff)) ^
((key.charCodeAt(i++) & 0xffff) << 8) ^
((key.charCodeAt(i++) & 0xffff) << 16);
top = key.charCodeAt(i++);
k1 ^= ((top & 0xff) << 24) ^
((top & 0xff00) >> 8);
}
k1 = 0;
switch (this.rem) {
case 3: k1 ^= (key.charCodeAt(i + 2) & 0xffff) << 16;
case 2: k1 ^= (key.charCodeAt(i + 1) & 0xffff) << 8;
case 1: k1 ^= (key.charCodeAt(i) & 0xffff);
}
this.h1 = h1;
}
this.k1 = k1;
return this;
};
// Get the result of this hash
//
// @return {number} The 32-bit hash
MurmurHash3.prototype.result = function() {
var k1, h1;
k1 = this.k1;
h1 = this.h1;
if (k1 > 0) {
k1 = (k1 * 0x2d51 + (k1 & 0xffff) * 0xcc9e0000) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (k1 * 0x3593 + (k1 & 0xffff) * 0x1b870000) & 0xffffffff;
h1 ^= k1;
}
h1 ^= this.len;
h1 ^= h1 >>> 16;
h1 = (h1 * 0xca6b + (h1 & 0xffff) * 0x85eb0000) & 0xffffffff;
h1 ^= h1 >>> 13;
h1 = (h1 * 0xae35 + (h1 & 0xffff) * 0xc2b20000) & 0xffffffff;
h1 ^= h1 >>> 16;
return h1 >>> 0;
};
// Reset the hash object for reuse
//
// @param {number} seed An optional positive integer
MurmurHash3.prototype.reset = function(seed) {
this.h1 = typeof seed === 'number' ? seed : 0;
this.rem = this.k1 = this.len = 0;
return this;
};
// A cached object to use. This can be safely used if you're in a single-
// threaded environment, otherwise you need to create new hashes to use.
cache = new MurmurHash3();
if (typeof(module) != 'undefined') {
module.exports = MurmurHash3;
} else {
this.MurmurHash3 = MurmurHash3;
}
}());

View File

@@ -0,0 +1,12 @@
/**
* @preserve
* JS Implementation of incremental MurmurHash3 (r150) (as of May 10, 2013)
*
* @author <a href="mailto:jensyt@gmail.com">Jens Taylor</a>
* @see http://github.com/homebrewing/brauhaus-diff
* @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
* @see http://github.com/garycourt/murmurhash-js
* @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
* @see http://sites.google.com/site/murmurhash/
*/
!function(){function t(h,r){var s=this instanceof t?this:e;return s.reset(r),"string"==typeof h&&h.length>0&&s.hash(h),s!==this?s:void 0}var e;t.prototype.hash=function(t){var e,h,r,s,i;switch(i=t.length,this.len+=i,h=this.k1,r=0,this.rem){case 0:h^=i>r?65535&t.charCodeAt(r++):0;case 1:h^=i>r?(65535&t.charCodeAt(r++))<<8:0;case 2:h^=i>r?(65535&t.charCodeAt(r++))<<16:0;case 3:h^=i>r?(255&t.charCodeAt(r))<<24:0,h^=i>r?(65280&t.charCodeAt(r++))>>8:0}if(this.rem=3&i+this.rem,i-=this.rem,i>0){for(e=this.h1;;){if(h=4294967295&11601*h+3432906752*(65535&h),h=h<<15|h>>>17,h=4294967295&13715*h+461832192*(65535&h),e^=h,e=e<<13|e>>>19,e=4294967295&5*e+3864292196,r>=i)break;h=65535&t.charCodeAt(r++)^(65535&t.charCodeAt(r++))<<8^(65535&t.charCodeAt(r++))<<16,s=t.charCodeAt(r++),h^=(255&s)<<24^(65280&s)>>8}switch(h=0,this.rem){case 3:h^=(65535&t.charCodeAt(r+2))<<16;case 2:h^=(65535&t.charCodeAt(r+1))<<8;case 1:h^=65535&t.charCodeAt(r)}this.h1=e}return this.k1=h,this},t.prototype.result=function(){var t,e;return t=this.k1,e=this.h1,t>0&&(t=4294967295&11601*t+3432906752*(65535&t),t=t<<15|t>>>17,t=4294967295&13715*t+461832192*(65535&t),e^=t),e^=this.len,e^=e>>>16,e=4294967295&51819*e+2246770688*(65535&e),e^=e>>>13,e=4294967295&44597*e+3266445312*(65535&e),e^=e>>>16,e>>>0},t.prototype.reset=function(t){return this.h1="number"==typeof t?t:0,this.rem=this.k1=this.len=0,this},e=new t,"undefined"!=typeof module?module.exports=t:this.MurmurHash3=t}();

View File

@@ -0,0 +1,40 @@
{
"name": "imurmurhash",
"version": "0.1.4",
"description": "An incremental implementation of MurmurHash3",
"homepage": "https://github.com/jensyt/imurmurhash-js",
"main": "imurmurhash.js",
"files": [
"imurmurhash.js",
"imurmurhash.min.js",
"package.json",
"README.md"
],
"repository": {
"type": "git",
"url": "https://github.com/jensyt/imurmurhash-js"
},
"bugs": {
"url": "https://github.com/jensyt/imurmurhash-js/issues"
},
"keywords": [
"murmur",
"murmurhash",
"murmurhash3",
"hash",
"incremental"
],
"author": {
"name": "Jens Taylor",
"email": "jensyt@gmail.com",
"url": "https://github.com/homebrewing"
},
"license": "MIT",
"dependencies": {
},
"devDependencies": {
},
"engines": {
"node": ">=0.8.19"
}
}

View File

@@ -0,0 +1,7 @@
'use strict';
var toString = Object.prototype.toString;
module.exports = function (x) {
var prototype;
return toString.call(x) === '[object Object]' && (prototype = Object.getPrototypeOf(x), prototype === null || prototype === Object.getPrototypeOf({}));
};

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,36 @@
{
"name": "is-plain-obj",
"version": "1.1.0",
"description": "Check if a value is a plain object",
"license": "MIT",
"repository": "sindresorhus/is-plain-obj",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "node test.js"
},
"files": [
"index.js"
],
"keywords": [
"obj",
"object",
"is",
"check",
"test",
"type",
"plain",
"vanilla",
"pure",
"simple"
],
"devDependencies": {
"ava": "0.0.4"
}
}

View File

@@ -0,0 +1,35 @@
# is-plain-obj [![Build Status](https://travis-ci.org/sindresorhus/is-plain-obj.svg?branch=master)](https://travis-ci.org/sindresorhus/is-plain-obj)
> Check if a value is a plain object
An object is plain if it's created by either `{}`, `new Object()` or `Object.create(null)`.
## Install
```
$ npm install --save is-plain-obj
```
## Usage
```js
var isPlainObj = require('is-plain-obj');
isPlainObj({foo: 'bar'});
//=> true
isPlainObj([1, 2, 3]);
//=> false
```
## Related
- [is-obj](https://github.com/sindresorhus/is-obj) - Check if a value is an object
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)

View File

@@ -0,0 +1,83 @@
'use strict';
const fs = require('fs');
const path = require('path');
const pify = require('pify');
const defaults = {
mode: 0o777 & (~process.umask()),
fs
};
// https://github.com/nodejs/node/issues/8987
// https://github.com/libuv/libuv/pull/1088
const checkPath = pth => {
if (process.platform === 'win32') {
const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, ''));
if (pathHasInvalidWinCharacters) {
const err = new Error(`Path contains invalid characters: ${pth}`);
err.code = 'EINVAL';
throw err;
}
}
};
module.exports = (input, opts) => Promise.resolve().then(() => {
checkPath(input);
opts = Object.assign({}, defaults, opts);
const fsP = pify(opts.fs);
const make = pth => {
return fsP.mkdir(pth, opts.mode)
.then(() => pth)
.catch(err => {
if (err.code === 'ENOENT') {
if (err.message.includes('null bytes') || path.dirname(pth) === pth) {
throw err;
}
return make(path.dirname(pth)).then(() => make(pth));
}
return fsP.stat(pth)
.then(stats => stats.isDirectory() ? pth : Promise.reject())
.catch(() => {
throw err;
});
});
};
return make(path.resolve(input));
});
module.exports.sync = (input, opts) => {
checkPath(input);
opts = Object.assign({}, defaults, opts);
const make = pth => {
try {
opts.fs.mkdirSync(pth, opts.mode);
} catch (err) {
if (err.code === 'ENOENT') {
if (err.message.includes('null bytes') || path.dirname(pth) === pth) {
throw err;
}
make(path.dirname(pth));
return make(pth);
}
try {
if (!opts.fs.statSync(pth).isDirectory()) {
throw new Error();
}
} catch (_) {
throw err;
}
}
return pth;
};
return make(path.resolve(input));
};

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,54 @@
{
"name": "make-dir",
"version": "1.0.0",
"description": "Make a directory and its parents if needed - Think `mkdir -p`",
"license": "MIT",
"repository": "sindresorhus/make-dir",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=4"
},
"scripts": {
"test": "xo && nyc ava"
},
"files": [
"index.js"
],
"keywords": [
"mkdir",
"mkdirp",
"make",
"directories",
"dir",
"dirs",
"folders",
"directory",
"folder",
"path",
"parent",
"parents",
"intermediate",
"recursively",
"recursive",
"create",
"fs",
"filesystem",
"file-system"
],
"dependencies": {
"pify": "^2.3.0"
},
"devDependencies": {
"ava": "*",
"coveralls": "^2.13.0",
"graceful-fs": "^4.1.11",
"nyc": "^10.2.0",
"path-type": "^2.0.0",
"tempy": "^0.1.0",
"xo": "*"
}
}

View File

@@ -0,0 +1,113 @@
# make-dir [![Build Status: macOS & Linux](https://travis-ci.org/sindresorhus/make-dir.svg?branch=master)](https://travis-ci.org/sindresorhus/make-dir) [![Build status: Windows](https://ci.appveyor.com/api/projects/status/e0vtt8y600w91gcs/branch/master?svg=true)](https://ci.appveyor.com/project/sindresorhus/make-dir/branch/master) [![Coverage Status](https://coveralls.io/repos/github/sindresorhus/make-dir/badge.svg)](https://coveralls.io/github/sindresorhus/make-dir)
> Make a directory and its parents if needed - Think `mkdir -p`
## Advantages over [`mkdirp`](https://github.com/substack/node-mkdirp)
- Promise API *(Async/await ready!)*
- Fixes many `mkdirp` issues: [#96](https://github.com/substack/node-mkdirp/pull/96) [#70](https://github.com/substack/node-mkdirp/issues/70) [#66](https://github.com/substack/node-mkdirp/issues/66)
- 100% test coverage
- CI-tested on macOS, Linux, and Windows
- Actively maintained
- Doesn't bundle a CLI
## Install
```
$ npm install --save make-dir
```
## Usage
```
$ pwd
/Users/sindresorhus/fun
$ tree
.
```
```js
const makeDir = require('make-dir');
makeDir('unicorn/rainbow/cake').then(path => {
console.log(path);
//=> '/Users/sindresorhus/fun/unicorn/rainbow/cake'
});
```
```
$ tree
.
└── unicorn
└── rainbow
└── cake
```
Multiple directories:
```js
const makeDir = require('make-dir');
Promise.all([
makeDir('unicorn/rainbow')
makeDir('foo/bar')
]).then(paths => {
console.log(paths);
/*
[
'/Users/sindresorhus/fun/unicorn/rainbow',
'/Users/sindresorhus/fun/foo/bar'
]
*/
});
```
## API
### makeDir(path, [options])
Returns a `Promise` for the path to the created directory.
### makeDir.sync(path, [options])
Returns the path to the created directory.
#### path
Type: `string`
Directory to create.
#### options
Type: `Object`
##### mode
Type: `integer`<br>
Default: `0o777 & (~process.umask())`
Directory [permissions](https://x-team.com/blog/file-system-permissions-umask-node-js/).
##### fs
Type: `Object`<br>
Default: `require('fs')`
Use a custom `fs` implementation. For example [`graceful-fs`](https://github.com/isaacs/node-graceful-fs).
## Related
- [make-dir-cli](https://github.com/sindresorhus/make-dir-cli) - CLI for this module
- [del](https://github.com/sindresorhus/del) - Delete files and directories
- [globby](https://github.com/sindresorhus/globby) - User-friendly glob matching
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)

View File

@@ -0,0 +1 @@
../../../pify/2.3.0/node_modules/pify

View File

@@ -0,0 +1,68 @@
'use strict';
var processFn = function (fn, P, opts) {
return function () {
var that = this;
var args = new Array(arguments.length);
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
return new P(function (resolve, reject) {
args.push(function (err, result) {
if (err) {
reject(err);
} else if (opts.multiArgs) {
var results = new Array(arguments.length - 1);
for (var i = 1; i < arguments.length; i++) {
results[i - 1] = arguments[i];
}
resolve(results);
} else {
resolve(result);
}
});
fn.apply(that, args);
});
};
};
var pify = module.exports = function (obj, P, opts) {
if (typeof P !== 'function') {
opts = P;
P = Promise;
}
opts = opts || {};
opts.exclude = opts.exclude || [/.+Sync$/];
var filter = function (key) {
var match = function (pattern) {
return typeof pattern === 'string' ? key === pattern : pattern.test(key);
};
return opts.include ? opts.include.some(match) : !opts.exclude.some(match);
};
var ret = typeof obj === 'function' ? function () {
if (opts.excludeMain) {
return obj.apply(this, arguments);
}
return processFn(obj, P, opts).apply(this, arguments);
} : {};
return Object.keys(obj).reduce(function (ret, key) {
var x = obj[key];
ret[key] = typeof x === 'function' && filter(key) ? processFn(x, P, opts) : x;
return ret;
}, ret);
};
pify.all = pify;

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,48 @@
{
"name": "pify",
"version": "2.3.0",
"description": "Promisify a callback-style function",
"license": "MIT",
"repository": "sindresorhus/pify",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "xo && ava && npm run optimization-test",
"optimization-test": "node --allow-natives-syntax optimization-test.js"
},
"files": [
"index.js"
],
"keywords": [
"promise",
"promises",
"promisify",
"denodify",
"denodeify",
"callback",
"cb",
"node",
"then",
"thenify",
"convert",
"transform",
"wrap",
"wrapper",
"bind",
"to",
"async",
"es2015"
],
"devDependencies": {
"ava": "*",
"pinkie-promise": "^1.0.0",
"v8-natives": "0.0.2",
"xo": "*"
}
}

View File

@@ -0,0 +1,119 @@
# pify [![Build Status](https://travis-ci.org/sindresorhus/pify.svg?branch=master)](https://travis-ci.org/sindresorhus/pify)
> Promisify a callback-style function
## Install
```
$ npm install --save pify
```
## Usage
```js
const fs = require('fs');
const pify = require('pify');
// promisify a single function
pify(fs.readFile)('package.json', 'utf8').then(data => {
console.log(JSON.parse(data).name);
//=> 'pify'
});
// or promisify all methods in a module
pify(fs).readFile('package.json', 'utf8').then(data => {
console.log(JSON.parse(data).name);
//=> 'pify'
});
```
## API
### pify(input, [promiseModule], [options])
Returns a promise wrapped version of the supplied function or module.
#### input
Type: `function`, `object`
Callback-style function or module whose methods you want to promisify.
#### promiseModule
Type: `function`
Custom promise module to use instead of the native one.
Check out [`pinkie-promise`](https://github.com/floatdrop/pinkie-promise) if you need a tiny promise polyfill.
#### options
##### multiArgs
Type: `boolean`
Default: `false`
By default, the promisified function will only return the second argument from the callback, which works fine for most APIs. This option can be useful for modules like `request` that return multiple arguments. Turning this on will make it return an array of all arguments from the callback, excluding the error argument, instead of just the second argument.
```js
const request = require('request');
const pify = require('pify');
pify(request, {multiArgs: true})('https://sindresorhus.com').then(result => {
const [httpResponse, body] = result;
});
```
##### include
Type: `array` of (`string`|`regex`)
Methods in a module to promisify. Remaining methods will be left untouched.
##### exclude
Type: `array` of (`string`|`regex`)
Default: `[/.+Sync$/]`
Methods in a module **not** to promisify. Methods with names ending with `'Sync'` are excluded by default.
##### excludeMain
Type: `boolean`
Default: `false`
By default, if given module is a function itself, this function will be promisified. Turn this option on if you want to promisify only methods of the module.
```js
const pify = require('pify');
function fn() {
return true;
}
fn.method = (data, callback) => {
setImmediate(() => {
callback(data, null);
});
};
// promisify methods but not fn()
const promiseFn = pify(fn, {excludeMain: true});
if (promiseFn()) {
promiseFn.method('hi').then(data => {
console.log(data);
});
}
```
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)

View File

@@ -0,0 +1,15 @@
The ISC License
Copyright (c) Isaac Z. Schlueter
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@@ -0,0 +1,143 @@
# Controlling Flow: callbacks are easy
## What's actually hard?
- Doing a bunch of things in a specific order.
- Knowing when stuff is done.
- Handling failures.
- Breaking up functionality into parts (avoid nested inline callbacks)
## Common Mistakes
- Abandoning convention and consistency.
- Putting all callbacks inline.
- Using libraries without grokking them.
- Trying to make async code look sync.
## Define Conventions
- Two kinds of functions: *actors* take action, *callbacks* get results.
- Essentially the continuation pattern. Resulting code *looks* similar
to fibers, but is *much* simpler to implement.
- Node works this way in the lowlevel APIs already, and it's very flexible.
## Callbacks
- Simple responders
- Must always be prepared to handle errors, that's why it's the first argument.
- Often inline anonymous, but not always.
- Can trap and call other callbacks with modified data, or pass errors upwards.
## Actors
- Last argument is a callback.
- If any error occurs, and can't be handled, pass it to the callback and return.
- Must not throw. Return value ignored.
- return x ==> return cb(null, x)
- throw er ==> return cb(er)
```javascript
// return true if a path is either
// a symlink or a directory.
function isLinkOrDir (path, cb) {
fs.lstat(path, function (er, s) {
if (er) return cb(er)
return cb(null, s.isDirectory() || s.isSymbolicLink())
})
}
```
# asyncMap
## Usecases
- I have a list of 10 files, and need to read all of them, and then continue when they're all done.
- I have a dozen URLs, and need to fetch them all, and then continue when they're all done.
- I have 4 connected users, and need to send a message to all of them, and then continue when that's done.
- I have a list of n things, and I need to dosomething with all of them, in parallel, and get the results once they're all complete.
## Solution
```javascript
var asyncMap = require("slide").asyncMap
function writeFiles (files, what, cb) {
asyncMap(files, function (f, cb) {
fs.writeFile(f, what, cb)
}, cb)
}
writeFiles([my, file, list], "foo", cb)
```
# chain
## Usecases
- I have to do a bunch of things, in order. Get db credentials out of a file,
read the data from the db, write that data to another file.
- If anything fails, do not continue.
- I still have to provide an array of functions, which is a lot of boilerplate,
and a pita if your functions take args like
```javascript
function (cb) {
blah(a, b, c, cb)
}
```
- Results are discarded, which is a bit lame.
- No way to branch.
## Solution
- reduces boilerplate by converting an array of [fn, args] to an actor
that takes no arguments (except cb)
- A bit like Function#bind, but tailored for our use-case.
- bindActor(obj, "method", a, b, c)
- bindActor(fn, a, b, c)
- bindActor(obj, fn, a, b, c)
- branching, skipping over falsey arguments
```javascript
chain([
doThing && [thing, a, b, c]
, isFoo && [doFoo, "foo"]
, subChain && [chain, [one, two]]
], cb)
```
- tracking results: results are stored in an optional array passed as argument,
last result is always in results[results.length - 1].
- treat chain.first and chain.last as placeholders for the first/last
result up until that point.
## Non-trivial example
- Read number files in a directory
- Add the results together
- Ping a web service with the result
- Write the response to a file
- Delete the number files
```javascript
var chain = require("slide").chain
function myProgram (cb) {
var res = [], last = chain.last, first = chain.first
chain([
[fs, "readdir", "the-directory"]
, [readFiles, "the-directory", last]
, [sum, last]
, [ping, "POST", "example.com", 80, "/foo", last]
, [fs, "writeFile", "result.txt", last]
, [rmFiles, "./the-directory", first]
], res, cb)
}
```
# Conclusion: Convention Profits
- Consistent API from top to bottom.
- Sneak in at any point to inject functionality. Testable, reusable, ...
- When ruby and python users whine, you can smile condescendingly.

View File

@@ -0,0 +1 @@
module.exports=require("./lib/slide")

View File

@@ -0,0 +1,20 @@
{
"name": "slide",
"version": "1.1.6",
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"contributors": [
"S. Sriram <ssriram@gmail.com> (http://www.565labs.com)"
],
"description": "A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS",
"main": "./lib/slide.js",
"dependencies": {},
"devDependencies": {},
"engines": {
"node": "*"
},
"repository": {
"type": "git",
"url": "git://github.com/isaacs/slide-flow-control.git"
},
"license": "ISC"
}

View File

@@ -0,0 +1 @@
../../../is-plain-obj/1.1.0/node_modules/is-plain-obj

View File

@@ -0,0 +1,44 @@
'use strict';
var isPlainObj = require('is-plain-obj');
module.exports = function (obj, opts) {
if (!isPlainObj(obj)) {
throw new TypeError('Expected a plain object');
}
opts = opts || {};
// DEPRECATED
if (typeof opts === 'function') {
opts = {compare: opts};
}
var deep = opts.deep;
var seenInput = [];
var seenOutput = [];
var sortKeys = function (x) {
var seenIndex = seenInput.indexOf(x);
if (seenIndex !== -1) {
return seenOutput[seenIndex];
}
var ret = {};
var keys = Object.keys(x).sort(opts.compare);
seenInput.push(x);
seenOutput.push(ret);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var val = x[key];
ret[key] = deep && isPlainObj(val) ? sortKeys(val) : val;
}
return ret;
};
return sortKeys(obj);
};

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,40 @@
{
"name": "sort-keys",
"version": "1.1.2",
"description": "Sort the keys of an object",
"license": "MIT",
"repository": "sindresorhus/sort-keys",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "xo && mocha"
},
"files": [
"index.js"
],
"keywords": [
"sort",
"object",
"keys",
"obj",
"key",
"stable",
"deterministic",
"deep",
"recursive",
"recursively"
],
"dependencies": {
"is-plain-obj": "^1.0.0"
},
"devDependencies": {
"mocha": "*",
"xo": "*"
}
}

View File

@@ -0,0 +1,60 @@
# sort-keys [![Build Status](https://travis-ci.org/sindresorhus/sort-keys.svg?branch=master)](https://travis-ci.org/sindresorhus/sort-keys)
> Sort the keys of an object
Useful to get a deterministically ordered object, as the order of keys can vary between engines.
## Install
```
$ npm install --save sort-keys
```
## Usage
```js
const sortKeys = require('sort-keys');
sortKeys({c: 0, a: 0, b: 0});
//=> {a: 0, b: 0, c: 0}
sortKeys({b: {b: 0, a: 0}, a: 0}, {deep: true});
//=> {a: 0, b: {a: 0, b: 0}}
sortKeys({c: 0, a: 0, b: 0}, {
compare: (a, b) => -a.localeCompare(b)
});
//=> {c: 0, b: 0, a: 0}
```
## API
### sortKeys(input, [options])
Returns a new object with sorted keys.
#### input
Type: `Object`
#### options
##### deep
Type: `boolean`
Recursively sort keys.
##### compare
Type: `Function`
[Compare function.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)

View File

@@ -0,0 +1 @@
../../../is-plain-obj/1.1.0/node_modules/is-plain-obj

View File

@@ -0,0 +1,55 @@
'use strict';
const isPlainObj = require('is-plain-obj');
module.exports = (obj, opts) => {
if (!isPlainObj(obj)) {
throw new TypeError('Expected a plain object');
}
opts = opts || {};
// DEPRECATED
if (typeof opts === 'function') {
throw new TypeError('Specify the compare function as an option instead');
}
const deep = opts.deep;
const seenInput = [];
const seenOutput = [];
const sortKeys = x => {
const seenIndex = seenInput.indexOf(x);
if (seenIndex !== -1) {
return seenOutput[seenIndex];
}
const ret = {};
const keys = Object.keys(x).sort(opts.compare);
seenInput.push(x);
seenOutput.push(ret);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const val = x[key];
if (deep && Array.isArray(val)) {
const retArr = [];
for (let j = 0; j < val.length; j++) {
retArr[j] = isPlainObj(val[j]) ? sortKeys(val[j]) : val[j];
}
ret[key] = retArr;
continue;
}
ret[key] = deep && isPlainObj(val) ? sortKeys(val) : val;
}
return ret;
};
return sortKeys(obj);
};

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,40 @@
{
"name": "sort-keys",
"version": "2.0.0",
"description": "Sort the keys of an object",
"license": "MIT",
"repository": "sindresorhus/sort-keys",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=4"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js"
],
"keywords": [
"sort",
"object",
"keys",
"obj",
"key",
"stable",
"deterministic",
"deep",
"recursive",
"recursively"
],
"dependencies": {
"is-plain-obj": "^1.0.0"
},
"devDependencies": {
"ava": "*",
"xo": "*"
}
}

View File

@@ -0,0 +1,60 @@
# sort-keys [![Build Status](https://travis-ci.org/sindresorhus/sort-keys.svg?branch=master)](https://travis-ci.org/sindresorhus/sort-keys)
> Sort the keys of an object
Useful to get a deterministically ordered object, as the order of keys can vary between engines.
## Install
```
$ npm install --save sort-keys
```
## Usage
```js
const sortKeys = require('sort-keys');
sortKeys({c: 0, a: 0, b: 0});
//=> {a: 0, b: 0, c: 0}
sortKeys({b: {b: 0, a: 0}, a: 0}, {deep: true});
//=> {a: 0, b: {a: 0, b: 0}}
sortKeys({c: 0, a: 0, b: 0}, {
compare: (a, b) => -a.localeCompare(b)
});
//=> {c: 0, b: 0, a: 0}
```
## API
### sortKeys(input, [options])
Returns a new object with sorted keys.
#### input
Type: `Object`
#### options
##### deep
Type: `boolean`
Recursively sort keys.
##### compare
Type: `Function`
[Compare function.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)

View File

@@ -0,0 +1 @@
../../../graceful-fs/4.1.11/node_modules/graceful-fs

View File

@@ -0,0 +1 @@
../../../imurmurhash/0.1.4/node_modules/imurmurhash

View File

@@ -0,0 +1 @@
../../../slide/1.1.6/node_modules/slide

View File

@@ -0,0 +1,6 @@
Copyright (c) 2015, Rebecca Turner
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@@ -0,0 +1,47 @@
write-file-atomic
-----------------
This is an extension for node's `fs.writeFile` that makes its operation
atomic and allows you set ownership (uid/gid of the file).
### var writeFileAtomic = require('write-file-atomic')<br>writeFileAtomic(filename, data, [options], callback)
* filename **String**
* data **String** | **Buffer**
* options **Object**
* chown **Object**
* uid **Number**
* gid **Number**
* encoding **String** | **Null** default = 'utf8'
* fsync **Boolean** default = true
* mode **Number** default = 438 (aka 0666 in Octal)
callback **Function**
Atomically and asynchronously writes data to a file, replacing the file if it already
exists. data can be a string or a buffer.
The file is initially named `filename + "." + murmurhex(__filename, process.pid, ++invocations)`.
If writeFile completes successfully then, if passed the **chown** option it will change
the ownership of the file. Finally it renames the file back to the filename you specified. If
it encounters errors at any of these steps it will attempt to unlink the temporary file and then
pass the error back to the caller.
If provided, the **chown** option requires both **uid** and **gid** properties or else
you'll get an error.
The **encoding** option is ignored if **data** is a buffer. It defaults to 'utf8'.
If the **fsync** option is **false**, writeFile will skip the final fsync call.
Example:
```javascript
writeFileAtomic('message.txt', 'Hello Node', {chown:{uid:100,gid:50}}, function (err) {
if (err) throw err;
console.log('It\'s saved!');
});
```
### var writeFileAtomicSync = require('write-file-atomic').sync<br>writeFileAtomicSync(filename, data, [options])
The synchronous version of **writeFileAtomic**.

View File

@@ -0,0 +1,134 @@
'use strict'
module.exports = writeFile
module.exports.sync = writeFileSync
module.exports._getTmpname = getTmpname // for testing
var fs = require('graceful-fs')
var chain = require('slide').chain
var MurmurHash3 = require('imurmurhash')
var invocations = 0
function getTmpname (filename) {
return filename + '.' +
MurmurHash3(__filename)
.hash(String(process.pid))
.hash(String(++invocations))
.result()
}
function writeFile (filename, data, options, callback) {
if (options instanceof Function) {
callback = options
options = null
}
if (!options) options = {}
fs.realpath(filename, function (_, realname) {
_writeFile(realname || filename, data, options, callback)
})
}
function _writeFile (filename, data, options, callback) {
var tmpfile = getTmpname(filename)
if (options.mode && options.chown) {
return thenWriteFile()
} else {
// Either mode or chown is not explicitly set
// Default behavior is to copy it from original file
return fs.stat(filename, function (err, stats) {
if (err || !stats) return thenWriteFile()
options = Object.assign({}, options)
if (!options.mode) {
options.mode = stats.mode
}
if (!options.chown && process.getuid) {
options.chown = { uid: stats.uid, gid: stats.gid }
}
return thenWriteFile()
})
}
function thenWriteFile () {
chain([
[writeFileAsync, tmpfile, data, options.mode, options.encoding || 'utf8'],
options.chown && [fs, fs.chown, tmpfile, options.chown.uid, options.chown.gid],
options.mode && [fs, fs.chmod, tmpfile, options.mode],
[fs, fs.rename, tmpfile, filename]
], function (err) {
err ? fs.unlink(tmpfile, function () { callback(err) })
: callback()
})
}
// doing this instead of `fs.writeFile` in order to get the ability to
// call `fsync`.
function writeFileAsync (file, data, mode, encoding, cb) {
fs.open(file, 'w', options.mode, function (err, fd) {
if (err) return cb(err)
if (Buffer.isBuffer(data)) {
return fs.write(fd, data, 0, data.length, 0, syncAndClose)
} else if (data != null) {
return fs.write(fd, String(data), 0, String(encoding), syncAndClose)
} else {
return syncAndClose()
}
function syncAndClose (err) {
if (err) return cb(err)
if (options.fsync !== false) {
fs.fsync(fd, function (err) {
if (err) return cb(err)
fs.close(fd, cb)
})
} else {
fs.close(fd, cb)
}
}
})
}
}
function writeFileSync (filename, data, options) {
if (!options) options = {}
try {
filename = fs.realpathSync(filename)
} catch (ex) {
// it's ok, it'll happen on a not yet existing file
}
var tmpfile = getTmpname(filename)
try {
if (!options.mode || !options.chown) {
// Either mode or chown is not explicitly set
// Default behavior is to copy it from original file
try {
var stats = fs.statSync(filename)
options = Object.assign({}, options)
if (!options.mode) {
options.mode = stats.mode
}
if (!options.chown && process.getuid) {
options.chown = { uid: stats.uid, gid: stats.gid }
}
} catch (ex) {
// ignore stat errors
}
}
var fd = fs.openSync(tmpfile, 'w', options.mode)
if (Buffer.isBuffer(data)) {
fs.writeSync(fd, data, 0, data.length, 0)
} else if (data != null) {
fs.writeSync(fd, String(data), 0, String(options.encoding || 'utf8'))
}
if (options.fsync !== false) {
fs.fsyncSync(fd)
}
fs.closeSync(fd)
if (options.chown) fs.chownSync(tmpfile, options.chown.uid, options.chown.gid)
if (options.mode) fs.chmodSync(tmpfile, options.mode)
fs.renameSync(tmpfile, filename)
} catch (err) {
try { fs.unlinkSync(tmpfile) } catch (e) {}
throw err
}
}

View File

@@ -0,0 +1,38 @@
{
"name": "write-file-atomic",
"version": "2.1.0",
"description": "Write files in an atomic fashion w/configurable ownership",
"main": "index.js",
"scripts": {
"test": "standard && tap --100 test/*.js"
},
"repository": {
"type": "git",
"url": "git@github.com:iarna/write-file-atomic.git"
},
"keywords": [
"writeFile",
"atomic"
],
"author": "Rebecca Turner <me@re-becca.org> (http://re-becca.org)",
"license": "ISC",
"bugs": {
"url": "https://github.com/iarna/write-file-atomic/issues"
},
"homepage": "https://github.com/iarna/write-file-atomic",
"dependencies": {
"graceful-fs": "^4.1.11",
"imurmurhash": "^0.1.4",
"slide": "^1.1.5"
},
"devDependencies": {
"mkdirp": "^0.5.1",
"require-inject": "^1.4.0",
"rimraf": "^2.5.4",
"standard": "^10.0.2",
"tap": "^10.3.2"
},
"files": [
"index.js"
]
}

View File

@@ -0,0 +1 @@
../../../detect-indent/5.0.0/node_modules/detect-indent

View File

@@ -0,0 +1 @@
../../../graceful-fs/4.1.11/node_modules/graceful-fs

View File

@@ -0,0 +1 @@
../../../make-dir/1.0.0/node_modules/make-dir

View File

@@ -0,0 +1 @@
../../../pify/2.3.0/node_modules/pify

View File

@@ -0,0 +1 @@
../../../sort-keys/1.1.2/node_modules/sort-keys

View File

@@ -0,0 +1 @@
../../../write-file-atomic/2.1.0/node_modules/write-file-atomic

View File

@@ -0,0 +1,73 @@
'use strict';
const path = require('path');
const fs = require('graceful-fs');
const writeFileAtomic = require('write-file-atomic');
const sortKeys = require('sort-keys');
const makeDir = require('make-dir');
const pify = require('pify');
const detectIndent = require('detect-indent');
const init = (fn, fp, data, opts) => {
if (!fp) {
throw new TypeError('Expected a filepath');
}
if (data === undefined) {
throw new TypeError('Expected data to stringify');
}
opts = Object.assign({
indent: '\t',
sortKeys: false
}, opts);
if (opts.sortKeys) {
data = sortKeys(data, {
deep: true,
compare: typeof opts.sortKeys === 'function' && opts.sortKeys
});
}
return fn(fp, data, opts);
};
const readFile = fp => pify(fs.readFile)(fp, 'utf8').catch(() => {});
const main = (fp, data, opts) => {
return (opts.detectIndent ? readFile(fp) : Promise.resolve())
.then(str => {
const indent = str ? detectIndent(str).indent : opts.indent;
const json = JSON.stringify(data, opts.replacer, indent);
return pify(writeFileAtomic)(fp, `${json}\n`, {mode: opts.mode});
});
};
const mainSync = (fp, data, opts) => {
let indent = opts.indent;
if (opts.detectIndent) {
try {
const file = fs.readFileSync(fp, 'utf8');
indent = detectIndent(file).indent;
} catch (err) {
if (err.code !== 'ENOENT') {
throw err;
}
}
}
const json = JSON.stringify(data, opts.replacer, indent);
return writeFileAtomic.sync(fp, `${json}\n`, {mode: opts.mode});
};
module.exports = (fp, data, opts) => {
return makeDir(path.dirname(fp), {fs})
.then(() => init(main, fp, data, opts));
};
module.exports.sync = (fp, data, opts) => {
makeDir.sync(path.dirname(fp), {fs});
init(mainSync, fp, data, opts);
};

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,48 @@
{
"name": "write-json-file",
"version": "2.2.0",
"description": "Stringify and write JSON to a file atomically",
"license": "MIT",
"repository": "sindresorhus/write-json-file",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=4"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js"
],
"keywords": [
"write",
"json",
"stringify",
"file",
"fs",
"graceful",
"stable",
"sort",
"newline",
"indent",
"atomic",
"atomically"
],
"dependencies": {
"detect-indent": "^5.0.0",
"graceful-fs": "^4.1.2",
"make-dir": "^1.0.0",
"pify": "^2.0.0",
"sort-keys": "^1.1.1",
"write-file-atomic": "^2.0.0"
},
"devDependencies": {
"ava": "*",
"tempfile": "^2.0.0",
"xo": "*"
}
}

View File

@@ -0,0 +1,83 @@
# write-json-file [![Build Status](https://travis-ci.org/sindresorhus/write-json-file.svg?branch=master)](https://travis-ci.org/sindresorhus/write-json-file)
> Stringify and write JSON to a file [atomically](https://github.com/npm/write-file-atomic)
Creates directories for you as needed.
## Install
```
$ npm install --save write-json-file
```
## Usage
```js
const writeJsonFile = require('write-json-file');
writeJsonFile('foo.json', {foo: true}).then(() => {
console.log('done');
});
```
## API
### writeJsonFile(filepath, data, [options])
Returns a `Promise`.
### writeJsonFile.sync(filepath, data, [options])
#### options
Type: `Object`
##### indent
Type: `string` `number`<br>
Default: `\t`
Indentation as a string or number of spaces.<br>
Pass in `null` for no formatting.
##### detectIndent
Type: `boolean`<br>
Default: `false`
Detect indentation automatically if the file exists.
##### sortKeys
Type: `boolean` `function`<br>
Default: `false`
Sort the keys recursively.<br>
Optionally pass in a [`compare`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) function.
##### replacer
Type: `function`
Passed into [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter).
##### mode
Type: `number`<br>
Default: `0o666`
[Mode](https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation) used when writing the file.
## Related
- [load-json-file](https://github.com/sindresorhus/load-json-file) - Read and parse a JSON file
- [make-dir](https://github.com/sindresorhus/make-dir) - Make a directory and its parents if needed
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)

View File

@@ -0,0 +1 @@
../../../sort-keys/2.0.0/node_modules/sort-keys

View File

@@ -0,0 +1 @@
../../../write-json-file/2.2.0/node_modules/write-json-file

View File

@@ -0,0 +1,53 @@
'use strict';
const path = require('path');
const writeJsonFile = require('write-json-file');
const sortKeys = require('sort-keys');
const opts = {detectIndent: true};
const dependencyKeys = new Set([
'dependencies',
'devDependencies',
'optionalDependencies',
'peerDependencies'
]);
function normalize(pkg) {
const ret = {};
for (const key of Object.keys(pkg)) {
if (!dependencyKeys.has(key)) {
ret[key] = pkg[key];
} else if (Object.keys(pkg[key]).length !== 0) {
ret[key] = sortKeys(pkg[key]);
}
}
return ret;
}
module.exports = (fp, data) => {
if (typeof fp !== 'string') {
data = fp;
fp = '.';
}
fp = path.basename(fp) === 'package.json' ? fp : path.join(fp, 'package.json');
data = normalize(data);
return writeJsonFile(fp, data, opts);
};
module.exports.sync = (fp, data) => {
if (typeof fp !== 'string') {
data = fp;
fp = '.';
}
fp = path.basename(fp) === 'package.json' ? fp : path.join(fp, 'package.json');
data = normalize(data);
writeJsonFile.sync(fp, data, opts);
};

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,41 @@
{
"name": "write-pkg",
"version": "3.1.0",
"description": "Write a package.json file",
"license": "MIT",
"repository": "sindresorhus/write-pkg",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=4"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js"
],
"keywords": [
"json",
"write",
"stringify",
"file",
"fs",
"graceful",
"pkg",
"package"
],
"dependencies": {
"sort-keys": "^2.0.0",
"write-json-file": "^2.2.0"
},
"devDependencies": {
"ava": "*",
"read-pkg": "^2.0.0",
"tempfile": "^2.0.0",
"xo": "*"
}
}

View File

@@ -0,0 +1,59 @@
# write-pkg [![Build Status](https://travis-ci.org/sindresorhus/write-pkg.svg?branch=master)](https://travis-ci.org/sindresorhus/write-pkg)
> Write a `package.json` file
Writes atomically and creates directories for you as needed. Sorts dependencies when writing. Preserves the indentation if the file already exists.
## Install
```
$ npm install write-pkg
```
## Usage
```js
const path = require('path');
const writePkg = require('write-pkg');
writePkg({foo: true}).then(() => {
console.log('done');
});
writePkg(__dirname, {foo: true}).then(() => {
console.log('done');
});
writePkg(path.join('unicorn', 'package.json'), {foo: true}).then(() => {
console.log('done');
});
```
## API
### writePkg([path], data)
Returns a `Promise`.
### writePkg.sync([path], data)
#### path
Type: `string`<br>
Default: `process.cwd()`
Path to where the `package.json` file should be written or its directory.
## Related
- [read-pkg](https://github.com/sindresorhus/read-pkg) - Read a `package.json` file
- [write-json-file](https://github.com/sindresorhus/write-json-file) - Stringify and write JSON to a file atomically
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)

63
example/node_modules/.shrinkwrap.yaml generated vendored Normal file
View File

@@ -0,0 +1,63 @@
dependencies:
write-pkg: 3.1.0
packages:
/detect-indent/5.0.0:
resolution:
integrity: sha1-OHHMCmoALow+Wzz38zYmRnXwa50=
/graceful-fs/4.1.11:
resolution:
integrity: sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=
/imurmurhash/0.1.4:
resolution:
integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=
/is-plain-obj/1.1.0:
resolution:
integrity: sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
/make-dir/1.0.0:
dependencies:
pify: 2.3.0
resolution:
integrity: sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=
/pify/2.3.0:
resolution:
integrity: sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
/slide/1.1.6:
resolution:
integrity: sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=
/sort-keys/1.1.2:
dependencies:
is-plain-obj: 1.1.0
resolution:
integrity: sha1-RBttTTRnmPG05J6JIK37oOVD+a0=
/sort-keys/2.0.0:
dependencies:
is-plain-obj: 1.1.0
resolution:
integrity: sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=
/write-file-atomic/2.1.0:
dependencies:
graceful-fs: 4.1.11
imurmurhash: 0.1.4
slide: 1.1.6
resolution:
integrity: sha512-0TZ20a+xcIl4u0+Mj5xDH2yOWdmQiXlKf9Hm+TgDXjTMsEYb+gDrmb8e8UNAzMCitX8NBqG4Z/FUQIyzv/R1JQ==
/write-json-file/2.2.0:
dependencies:
detect-indent: 5.0.0
graceful-fs: 4.1.11
make-dir: 1.0.0
pify: 2.3.0
sort-keys: 1.1.2
write-file-atomic: 2.1.0
resolution:
integrity: sha1-UYYlBruzthnu+reFnx/WxtBTCHY=
/write-pkg/3.1.0:
dependencies:
sort-keys: 2.0.0
write-json-file: 2.2.0
resolution:
integrity: sha1-AwqZlMyZk9JbTnWp8aGSNgcpHOk=
registry: 'https://registry.npmjs.org/'
shrinkwrapVersion: 3
specifiers:
write-pkg: ^3.1.0

1
example/node_modules/write-pkg generated vendored Symbolic link
View File

@@ -0,0 +1 @@
.registry.npmjs.org/write-pkg/3.1.0/node_modules/write-pkg