lowdb
Advanced tools
Comparing version 0.16.2 to 0.17.0
@@ -1,3 +0,3 @@ | ||
/*! lowdb v0.16.2 */ | ||
var low = | ||
/*! lowdb v0.17.0 */ | ||
var lowdb = | ||
/******/ (function(modules) { // webpackBootstrap | ||
@@ -11,5 +11,5 @@ /******/ // The module cache | ||
/******/ // Check if module is in cache | ||
/******/ if(installedModules[moduleId]) | ||
/******/ if(installedModules[moduleId]) { | ||
/******/ return installedModules[moduleId].exports; | ||
/******/ | ||
/******/ } | ||
/******/ // Create a new module (and put it into the cache) | ||
@@ -39,5 +39,2 @@ /******/ var module = installedModules[moduleId] = { | ||
/******/ | ||
/******/ // identity function for calling harmony imports with the correct context | ||
/******/ __webpack_require__.i = function(value) { return value; }; | ||
/******/ | ||
/******/ // define getter function for harmony exports | ||
@@ -70,3 +67,3 @@ /******/ __webpack_require__.d = function(exports, name, getter) { | ||
/******/ // Load entry module and return exports | ||
/******/ return __webpack_require__(__webpack_require__.s = 2); | ||
/******/ return __webpack_require__(__webpack_require__.s = 0); | ||
/******/ }) | ||
@@ -81,52 +78,50 @@ /************************************************************************/ | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
var isPromise = __webpack_require__(6); | ||
var memory = __webpack_require__(5); | ||
var defaultStorage = __webpack_require__(4); | ||
var lodash = __webpack_require__(1); | ||
var isPromise = __webpack_require__(2); | ||
var init = function init(db, key, source) { | ||
var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}, | ||
_ref$storage = _ref.storage, | ||
storage = _ref$storage === undefined ? defaultStorage : _ref$storage, | ||
_ref$format = _ref.format, | ||
format = _ref$format === undefined ? {} : _ref$format; | ||
module.exports = function (adapter) { | ||
if ((typeof adapter === 'undefined' ? 'undefined' : _typeof(adapter)) !== 'object') { | ||
throw new Error('An adapter must be provided, see https://github.com/typicode/lowdb/#usage'); | ||
} | ||
db.source = source; | ||
// Create a fresh copy of lodash | ||
var _ = lodash.runInContext(); | ||
var db = _.chain({}); | ||
// Set storage | ||
// In-memory only if no source is provided | ||
db.storage = _extends({}, memory, db.source && storage); | ||
// Add write function to lodash | ||
// Calls save before returning result | ||
_.prototype.write = _.wrap(_.prototype.value, function (func) { | ||
var funcRes = func.apply(this); | ||
return db.write(funcRes); | ||
}); | ||
db.read = function () { | ||
var s = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : source; | ||
function plant(state) { | ||
db.__wrapped__ = state; | ||
return db; | ||
} | ||
var r = db.storage.read(s, format.deserialize); | ||
// Lowdb API | ||
// Expose _ for mixins | ||
db._ = _; | ||
return isPromise(r) ? r.then(db.plant) : db.plant(r); | ||
db.read = function () { | ||
var r = adapter.read(); | ||
return isPromise(r) ? r.then(plant) : plant(r); | ||
}; | ||
db.write = function () { | ||
var dest = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : source; | ||
var value = (arguments.length <= 1 ? 0 : arguments.length - 1) ? arguments.length <= 1 ? undefined : arguments[1] : db.getState(); | ||
var w = db.storage.write(dest, db.getState(), format.serialize); | ||
db.write = function (returnValue) { | ||
var w = adapter.write(db.getState()); | ||
return isPromise(w) ? w.then(function () { | ||
return value; | ||
}) : value; | ||
return returnValue; | ||
}) : returnValue; | ||
}; | ||
db.plant = function (state) { | ||
db[key] = state; | ||
return db; | ||
}; | ||
db.getState = function () { | ||
return db[key]; | ||
return db.__wrapped__; | ||
}; | ||
db.setState = function (state) { | ||
db.plant(state); | ||
return db.write(); | ||
return plant(state); | ||
}; | ||
@@ -137,6 +132,2 @@ | ||
module.exports = { | ||
init: init | ||
}; | ||
/***/ }), | ||
@@ -150,91 +141,2 @@ /* 1 */ | ||
/* 2 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
"use strict"; | ||
var lodash = __webpack_require__(1); | ||
var common = __webpack_require__(0); | ||
module.exports = function (source) { | ||
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
// Create a fresh copy of lodash | ||
var _ = lodash.runInContext(); | ||
var db = _.chain({}); | ||
// Expose _ for mixins | ||
db._ = _; | ||
// Add write function to lodash | ||
// Calls save before returning result | ||
_.prototype.write = _.wrap(_.prototype.value, function (func) { | ||
var dest = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : source; | ||
var funcRes = func.apply(this); | ||
return db.write(dest, funcRes); | ||
}); | ||
return common.init(db, '__wrapped__', source, opts); | ||
}; | ||
/***/ }), | ||
/* 3 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
"use strict"; | ||
// Pretty stringify | ||
module.exports = function stringify(obj) { | ||
return JSON.stringify(obj, null, 2); | ||
}; | ||
/***/ }), | ||
/* 4 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
"use strict"; | ||
/* global localStorage */ | ||
var stringify = __webpack_require__(3); | ||
module.exports = { | ||
read: function browserRead(source) { | ||
var deserialize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : JSON.parse; | ||
var data = localStorage.getItem(source); | ||
if (data) { | ||
return deserialize(data); | ||
} else { | ||
localStorage.setItem(source, '{}'); | ||
return {}; | ||
} | ||
}, | ||
write: function browserWrite(dest, obj) { | ||
var serialize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringify; | ||
localStorage.setItem(dest, serialize(obj)); | ||
} | ||
}; | ||
/***/ }), | ||
/* 5 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
"use strict"; | ||
module.exports = { | ||
read: function memoryRead() { | ||
return {}; | ||
}, | ||
write: function memoryWrite() { | ||
return {}; | ||
} | ||
}; | ||
/***/ }), | ||
/* 6 */ | ||
/***/ (function(module, exports) { | ||
@@ -241,0 +143,0 @@ |
@@ -1,2 +0,2 @@ | ||
/*! lowdb v0.16.2 */ | ||
var low=function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var n={};return e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=2)}([function(t,e,n){"use strict";var r=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},o=n(6),i=n(5),u=n(4),a=function(t,e,n){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},c=a.storage,f=void 0===c?u:c,s=a.format,l=void 0===s?{}:s;return t.source=n,t.storage=r({},i,t.source&&f),t.read=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:n,r=t.storage.read(e,l.deserialize);return o(r)?r.then(t.plant):t.plant(r)},t.write=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:n,r=(arguments.length<=1?0:arguments.length-1)?arguments.length<=1?void 0:arguments[1]:t.getState(),i=t.storage.write(e,t.getState(),l.serialize);return o(i)?i.then(function(){return r}):r},t.plant=function(n){return t[e]=n,t},t.getState=function(){return t[e]},t.setState=function(e){return t.plant(e),t.write()},t.read()};t.exports={init:a}},function(t,e){t.exports=_},function(t,e,n){"use strict";var r=n(1),o=n(0);t.exports=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=r.runInContext(),i=n.chain({});return i._=n,n.prototype.write=n.wrap(n.prototype.value,function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t,r=e.apply(this);return i.write(n,r)}),o.init(i,"__wrapped__",t,e)}},function(t,e,n){"use strict";t.exports=function(t){return JSON.stringify(t,null,2)}},function(t,e,n){"use strict";var r=n(3);t.exports={read:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:JSON.parse,n=localStorage.getItem(t);return n?e(n):(localStorage.setItem(t,"{}"),{})},write:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:r;localStorage.setItem(t,n(e))}}},function(t,e,n){"use strict";t.exports={read:function(){return{}},write:function(){return{}}}},function(t,e){function n(t){return!!t&&("object"==typeof t||"function"==typeof t)&&"function"==typeof t.then}t.exports=n}]); | ||
/*! lowdb v0.17.0 */ | ||
var lowdb=function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},o=n(1),u=n(2);t.exports=function(t){function e(t){return i.__wrapped__=t,i}if("object"!==(void 0===t?"undefined":r(t)))throw new Error("An adapter must be provided, see https://github.com/typicode/lowdb/#usage");var n=o.runInContext(),i=n.chain({});return n.prototype.write=n.wrap(n.prototype.value,function(t){var e=t.apply(this);return i.write(e)}),i._=n,i.read=function(){var n=t.read();return u(n)?n.then(e):e(n)},i.write=function(e){var n=t.write(i.getState());return u(n)?n.then(function(){return e}):e},i.getState=function(){return i.__wrapped__},i.setState=function(t){return e(t)},i.read()}},function(t,e){t.exports=_},function(t,e){function n(t){return!!t&&("object"==typeof t||"function"==typeof t)&&"function"==typeof t.then}t.exports=n}]); |
@@ -13,3 +13,3 @@ # lowdb/lib/fp | ||
import low from 'lowdb/lib/fp' | ||
import { concat, find, sortBy, pick } from 'lodash/fp' | ||
import { concat, find, sortBy, take, random } from 'lodash/fp' | ||
@@ -25,3 +25,3 @@ const db = low() | ||
posts.write( | ||
concat({ title: 'lowdb is awesome' }) | ||
concat({ title: 'lowdb is awesome', views: random(0, 5) }) | ||
) | ||
@@ -37,3 +37,3 @@ | ||
sortBy('views'), | ||
pick(5) | ||
take(5) | ||
]) | ||
@@ -40,0 +40,0 @@ ``` |
@@ -6,6 +6,8 @@ # Examples | ||
```js | ||
// cli.js | ||
const low = require('lowdb') | ||
const db = low('db.json') | ||
const FileSync = require('lowdb/adapters/FileSync') | ||
const adapter = new FileSync('db.json') | ||
const db = low(adapter) | ||
db.defaults({ posts: [] }) | ||
@@ -30,4 +32,7 @@ .write() | ||
import low from 'lowdb' | ||
const db = low('db') | ||
import LocalStorage from 'lowdb/adapters/LocalStorage' | ||
const adapter = new LocalStorage('db') | ||
const db = low(adapter) | ||
db.defaults({ posts: [] }) | ||
@@ -51,3 +56,3 @@ .write() | ||
const low = require('lowdb') | ||
const fileAsync = require('lowdb/lib/storages/file-async') | ||
const FileAsync = require('lowdb/lib/adapters/FileAsync') | ||
@@ -57,8 +62,2 @@ // Create server | ||
// Start database using file-async storage | ||
// For ease of use, read is synchronous | ||
const db = low('db.json', { | ||
storage: fileAsync | ||
}) | ||
// Routes | ||
@@ -84,34 +83,30 @@ // GET /posts/:id | ||
// Init | ||
db.defaults({ posts: [] }) | ||
.write() | ||
// Create database instance and start server | ||
const adapter = new FileAsync('db.json') | ||
low(adapter) | ||
.then(db => { | ||
db.defaults({ posts: [] }) | ||
.write() | ||
}) | ||
.then(() => { | ||
app.listen(3000, () => console.log('Server is listening') | ||
}) | ||
app.listen(3000, () => console.log('listening on port 3000') | ||
}) | ||
``` | ||
Using ES7 `async/await` and [Babel](https://babeljs.io/), you can simplify the previous `POST` example above like this: | ||
```js | ||
app.post('/posts', async (req, res) => { | ||
const post = await db.get('posts') | ||
.push(req.body) | ||
.last() | ||
.assign({ id: Date.now() }) | ||
.write() | ||
res.send(post) | ||
}) | ||
``` | ||
## In-memory | ||
In this mode, no storage is used. Everything is done in memory. | ||
With this adapter, calling `write` will do nothing. One use case for this adapter can be for tests. | ||
You can still persist data but you'll have to do it yourself. Here's an example: | ||
```js | ||
const fs = require('fs') | ||
const db = low() | ||
const low = require('low') | ||
const FileSync = require('low/adapters/FileSync') | ||
const Memory = require('low/adapters/Memory') | ||
const db = low( | ||
process.env.NODE_ENV === 'test' | ||
? new Memory() | ||
: new FileSync('db.json') | ||
) | ||
db.defaults({ posts: [] }) | ||
@@ -123,7 +118,2 @@ .write() | ||
.write() | ||
// Manual writing | ||
fs.writeFileSync('db.json', JSON.stringify(db.getState())) | ||
``` | ||
In this case, it's recommended to create a custom storage. |
'use strict'; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var isPromise = require('is-promise'); | ||
var memory = require('./storages/memory'); | ||
var defaultStorage = require('./storages/file-sync'); | ||
var init = function init(db, key, source) { | ||
var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}, | ||
_ref$storage = _ref.storage, | ||
storage = _ref$storage === undefined ? defaultStorage : _ref$storage, | ||
_ref$format = _ref.format, | ||
format = _ref$format === undefined ? {} : _ref$format; | ||
db.source = source; | ||
// Set storage | ||
// In-memory only if no source is provided | ||
db.storage = _extends({}, memory, db.source && storage); | ||
var init = function init(db, key, adapter) { | ||
db.read = function () { | ||
var s = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : source; | ||
var r = adapter.read(); | ||
var r = db.storage.read(s, format.deserialize); | ||
return isPromise(r) ? r.then(db.plant) : db.plant(r); | ||
@@ -31,7 +13,6 @@ }; | ||
db.write = function () { | ||
var dest = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : source; | ||
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : db.getState(); | ||
var value = (arguments.length <= 1 ? 0 : arguments.length - 1) ? arguments.length <= 1 ? undefined : arguments[1] : db.getState(); | ||
var w = adapter.write(db.getState()); | ||
var w = db.storage.write(dest, db.getState(), format.serialize); | ||
return isPromise(w) ? w.then(function () { | ||
@@ -53,3 +34,3 @@ return value; | ||
db.plant(state); | ||
return db.write(); | ||
return db; | ||
}; | ||
@@ -56,0 +37,0 @@ |
@@ -8,5 +8,3 @@ 'use strict'; | ||
module.exports = function (source) { | ||
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
module.exports = function (adapter) { | ||
function db(path, defaultValue) { | ||
@@ -21,3 +19,3 @@ function getValue(funcs) { | ||
set(db.getState(), path, result); | ||
return db.write(source, result); | ||
return db.write(); | ||
}; | ||
@@ -28,3 +26,3 @@ | ||
return common.init(db, '__state__', source, opts); | ||
return common.init(db, '__state__', adapter); | ||
}; |
'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
var lodash = require('lodash'); | ||
var common = require('./common'); | ||
var isPromise = require('is-promise'); | ||
module.exports = function (source) { | ||
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
module.exports = function (adapter) { | ||
if ((typeof adapter === 'undefined' ? 'undefined' : _typeof(adapter)) !== 'object') { | ||
throw new Error('An adapter must be provided, see https://github.com/typicode/lowdb/#usage'); | ||
} | ||
@@ -13,15 +17,39 @@ // Create a fresh copy of lodash | ||
// Expose _ for mixins | ||
db._ = _; | ||
// Add write function to lodash | ||
// Calls save before returning result | ||
_.prototype.write = _.wrap(_.prototype.value, function (func) { | ||
var dest = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : source; | ||
var funcRes = func.apply(this); | ||
return db.write(dest, funcRes); | ||
return db.write(funcRes); | ||
}); | ||
return common.init(db, '__wrapped__', source, opts); | ||
function plant(state) { | ||
db.__wrapped__ = state; | ||
return db; | ||
} | ||
// Lowdb API | ||
// Expose _ for mixins | ||
db._ = _; | ||
db.read = function () { | ||
var r = adapter.read(); | ||
return isPromise(r) ? r.then(plant) : plant(r); | ||
}; | ||
db.write = function (returnValue) { | ||
var w = adapter.write(db.getState()); | ||
return isPromise(w) ? w.then(function () { | ||
return returnValue; | ||
}) : returnValue; | ||
}; | ||
db.getState = function () { | ||
return db.__wrapped__; | ||
}; | ||
db.setState = function (state) { | ||
return plant(state); | ||
}; | ||
return db.read(); | ||
}; |
@@ -5,6 +5,4 @@ 'use strict'; | ||
module.exports = function (source) { | ||
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
return common.init({}, '__state__', source, opts); | ||
module.exports = function (adapter) { | ||
return common.init({}, '__state__', adapter); | ||
}; |
{ | ||
"name": "lowdb", | ||
"version": "0.16.2", | ||
"version": "0.17.0", | ||
"description": "JSON database for Node and the browser powered by lodash API", | ||
@@ -21,10 +21,10 @@ "keywords": [ | ||
"scripts": { | ||
"test": "npm run tape && standard", | ||
"fix": "standard --fix", | ||
"tape": "tape -r babel-register -r babel-polyfill test/*.js | tap-spec", | ||
"prepublish": "npm run build && pkg-ok", | ||
"precommit": "npm test", | ||
"test": "jest && npm run lint", | ||
"lint": "eslint . --ignore-path .gitignore", | ||
"fix": "npm run lint -- --fix", | ||
"prepublishOnly": "npm run build && pkg-ok", | ||
"build": "npm run build:lib && npm run build:dist", | ||
"build:lib": "rimraf lib && babel src --out-dir lib", | ||
"build:dist": "rimraf dist && webpack && webpack -p" | ||
"build:lib": "rimraf lib && babel src --out-dir lib && mv lib/adapters adapters", | ||
"build:dist": "rimraf dist && webpack && webpack -p", | ||
"precommit": "npm test" | ||
}, | ||
@@ -45,2 +45,3 @@ "repository": { | ||
"lodash": "4", | ||
"pify": "^3.0.0", | ||
"steno": "^0.4.1" | ||
@@ -51,29 +52,32 @@ }, | ||
"babel-eslint": "^7.0.0", | ||
"babel-loader": "^6.2.2", | ||
"babel-jest": "^20.0.3", | ||
"babel-loader": "^7.1.1", | ||
"babel-polyfill": "^6.9.1", | ||
"babel-preset-es2015": "^6.1.18", | ||
"babel-preset-stage-3": "^6.3.13", | ||
"babel-preset-env": "^1.6.0", | ||
"babel-register": "^6.9.0", | ||
"husky": "^0.13.0", | ||
"lodash-id": "^0.13.0", | ||
"delay": "^2.0.0", | ||
"eslint": "^3.19.0", | ||
"eslint-config-prettier": "^2.3.0", | ||
"eslint-config-standard": "^10.2.1", | ||
"eslint-plugin-import": "^2.6.1", | ||
"eslint-plugin-node": "^5.1.0", | ||
"eslint-plugin-prettier": "^2.1.2", | ||
"eslint-plugin-promise": "^3.5.0", | ||
"eslint-plugin-standard": "^3.0.1", | ||
"husky": "^0.14.3", | ||
"jest": "^20.0.4", | ||
"lodash-id": "^0.14.0", | ||
"mv": "^2.1.1", | ||
"pkg-ok": "^1.0.1", | ||
"ramda": "^0.23.0", | ||
"prettier": "^1.5.2", | ||
"ramda": "^0.24.1", | ||
"regenerator-runtime": "^0.11.0", | ||
"rimraf": "^2.5.4", | ||
"sinon": "^1.17.2", | ||
"standard": "^8.5.0", | ||
"tap-spec": "^4.1.1", | ||
"tape": "^4.2.2", | ||
"tempfile": "^1.1.1", | ||
"webpack": "^2.2.1" | ||
"sinon": "^2.3.8", | ||
"tempfile": "^2.0.0", | ||
"webpack": "^3.3.0" | ||
}, | ||
"engines": { | ||
"node": ">= 0.12" | ||
}, | ||
"browser": { | ||
"./src/storages/file-sync.js": "./src/storages/browser.js", | ||
"./lib/storages/file-sync.js": "./lib/storages/browser.js" | ||
}, | ||
"standard": { | ||
"parser": "babel-eslint" | ||
"node": ">=4" | ||
} | ||
} |
234
README.md
@@ -1,8 +0,26 @@ | ||
# Lowdb [![NPM version](https://badge.fury.io/js/lowdb.svg)](http://badge.fury.io/js/lowdb) [![Build Status](https://travis-ci.org/typicode/lowdb.svg?branch=master)](https://travis-ci.org/typicode/lowdb) | ||
# Lowdb | ||
> A small local database powered by lodash API | ||
[![](http://img.shields.io/npm/dm/lowdb.svg?style=flat)](https://www.npmjs.org/package/lowdb) [![NPM version](https://badge.fury.io/js/lowdb.svg)](http://badge.fury.io/js/lowdb) [![Build Status](https://travis-ci.org/typicode/lowdb.svg?branch=master)](https://travis-ci.org/typicode/lowdb) [![Support on Patreon](https://img.shields.io/badge/Patreon-%E2%99%A5-ff69b4.svg)](https://www.patreon.com/typicode) | ||
> Lodash powered mini database | ||
```js | ||
const db = low('db.json') | ||
db.get('posts') | ||
.push({ id: 1, title: 'lowdb is awesome'}) | ||
.write() | ||
``` | ||
## Usage | ||
```sh | ||
npm install lowdb | ||
``` | ||
```js | ||
const low = require('lowdb') | ||
const FileSync = require('lowdb/adapters/FileSync') | ||
const adapter = new FileSync('db.json') | ||
const db = low(adapter) | ||
// Set some defaults if your JSON file is empty | ||
@@ -17,3 +35,3 @@ db.defaults({ posts: [], user: {} }) | ||
// Set a user | ||
// Set a user using Lodash powerful shorthand syntax | ||
db.set('user.name', 'typicode') | ||
@@ -39,2 +57,3 @@ .write() | ||
```js | ||
// Use .value() instead of .write() if you're only reading from db | ||
db.get('posts') | ||
@@ -47,3 +66,3 @@ .find({ id: 1 }) | ||
It supports __Node__, the __browser__ and uses __lodash API__, so it's very simple to learn. Actually... you may already know how to use lowdb :wink: | ||
It supports __Node__, the __browser__ and uses __lodash API__, so it's very simple to learn. Actually, if you know Lodash, you already know how to use lowdb :wink: | ||
@@ -57,32 +76,9 @@ * [Usage examples](https://github.com/typicode/lowdb/tree/master/examples) | ||
* [JSFiddle live example](https://jsfiddle.net/typicode/4kd7xxbu/) | ||
* [__Migrating from 0.14 to 0.15? See this guide.__](https://github.com/typicode/lowdb/releases/tag/v0.15.0) | ||
## Why lowdb? | ||
__Important__ lowdb doesn't support Cluster and may have issues with very large JSON files (~200MB). | ||
* Lodash API | ||
* Minimal and simple to use | ||
* Highly flexible | ||
* __Custom storage__ (file, browser, in-memory, ...) | ||
* __Custom format__ (JSON, BSON, YAML, XML, ...) | ||
* Mixins (id support, ...) | ||
* Read-only or write-only modes | ||
* Encryption | ||
__Important__ lowdb doesn't support Cluster. | ||
## Used by | ||
* [typicode/json-server](https://github.com/typicode/json-server) - REST API with zero coding | ||
* [henryboldi/felony](https://github.com/henryboldi/felony) - Next Level PGP | ||
* [googlesamples/md2googleslides](https://github.com/googlesamples/md2googleslides) - Generate Google Slides from markdown | ||
* [sqren/fb-sleep-stats](https://github.com/sqren/fb-sleep-stats) - Sleeping habits tracker | ||
* [panzhangwang/getAwesomeness](https://github.com/panzhangwang/getAwesomeness) - All amazing awesomeness from Github | ||
* [redux-promise-middleware](https://github.com/pburtchaell/redux-promise-middleware) - Redux middleware | ||
* [sasha-alias/sqltabs](https://github.com/sasha-alias/sqltabs) - Rich SQL client | ||
* ... and [__600+ repositories__](https://libraries.io/npm/lowdb/dependent-repositories) | ||
## Install | ||
```sh | ||
npm install lowdb --save | ||
npm install lowdb | ||
``` | ||
@@ -101,4 +97,6 @@ | ||
<script src="https://unpkg.com/lowdb/dist/lowdb.min.js"></script> | ||
<script src="https://unpkg.com/lowdb/dist/LocalStorage.min.js"></script> | ||
<script> | ||
var db = low('db') | ||
var adapter = new LocalStorage('db') | ||
var db = low(adapter) | ||
</script> | ||
@@ -109,41 +107,20 @@ ``` | ||
__low([source, [options])__ | ||
__low(adapter)__ | ||
* `source` string or null, will be passed to storage | ||
* `options` object | ||
* `storage` object, by default `lowdb/lib/storages/file-sync` or `lowdb/lib/storages/browser`. | ||
* `read` function | ||
* `write` function | ||
* `format` object | ||
* `serialize` function, by default `JSON.stringify` | ||
* `deserialize` function, by default `JSON.parse` | ||
Returns a lodash [chain](https://lodash.com/docs/4.17.4#chain) with additional properties and functions described below. | ||
Creates a __lodash chain__, you can use __any__ lodash method on it. When `.value()` is called data is saved using `storage`. | ||
__db.[...].write()__ and __db.[...].value()__ | ||
You can use `options` to configure how lowdb should persist data. Here are some examples: | ||
`write()` is syntactic sugar for calling `value()` and `db.write()` in one line. On the other side, `value()` is just [\_.protoype.value()](https://lodash.com/docs/4.17.4#prototype-value), use it to execute a chain. | ||
```js | ||
// in-memory | ||
low() | ||
db.set('user.name', 'typicode') | ||
.write() | ||
// persisted using async file storage | ||
low('db.json', { storage: require('lowdb/lib/storages/file-async') }) | ||
// is equivalent to | ||
db.set('user.name', 'typicode') | ||
.value() | ||
// persisted using a custom storage | ||
low('some-source', { storage: require('./my-custom-storage') }) | ||
// read-only | ||
const fileSync = require('lowdb/lib/storages/file-sync') | ||
low('db.json', { | ||
storage: { | ||
read: fileSync.read | ||
} | ||
}) | ||
// write-only | ||
low('db.json', { | ||
storage: { | ||
write: fileSync.write | ||
} | ||
}) | ||
db.write() | ||
``` | ||
@@ -162,4 +139,5 @@ | ||
const post1 = db.get('posts').first().value() | ||
const post2 = db.get('posts').second().value() | ||
db.get('posts') | ||
.second() | ||
.value() | ||
``` | ||
@@ -169,3 +147,3 @@ | ||
Use whenever you want to access the database state. | ||
Returns database state. | ||
@@ -178,3 +156,3 @@ ```js | ||
Use it to drop database or set a new state (database will be automatically persisted). | ||
Replaces database state. | ||
@@ -186,22 +164,28 @@ ```js | ||
__db.write([source])__ | ||
__db.write()__ | ||
Persists database using `storage.write` option. Depending on the storage, it may return a promise (for example, with `file-async`). | ||
Persists database using `adapter.write` (depending on the adapter, may return a promise). | ||
By default, lowdb automatically calls it when database changes. | ||
```js | ||
// With lowdb/adapters/FileSync | ||
db.write() | ||
console.log('State has been saved') | ||
```js | ||
const db = low('db.json') | ||
db.write() // writes to db.json | ||
db.write('copy.json') // writes to copy.json | ||
// With lowdb/adapters/FileAsync | ||
db.write() | ||
.then(() => console.log('State has been saved')) | ||
``` | ||
__db.read([source])__ | ||
__db.read()__ | ||
Reads source using `storage.read` option. Depending on the storage, it may return a promise. | ||
Reads source using `storage.read` option (depending on the adapter, may return a promise). | ||
```js | ||
const db = low('db.json') | ||
db.read() // reads db.json | ||
db.read('copy.json') // reads copy.json | ||
// With lowdb/FileSync | ||
db.read() | ||
console.log('State has been updated') | ||
// With lowdb/FileAsync | ||
db.write() | ||
.then(() => console.log('State has been updated')) | ||
``` | ||
@@ -217,3 +201,3 @@ | ||
Also, the execution of methods is lazy, that is, execution is deferred until `.value()` is called. | ||
Also, the execution of methods is lazy, that is, execution is deferred until `.value()` or `.write()` is called. | ||
@@ -302,3 +286,2 @@ #### Examples | ||
### How to use id based resources | ||
@@ -308,66 +291,71 @@ | ||
[lodash-id](https://github.com/typicode/lodash-id) provides a set of helpers for creating and manipulating id-based resources. | ||
[shortid](https://github.com/dylang/shortid) is more minimalist and returns a unique id that you can use when creating resources. | ||
```js | ||
const db = low('db.json') | ||
const shortid = require('shortid') | ||
db._.mixin(require('lodash-id')) | ||
const postId = db | ||
.get('posts') | ||
.push({ id: shortid.generate(), title: 'low!' }) | ||
.write() | ||
.id | ||
const postId = db.get('posts').insert({ title: 'low!' }).write().id | ||
const post = db.get('posts').getById(postId).value() | ||
const post = db | ||
.get('posts') | ||
.find({ id: postId }) | ||
.value() | ||
``` | ||
[uuid](https://github.com/broofa/node-uuid) is more minimalist and returns a unique id that you can use when creating resources. | ||
[lodash-id](https://github.com/typicode/lodash-id) provides a set of helpers for creating and manipulating id-based resources. | ||
```js | ||
const uuid = require('uuid') | ||
const lodashId = require('lodash-id') | ||
const db = low('db.json') | ||
const postId = db.get('posts').push({ id: uuid(), title: 'low!' }).write().id | ||
const post = db.get('posts').find({ id: postId }).value() | ||
db._.mixin(lodashId) | ||
const post = db | ||
.get('posts') | ||
.insert({ title: 'low!' }) | ||
.write() | ||
const post = db | ||
.get('posts') | ||
.getById(post.id) | ||
.value() | ||
``` | ||
### How to use a custom storage or format | ||
### How to create custom adapters | ||
`low()` accepts custom storage or format. Simply create objects with `read/write` or `serialize/deserialize` methods. See `src/browser.js` code source for a full example. | ||
`low()` accepts custom Adapter, so you can virtually save your data to any storage using any format. | ||
```js | ||
const myStorage = { | ||
read: (source, deserialize) => // must return an object or a Promise | ||
write: (source, obj, serialize) => // must return undefined or a Promise | ||
} | ||
class MyStorage { | ||
constructor() { | ||
// ... | ||
} | ||
const myFormat = { | ||
serialize: (obj) => // must return data (usually string) | ||
deserialize: (data) => // must return an object | ||
read() { | ||
// Should return data (object or array) or a Promise | ||
} | ||
write(data) { | ||
// Should return nothing or a Promise | ||
} | ||
} | ||
low(source, { | ||
storage: myStorage, | ||
format: myFormat | ||
}) | ||
const adapter = new MyStorage(args) | ||
const db = low() | ||
``` | ||
See [src/adapters](src/adapters) for examples. | ||
### How to encrypt data | ||
Simply `encrypt` and `decrypt` data in `format.serialize` and `format.deserialize` methods. | ||
`FileSync` and `FileAsync` accept custom serializing and deserializing functions. | ||
For example, using [cryptr](https://github.com/MauriceButler/cryptr): | ||
```js | ||
const Cryptr = require("./cryptr"), | ||
const cryptr = new Cryptr('my secret key') | ||
const db = low('db.json', { | ||
format: { | ||
deserialize: (str) => { | ||
const decrypted = cryptr.decrypt(str) | ||
const obj = JSON.parse(decrypted) | ||
return obj | ||
}, | ||
serialize: (obj) => { | ||
const str = JSON.stringify(obj) | ||
const encrypted = cryptr.encrypt(str) | ||
return encrypted | ||
} | ||
} | ||
const adapter = new FileSync('db.json', { | ||
serialize: (data) => encrypt(JSON.stringify(data)) | ||
deserialize: (data) => JSON.parse(decrypt(data)) | ||
}) | ||
@@ -388,2 +376,2 @@ ``` | ||
MIT - [Typicode](https://github.com/typicode) | ||
MIT - [Typicode :cactus:](https://github.com/typicode) |
@@ -7,9 +7,10 @@ var path = require('path') | ||
module.exports = { | ||
entry: './src/main.js', | ||
entry: { | ||
lowdb: './src/main.js', | ||
LocalStorage: './src/adapters/LocalStorage' | ||
}, | ||
output: { | ||
path: path.resolve(__dirname, 'dist'), | ||
filename: process.argv.indexOf('-p') !== -1 | ||
? 'lowdb.min.js' | ||
: 'lowdb.js', | ||
library: 'low' | ||
filename: process.argv.indexOf('-p') !== -1 ? '[name].min.js' : '[name].js', | ||
library: '[name]' | ||
}, | ||
@@ -19,5 +20,3 @@ externals: { | ||
}, | ||
plugins: [ | ||
new webpack.BannerPlugin(banner) | ||
], | ||
plugins: [new webpack.BannerPlugin(banner)], | ||
module: { | ||
@@ -24,0 +23,0 @@ loaders: [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
45501
23
596
5
28
364
1
+ Addedpify@^3.0.0
+ Addedpify@3.0.0(transitive)