From e518eda43c24ef5e651c78b07df8c64b88aa9e02 Mon Sep 17 00:00:00 2001 From: eli_oat Date: Sun, 23 Jan 2022 19:25:49 -0500 Subject: [PATCH] * --- .gitignore | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 3 + UNLICENSE | 24 ++++++ ldb.js | 151 +++++++++++++++++++++++++++++++++++ 4 files changed, 403 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 UNLICENSE create mode 100644 ldb.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e3e98e9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,225 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/emacs,macos,node +# Edit at https://www.toptal.com/developers/gitignore?templates=emacs,macos,node + +### Emacs ### +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# network security +/network-security.data + + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### Node Patch ### +# Serverless Webpack directories +.webpack/ + +# Optional stylelint cache + +# SvelteKit build / generate output +.svelte-kit + +# End of https://www.toptal.com/developers/gitignore/api/emacs,macos,node \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..28504e0 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# ldb.js + +This is an itsy-bitsy database for the browser. Useful for trivial web apps and other toy projects. \ No newline at end of file diff --git a/UNLICENSE b/UNLICENSE new file mode 100644 index 0000000..00d2e13 --- /dev/null +++ b/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +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 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. + +For more information, please refer to \ No newline at end of file diff --git a/ldb.js b/ldb.js new file mode 100644 index 0000000..5822837 --- /dev/null +++ b/ldb.js @@ -0,0 +1,151 @@ +/* ============================= +================================ + + /$$ /$$ /$$ + | $$ | $$| $$ + | $$ /$$$$$$$| $$$$$$$ + | $$ /$$__ $$| $$__ $$ + | $$| $$ | $$| $$ \ $$ + | $$| $$ | $$| $$ | $$ + | $$| $$$$$$$| $$$$$$$/ + |__/ \_______/|_______/ + + 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(); + } + +}; \ No newline at end of file -- 2.45.2