json-file-plus
Advanced tools
Comparing version
32
index.js
@@ -5,5 +5,4 @@ var fs = require('fs'); | ||
var is = require('is'); | ||
var promiseback = require('promiseback'); | ||
var setImmediate = setImmediate || function (func) { setTimeout(func, 0); }; | ||
var JSONFile = function (filename, raw) { | ||
@@ -31,6 +30,5 @@ var hasTrailingNewline = (/\n\n$/).test(raw); | ||
} | ||
if (is.fn(callback)) { | ||
setImmediate(function () { callback(null, value); }); | ||
} | ||
return value; | ||
var deferred = promiseback(callback); | ||
deferred.resolve(value); | ||
return deferred.promise; | ||
}; | ||
@@ -45,9 +43,16 @@ JSONFile.prototype.set = function (obj) { | ||
var json = new Buffer(JSON.stringify(this.data, null, indent) + endingNewlines); | ||
fs.writeFile(this.filename, json, callback); | ||
var deferred = promiseback(callback); | ||
fs.writeFile(this.filename, json, deferred.resolve); | ||
return deferred.promise; | ||
}; | ||
var readJSON = function (filename, callback) { | ||
if (!is.fn(callback)) { | ||
throw new TypeError('callback must be a function'); | ||
var readJSON = function (filename) { | ||
var callback; | ||
if (arguments.length > 1) { | ||
callback = arguments[1]; | ||
if (!is.fn(callback)) { | ||
throw new TypeError('callback must be a function if provided'); | ||
} | ||
} | ||
var deferred = promiseback(callback); | ||
fs.readFile(filename, { encoding: 'utf8' }, function (err, raw) { | ||
@@ -60,4 +65,9 @@ var file; | ||
} | ||
callback(err, file); | ||
if (err) { | ||
deferred.reject(err); | ||
} else { | ||
deferred.resolve(file); | ||
} | ||
}); | ||
return deferred.promise; | ||
}; | ||
@@ -64,0 +74,0 @@ readJSON.JSONFile = JSONFile; |
{ | ||
"name": "json-file-plus", | ||
"version": "1.0.7", | ||
"version": "2.0.0", | ||
"author": "Jordan Harband", | ||
@@ -23,14 +23,17 @@ "description": "Read from and write to a JSON file, minimizing diffs and preserving formatting.", | ||
"read", | ||
"write" | ||
"write", | ||
"promise", | ||
"promiseback" | ||
], | ||
"dependencies": { | ||
"is": "~2.0.1", | ||
"node.extend": "~1.1.2" | ||
"node.extend": "~1.1.2", | ||
"promiseback": "~2.0.0" | ||
}, | ||
"devDependencies": { | ||
"tape": "~2.14.0", | ||
"foreach": "~2.0.4", | ||
"tape": "~3.0.0", | ||
"foreach": "~2.0.5", | ||
"object-keys": "~1.0.1", | ||
"covert": "~1.0.0", | ||
"jscs": "~1.6.1" | ||
"jscs": "~1.6.2" | ||
}, | ||
@@ -37,0 +40,0 @@ "engines": { |
@@ -1,10 +0,10 @@ | ||
#json-file-plus <sup>[![Version Badge][2]][1]</sup> | ||
#json-file-plus <sup>[![Version Badge][npm-version-svg]][npm-url]</sup> | ||
[![Build Status][3]][4] | ||
[![dependency status][5]][6] | ||
[![dev dependency status][7]][8] | ||
[![Build Status][travis-svg]][travis-url] | ||
[![dependency status][deps-svg]][deps-url] | ||
[![dev dependency status][dev-deps-svg]][dev-deps-url] | ||
[![License][license-image]][license-url] | ||
[![Downloads][downloads-image]][downloads-url] | ||
[![npm badge][9]][1] | ||
[![npm badge][npm-badge-png]][npm-url] | ||
@@ -18,2 +18,3 @@ A module to read from and write to JSON files, without losing formatting, to minimize diffs. | ||
var filename = path.join(process.cwd(), 'package.json'); | ||
/* Note: jsonFile also returns a Promise, if you prefer that to a Node-style callback ("errorback"). */ | ||
jsonFile(filename, function (err, file) { | ||
@@ -25,6 +26,6 @@ if (err) { return doSomethingWithError(err); } | ||
file.get('version'); // get top-level keys, synchronously | ||
file.get('version', callback); // get top-level keys, asynchronously | ||
file.get(); // get entire data, synchronously | ||
file.get(callback); // get entire data, asynchronously | ||
file.get('version'); // get top-level keys. returns a Promise | ||
file.get('version', callback); // get top-level keys. calls the errorback | ||
file.get(); // get entire data. returns a Promise | ||
file.get(callback); // get entire data. calls the errorback | ||
@@ -45,4 +46,9 @@ /* pass any plain object into "set" to merge in a deep copy */ | ||
/* Save the file, preserving formatting. */ | ||
/* Callback will be passed to fs.writeFile */ | ||
file.save(fsWriteFileCallback); | ||
/* Errorback will be passed to fs.writeFile */ | ||
/* Returns a Promise. */ | ||
file.save(fsWriteFileCallback).then(function () { | ||
console.log('success!'); | ||
}, function (err) { | ||
console.log('error!', err); | ||
}); | ||
}); | ||
@@ -54,11 +60,11 @@ ``` | ||
[1]: https://npmjs.org/package/json-file-plus | ||
[2]: http://vb.teelaun.ch/ljharb/node-json-file.svg | ||
[3]: https://travis-ci.org/ljharb/node-json-file.svg | ||
[4]: https://travis-ci.org/ljharb/node-json-file | ||
[5]: https://david-dm.org/ljharb/node-json-file.svg | ||
[6]: https://david-dm.org/ljharb/node-json-file | ||
[7]: https://david-dm.org/ljharb/node-json-file/dev-status.svg | ||
[8]: https://david-dm.org/ljharb/node-json-file#info=devDependencies | ||
[9]: https://nodei.co/npm/json-file-plus.png?downloads=true&stars=true | ||
[npm-url]: https://npmjs.org/package/json-file-plus | ||
[npm-version-svg]: http://vb.teelaun.ch/ljharb/node-json-file.svg | ||
[travis-svg]: https://travis-ci.org/ljharb/node-json-file.svg | ||
[travis-url]: https://travis-ci.org/ljharb/node-json-file | ||
[deps-svg]: https://david-dm.org/ljharb/node-json-file.svg | ||
[deps-url]: https://david-dm.org/ljharb/node-json-file | ||
[dev-deps-svg]: https://david-dm.org/ljharb/node-json-file/dev-status.svg | ||
[dev-deps-url]: https://david-dm.org/ljharb/node-json-file#info=devDependencies | ||
[npm-badge-png]: https://nodei.co/npm/json-file-plus.png?downloads=true&stars=true | ||
[license-image]: http://img.shields.io/npm/l/json-file-plus.svg | ||
@@ -65,0 +71,0 @@ [license-url]: LICENSE |
@@ -24,5 +24,5 @@ var test = require('tape'); | ||
test('requires a callback', function (t) { | ||
test('requires a callback when arg is provided', function (t) { | ||
t.plan(6); | ||
t.throws(function () { jsonFile(testFilename); }, TypeError, 'requires a function'); | ||
t.throws(function () { jsonFile(testFilename, undefined); }, TypeError, 'requires a function'); | ||
t.throws(function () { jsonFile(testFilename, null); }, TypeError, 'requires a function'); | ||
@@ -100,8 +100,10 @@ t.throws(function () { jsonFile(testFilename, true); }, TypeError, 'requires a function'); | ||
st.deepEqual(file.data, testContents, 'file.data matches expected'); | ||
st.notEqual(file.get('obj'), file.data.obj, 'get(key)->object is not the same reference'); | ||
st.end(); | ||
file.get('obj').then(function (value) { | ||
st.notEqual(value, file.data.obj, 'get(key)->object is not the same reference'); | ||
st.end(); | ||
}); | ||
}); | ||
}); | ||
test('#get(): with key sync', function (st) { | ||
test('#get(): with key, promise', function (st) { | ||
st.plan(keys(testContents).length + 1); | ||
@@ -111,9 +113,10 @@ jsonFile(testFilename, function (err, file) { | ||
forEach(testContents, function (keyContents, key) { | ||
st.deepEqual(file.get(key), keyContents, 'data from get("' + key + '") matches'); | ||
file.get(key).then(function (value) { | ||
st.deepEqual(value, keyContents, 'data from get("' + key + '") matches'); | ||
}); | ||
}); | ||
st.end(); | ||
}); | ||
}); | ||
test('#get(): with key async', function (st) { | ||
test('#get(): with key, callback', function (st) { | ||
st.plan(keys(testContents).length + 1); | ||
@@ -124,3 +127,3 @@ jsonFile(testFilename, function (err, file) { | ||
file.get(key, function (err, data) { | ||
st.deepEqual(data, keyContents, 'data from async get("' + key + '") matches'); | ||
st.deepEqual(data, keyContents, 'data from callback get("' + key + '") matches'); | ||
}); | ||
@@ -131,14 +134,15 @@ }); | ||
test('#get(): without key sync', function (s2t) { | ||
test('#get(): without key, promise', function (s2t) { | ||
s2t.plan(3); | ||
jsonFile(testFilename, function (err, file) { | ||
s2t.error(err, 'no error'); | ||
var getData = file.get(); | ||
s2t.deepEqual(getData, file.data, 'data from get() matches'); | ||
s2t.notEqual(getData, file.data, 'data from get() is not the same reference'); | ||
s2t.end(); | ||
file.get().then(function (getData) { | ||
s2t.deepEqual(getData, file.data, 'data from get() matches'); | ||
s2t.notEqual(getData, file.data, 'data from get() is not the same reference'); | ||
s2t.end(); | ||
}); | ||
}); | ||
}); | ||
test('#get(): without key async', function (s2t) { | ||
test('#get(): without key, callback', function (s2t) { | ||
s2t.plan(3); | ||
@@ -214,3 +218,3 @@ jsonFile(testFilename, function (err, file) { | ||
test('saves properly', function (t) { | ||
t.plan(4); | ||
t.plan(5); | ||
jsonFile(testFilename, function (err, file) { | ||
@@ -222,7 +226,12 @@ t.equal(file.filename, testFilename, 'filename equals ' + testFilename); | ||
jsonFile(testFilename, function (err, file2) { | ||
t.equal(file2.get('foo'), !testContents.foo, 'value was properly saved'); | ||
file2.set({ foo: testContents.foo }); // restore original value | ||
file2.save(function (err) { | ||
t.error(err, 'no error'); | ||
t.end(); | ||
file2.get('foo').then(function (value) { | ||
t.equal(value, !testContents.foo, 'value was properly saved'); | ||
file2.set({ foo: testContents.foo }); // restore original value | ||
file2.save(function (err) { | ||
t.error(err, 'save callback: no error'); | ||
}).then(function () { | ||
t.ok(true, 'save promise: success'); | ||
}, function (err) { | ||
t.fail('save promise: error. should not be here.'); | ||
}); | ||
}); | ||
@@ -229,0 +238,0 @@ }); |
19137
5.84%124184
6.66%332
6.41%71
9.23%3
50%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added