ldb.js

This is an itsy-bitsy database for the browser. Useful for trivial web apps and other toy projects.

/* =============================
================================

     /$$       /$$ /$$
    | $$      | $$| $$
    | $$  /$$$$$$$| $$$$$$$
    | $$ /$$__  $$| $$__  $$
    | $$| $$  | $$| $$  \ $$
    | $$| $$  | $$| $$  | $$
    | $$|  $$$$$$$| $$$$$$$/
    |__/ \_______/|_______/

 An itsy-bitsy database for the
 browser, useful for web apps and
 other sorts of toy projects.

================================
============================== */

'use strict';

const ldb = {

    // Utils
    _uuid: () => {
        return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11)
            .replace(/[018]/g, c =>
                (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
    },
    _makeDocument: (document, dateCreated = null) => {
        const rightNow = new Date();
        let editedDate = null;
        if (dateCreated === null) {
            dateCreated = rightNow.toISOString();
        } else {
            dateCreated = dateCreated;
            editedDate = rightNow.toISOString();
        }
        const newDoc = {
            "created": dateCreated,
            "edited": editedDate,
            "doc": document
        };
        return newDoc;
    },
    _allKeys: () => {
        const data = JSON.parse(localStorage.getItem('ldb'));
        return Object.keys(data);
    },
    _allDocs: () => {
        const dbKeys = ldb._allKeys();
        let ret = [];
        dbKeys.forEach((row) => {
            ret.push((ldb.Get(row).doc));
        });
        return ret;
    },
    _table: (docsOnly = null) => {
        const dump = JSON.parse(localStorage.getItem('ldb'));
        if (docsOnly) {
            console.log('Just the docs.:');
            console.table(ldb._allDocs());
        } else {
            console.log('Number of rows: ' + Object.keys(dump).length);
            console.table(dump);
        }
        return null;
    },
    _destroy: (confirm) => {
        if (confirm === true) {
            localStorage.removeItem('ldb');
        } else {
            console.error('You must confirm this action.');
        }
    },

    // GET
    Get: (idToGet) => {
        let returnData = null;
        if (idToGet) {
            const data = JSON.parse(localStorage.getItem('ldb'));
            returnData = data[idToGet];
            if (returnData === undefined) {
                console.error('Unable to find record with id "' + idToGet + '"');
                returnData = null;
            }
        } else {
            if (localStorage.getItem('ldb') === null) {
                const defaultData = {};
                localStorage.setItem('ldb', JSON.stringify(defaultData));
            }
            returnData = JSON.parse(localStorage.getItem('ldb'));
        }
        return returnData;
    },

    // PUT
    Put: (newDocumentData) => {
        if (typeof newDocumentData === 'object') {
            let pagesData = ldb.Get();
            const uuid = ldb._uuid();
            const row = ldb._makeDocument(newDocumentData);
            Object.assign(pagesData, {
                [uuid]: row
            });
            const preFlight = JSON.stringify(pagesData);
            localStorage.setItem('ldb', preFlight);
        } else {
            console.error('Data must be an object.');
            console.log('Data is ' + typeof newDocumentData);
            console.log(newDocumentData);
        }
    },

    // UPDATE
    Update: (idToModify, newDocumentData = null) => {
        let pagesData = ldb.Get();
        let targetRow = pagesData[idToModify];
        const updatedRow = ldb._makeDocument(newDocumentData, targetRow.created);
        Object.assign(pagesData, {
            [idToModify]: updatedRow
        });
        const preFlight = JSON.stringify(pagesData);
        localStorage.setItem('ldb', preFlight);
    },

    // DELETE
    Delete: (idToRemove) => {
        // TODO: UNTESTED!
        let pagesData = ldb.Get();
        let targetRow = pagesData[idToRemove];
        Object.assign(pagesData, {
            [idToRemove]: null
        }); // FIXME: this will leave an empty ID behind
        const preFlight = JSON.stringify(pagesData);
        localStorage.setItem('ldb', preFlight);
    },

    // EXPORT
    Export: () => {
        const rightNow = new Date();
        const pagesData = JSON.stringify(ldb.Get());
        const dataUri = 'data:application/json;charset=utf-8,' + encodeURIComponent(pagesData);
        const exportFileDefaultName = rightNow.toISOString() + '--ldb_export.json';
        let linkElement = document.createElement('a');
        linkElement.setAttribute('href', dataUri);
        linkElement.setAttribute('download', exportFileDefaultName);
        linkElement.click();
    }

};