a barebones localfile-backed storage for stubbing out without redis or RDMS
npm install @ashnazg/dumbfile---
title: "@ashnazg/dumbfile"
sidebar_label: dumbfile
---
a barebones localfile-backed storage for stubbing out without redis or RDMS
const jsonLoad = require('@ashnazg/dumbfile').load; // ~/projects/ashnazg-npm/dumbfile/json.jsvar handle = await jsonLoad('./store.json');
console.log(handle.db); // contents of file are now ready on .db
handle.db.property = 'foo'; // mutate .db, it's just a plain old JS object.
await handle.save(); // saved back to disk, in a human-friendly format. Using tabs.
// admin edited config file while app was running?
await handle.reload(); // .db has been wiped and replaced with file's contents again.
`$3
`
var seven_days = 10006060247;var session_db_ready = dumb.load('../tokens.json').then(sys => { // N.B. if you've got src/ watched with something like nodemon, make sure the state file isn't in the watch list.
// create schemas if missing
sys.db = Object.assign({
tokens: {},
}, sys.db);
sys.setSessionExpiration = function(user, lifespan = seven_days) {
var token = genToken(user, lifespan);
var expires_on = Date.now() + lifespan;
this.db.tokens[user] = this.db.tokens[user] || {}; // this could be the first token creation for this user
this.db.tokens[user][token] = expires_on;
this.save(); // firing and forgetting the 'save completed' promise; I don't need confirmation that this hit disk for just sessions.
console.log("new db", this.db);
return token;
};
sys.isValidSession = function(user, token) {
var my_tokens = this.db.tokens[user];
if (!my_tokens) return false;
var expiration_date = my_tokens[token];
if (expiration_date === undefined) return false;
if (expiration_date > Date.now()) return getUid(user);
delete my_tokens[token];
return false;
};
return sys;
}
// caller should provide exactly one of pass or token
async function checkAuth(user, pass, token) {
if (pass) {
var uid = checkPass(user, pass);
if (uid) {
var sys = await session_db_ready;
var token = sys.setSessionExpiration(user);
return {uid, token};
}
} else if (token) {
var sys = await session_db_ready;
uid = sys.isValidSession(user, token);
if (uid) {
return {uid, token};
}
throw {message: 'token expired'};
}
throw {message: 'no acceptable credential provided'};
}
`Not using JSON?
There's a no-format-assumptions underlying layer you can use. It _does_ speak only utf8, as I only use raw Buffers when I have to.
`
var loadFile = require('./utf8.js').createDumbFile;var handle = loadFile('./store.raw');
var data = await handle.load();
await handle.save('new data');
`It also has a synchronous save function:
`
handle.saveSync('new data');
`handling not-yet-existing files
Both of the handle creation functions have two more params: a default value that's returned when the file doesn't exist, and a chmod mode used during save()'s file creation.
`
var handle = loadFile(filename, 'default config lines', 0o660); // default chmod os owner r/w only; 660 says group also has r/w perms.
var handle = jsonLoad(filename, {default: 'setting'}, 0o660);
`Release 1.1.4
Turned off some dbg logging I didn't mean to commit
Release 1.1.3
json file management no longer depends on {this.db}` for anything -- this allows me to pass a _subtree_ to a submodule, along with the save func, and now each submodule can shareSo now, a horde of async save()s results in all but the first save leaving a note for the first save job to handle it, and then waiting for it to finally give the "latest version
has been persisted."