UNPKG

makit

Version:

Make in JavaScript done right!

115 lines (114 loc) 3.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DataBase = void 0; const util_1 = require("util"); const logger_1 = require("../utils/logger"); const number_1 = require("../utils/number"); const l = logger_1.Logger.getOrCreate(); /** * 一个简易的 JSON 非关系性数据库。它的构成如下: * * * 一个 DataBase 对象由若干个 Document 构成 * * 一个 Document 由若干个 Property 构成 * * Note: sqlite 是各方面比较理想的替代品,但它有 Native Binding, * 能否成功安装会受网络、操作系统、Node 版本的影响,移植性不够。 */ class DataBase { constructor(filepath, fs) { this.filepath = filepath; this.fs = fs; this.data = {}; this.dirty = false; this.readFromDisk(); } /** * 查询文档属性 * * @param doc 文档名 * @param prop 属性名 * @param defaultValue 如果没有,则返回的默认值 */ query(doc, prop, defaultValue) { if (!this.data[doc]) { return defaultValue; } const value = this.data[doc][prop]; return value !== undefined ? value : defaultValue; } /** * 写入文档属性 * * @param doc 文档名 * @param prop 属性名 * @param newValue 新的属性值 */ write(doc, prop, newValue) { l.debug('DTBS', () => `setting ${doc}.${prop} to ${util_1.inspect(newValue)}`); this.dirty = true; this.data[doc] = this.data[doc] || {}; this.data[doc][prop] = newValue; return this.data[doc][prop]; } /** * 清空文档的所有属性,或清空数据库 * * @param doc 文档名,如果不传则清空所有文档 */ clear(doc) { this.dirty = true; if (doc) this.data[doc] = {}; else this.data = {}; } /** * 同步数据库到磁盘 * * @throws 文件写入错误 */ syncToDisk() { if (!this.dirty) { l.debug('DTBS', `documents clean, skip syncing`); return false; } l.verbose('DTBS', () => `syncing to disk ${this.filepath}`); const data = Buffer.from(JSON.stringify(this.data), 'utf8'); try { // Note: should be synchronous to handle exit event, // after which microtasks will not be scheduled or called. this.fs.writeFileSync(this.filepath, data); } catch (err) { err.message = 'Error sync to disk: ' + err.message; throw err; } l.verbose('DTBS', () => `${number_1.humanReadable(data.length)} bytes written to ${this.filepath}`); this.dirty = false; return true; } readFromDisk() { let str, data; try { str = this.fs.readFileSync(this.filepath, 'utf8'); } catch (err) { if (err.code === 'ENOENT') { // ignore if not exists, will be created on first sync str = '{}'; } else { throw err; } } try { data = JSON.parse(str); } catch (err) { // ignore corrupted file, it will be regenerated anyway } if (typeof data === 'object' && data !== null) this.data = data; } } exports.DataBase = DataBase;