hfs
Version:
HTTP File Server
57 lines (56 loc) • 2.97 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.storeFileAttr = storeFileAttr;
exports.loadFileAttr = loadFileAttr;
exports.purgeFileAttr = purgeFileAttr;
const kvstorage_1 = require("@rejetto/kvstorage");
const fs_1 = require("fs");
const util_1 = require("util");
const promises_1 = require("fs/promises");
const cross_1 = require("./cross");
const first_1 = require("./first");
const promises_2 = require("node:fs/promises");
const const_1 = require("./const");
const fsx = (0, cross_1.try_)(() => {
const lib = require('fs-x-attributes');
return { set: (0, util_1.promisify)(lib.set), get: (0, util_1.promisify)(lib.get) };
}, () => console.warn('fs-x-attributes not available'));
const fileAttrDb = new kvstorage_1.KvStorage({ defaultPutDelay: 1000, maxPutDelay: 5000 });
(0, first_1.onProcessExit)(() => fileAttrDb.flush());
const FN = 'file-attr.kv';
if ((0, fs_1.existsSync)(FN))
fileAttrDb.open(FN);
const FILE_ATTR_PREFIX = 'user.hfs.'; // user. prefix to be linux compatible
/* @param v must be JSON-able or undefined */
async function storeFileAttr(path, k, v) {
var _a, _b;
const s = await (0, promises_2.stat)(path).catch(() => null);
// since we don't have fsx.remove, we simulate it with an empty string
if (await (fsx === null || fsx === void 0 ? void 0 : fsx.set(path, FILE_ATTR_PREFIX + k, v === undefined ? '' : JSON.stringify(v)).then(() => 1, () => 0))) {
if (s && const_1.IS_WINDOWS)
(0, promises_2.utimes)(path, s.atime, s.mtime); // restore timestamps, necessary only on Windows
return true;
}
// fallback to our kv-storage
if (!fileAttrDb.isOpen())
if (!s && !v)
return; // file was probably deleted, and we were asked to remove a possible attribute, but there's no fileAttrDb, so we are done, don't create the db file for nothing
else
await fileAttrDb.open(FN);
// pipe should be a safe separator
return (_b = await ((_a = fileAttrDb.put(`${path}|${k}`, v)) === null || _a === void 0 ? void 0 : _a.catch((e) => {
console.error("couldn't store metadata on", path, String(e.message || e));
return false;
}))) !== null && _b !== void 0 ? _b : true; // if put is undefined, the value was already there
}
async function loadFileAttr(path, k) {
var _a;
return (_a = await (fsx === null || fsx === void 0 ? void 0 : fsx.get(path, FILE_ATTR_PREFIX + k).then((x) => x === '' ? undefined : (0, cross_1.tryJson)(String(x)), () => fileAttrDb.isOpen() ? fileAttrDb.get(`${path}|${k}`) : null))) !== null && _a !== void 0 ? _a : undefined; // normalize, as we get null instead of undefined on windows
}
async function purgeFileAttr() {
let n = 0;
await Promise.all(Array.from(fileAttrDb.keys()).map(k => (0, promises_1.access)(k).catch(() => n++ && void fileAttrDb.del(k))));
if (n)
await fileAttrDb.rewrite();
console.log(`removed ${n} entrie(s)`);
}
;