Skip to content

Commit

Permalink
Code & badges cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
nmaggioni committed Jan 17, 2020
1 parent ccb5962 commit abb73ff
Show file tree
Hide file tree
Showing 7 changed files with 1,166 additions and 375 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Simple JSONdb [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2125ce52d42e40b8971c2329c8a84d99)](https://www.codacy.com/app/nmaggioni/Simple-JSONdb?utm_source=github.com&utm_medium=referral&utm_content=nmaggioni/Simple-JSONdb&utm_campaign=Badge_Grade) [![dependencies Status](https://david-dm.org/nmaggioni/simple-jsondb/status.svg)](https://david-dm.org/nmaggioni/simple-jsondb) [![devDependencies Status](https://david-dm.org/nmaggioni/simple-jsondb/dev-status.svg)](https://david-dm.org/nmaggioni/simple-jsondb?type=dev)
A simple, no-frills, JSON storage engine for Node.JS with **100% test coverage**.
# Simple JSONdb [![npm](https://img.shields.io/npm/v/simple-json-db)](https://www.npmjs.com/package/simple-json-db) [![npm](https://img.shields.io/npm/dw/simple-json-db)](https://www.npmjs.com/package/simple-json-db) [![Minimum NodeJS version](https://img.shields.io/node/v/simple-json-db)](https://www.npmjs.com/package/simple-json-db) [![Dependents (via libraries.io)](https://img.shields.io/librariesio/dependents/npm/simple-json-db)](https://libraries.io/npm/simple-json-db/dependents) [![Snyk Vulnerabilities for npm package](https://img.shields.io/snyk/vulnerabilities/npm/simple-json-db)](https://snyk.io/vuln/search?q=simple-json-db&type=npm)

[![NPM](https://nodei.co/npm/simple-json-db.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/simple-json-db/)
[![NPM](https://nodei.co/npm-dl/simple-json-db.png?height=2)](https://nodei.co/npm/simple-json-db/)
A simple, no-frills, JSON storage engine for Node.JS with full test coverage.

## Installation

Expand Down
178 changes: 0 additions & 178 deletions dist/jsondb.js

This file was deleted.

180 changes: 174 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,177 @@
var semver = require('semver');
var nodeVersion = semver.clean(process.version);
const fs = require("fs");

if (semver.satisfies(nodeVersion, '>=6.0')) {
module.exports = require('./jsondb.js'); // ES6
} else {
module.exports = require('./dist/jsondb.js'); // ES5 (Babel transpiled)
/**
* Default configuration values.
* @type {{asyncWrite: boolean, syncOnWrite: boolean}}
*/
const defaultOptions = {
asyncWrite: false,
syncOnWrite: true
};

/**
* Validates the contents of a JSON file.
* @param {string} fileContent
* @returns {boolean} `true` if content is ok, throws error if not.
*/
let validateJSON = function(fileContent) {
try {
JSON.parse(fileContent);
} catch (e) {
throw new Error('Given filePath is not empty and its content is not valid JSON.');
}
return true;
};

/**
* Main constructor, manages existing storage file and parses options against default ones.
* @param {string} filePath The path of the file to use as storage.
* @param {object} [options] Configuration options.
* @param {boolean} [options.asyncWrite] Enables the storage to be asynchronously written to disk. Disabled by default (synchronous behaviour).
* @param {boolean} [options.syncOnWrite] Makes the storage be written to disk after every modification. Enabled by default.
* @constructor
*/
function JSONdb(filePath, options) {
// Mandatory arguments check
if (!filePath || !filePath.length) {
throw new Error('Missing file path argument.');
} else {
this.filePath = filePath;
}

// Options parsing
if (options) {
for (let key in defaultOptions) {
if (!options.hasOwnProperty(key)) options[key] = defaultOptions[key];
}
this.options = options;
} else {
this.options = defaultOptions;
}


// Storage initialization
this.storage = {};

// File existence check
let stats;
try {
stats = fs.statSync(filePath);
} catch (err) {
if (err.code === 'ENOENT') {
/* File doesn't exist */
return;
} else if (err.code === 'EACCES') {
throw new Error(`Cannot access path "${filePath}".`);
} else {
// Other error
throw new Error(`Error while checking for existence of path "${filePath}": ${err}`);
}
}
/* File exists */
try {
fs.accessSync(filePath, fs.constants.R_OK | fs.constants.W_OK);
} catch (err) {
throw new Error(`Cannot read & write on path "${filePath}". Check permissions!`);
}
if (stats.size > 0) {
let data;
try {
data = fs.readFileSync(filePath);
} catch (err) {
throw err; // TODO: Do something meaningful
}
if (validateJSON(data)) this.storage = JSON.parse(data);
}
}

/**
* Creates or modifies a key in the database.
* @param {string} key The key to create or alter.
* @param {object} value Whatever to store in the key. You name it, just keep it JSON-friendly.
*/
JSONdb.prototype.set = function(key, value) {
this.storage[key] = value;
if (this.options && this.options.syncOnWrite) this.sync();
};

/**
* Extracts the value of a key from the database.
* @param {string} key The key to search for.
* @returns {object|undefined} The value of the key or `undefined` if it doesn't exist.
*/
JSONdb.prototype.get = function(key) {
return this.storage.hasOwnProperty(key) ? this.storage[key] : undefined;
};

/**
* Checks if a key is contained in the database.
* @param {string} key The key to search for.
* @returns {boolean} `True` if it exists, `false` if not.
*/
JSONdb.prototype.has = function(key) {
return this.storage.hasOwnProperty(key);
};

/**
* Deletes a key from the database.
* @param {string} key The key to delete.
* @returns {boolean|undefined} `true` if the deletion succeeded, `false` if there was an error, or `undefined` if the key wasn't found.
*/
JSONdb.prototype.delete = function(key) {
let retVal = this.storage.hasOwnProperty(key) ? delete this.storage[key] : undefined;
if (this.options && this.options.syncOnWrite) this.sync();
return retVal;
};

/**
* Deletes all keys from the database.
* @returns {object} The JSONdb instance itself.
*/
JSONdb.prototype.deleteAll = function() {
for (var key in this.storage) {
//noinspection JSUnfilteredForInLoop
this.delete(key);
}
return this;
};

/**
* Writes the local storage object to disk.
*/
JSONdb.prototype.sync = function() {
if (this.options && this.options.asyncWrite) {
fs.writeFile(this.filePath, JSON.stringify(this.storage, null, 4), (err) => {
if (err) throw err;
});
} else {
try {
fs.writeFileSync(this.filePath, JSON.stringify(this.storage, null, 4));
} catch (err) {
if (err.code === 'EACCES') {
throw new Error(`Cannot access path "${this.filePath}".`);
} else {
throw new Error(`Error while writing to path "${this.filePath}": ${err}`);
}
}
}
};

/**
* If no parameter is given, returns **a copy** of the local storage. If an object is given, it is used to replace the local storage.
* @param {object} storage A JSON object to overwrite the local storage with.
* @returns {object} Clone of the internal JSON storage. `Error` if a parameter was given and it was not a valid JSON object.
*/
JSONdb.prototype.JSON = function(storage) {
if (storage) {
try {
JSON.parse(JSON.stringify(storage));
this.storage = storage;
} catch (err) {
throw new Error('Given parameter is not a valid JSON object.');
}
}
return JSON.parse(JSON.stringify(this.storage));
};

module.exports = JSONdb;
Loading

0 comments on commit abb73ff

Please sign in to comment.