UNPKG

node-json-db

Version:

Database using JSON file as storage for Node.JS

136 lines 5.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConfigWithAdapter = exports.Config = void 0; const path = require("path"); const JsonAdapter_1 = require("../adapter/data/JsonAdapter"); const Serializers_1 = require("../adapter/data/Serializers"); const FileAdapter_1 = require("../adapter/file/FileAdapter"); const CipheredFileAdapter_1 = require("../adapter/file/CipheredFileAdapter"); class Config { adapter; _filename; saveOnPush; separator; syncOnSave; humanReadable; _serializers; _cipherKey; get filename() { return this._filename; } constructor(filename, saveOnPush = true, humanReadable = false, separator = '/', syncOnSave = false) { this._filename = filename; // Force json if no extension if (path.extname(filename) === "") { this._filename += ".json"; } this.saveOnPush = saveOnPush; this.separator = separator; this.syncOnSave = syncOnSave; this.humanReadable = humanReadable; this._serializers = [...Serializers_1.defaultSerializers]; this.adapter = new JsonAdapter_1.JsonAdapter(new FileAdapter_1.FileAdapter(this._filename, syncOnSave), humanReadable, this._serializers); } /** * Add a custom serializer for handling additional types during JSON serialization. * * Custom serializers allow you to extend the built-in type support (Date, Set, Map, RegExp, BigInt) * with your own types. Each serializer uses a `__type`/`__value` envelope pattern in the stored JSON. * * @param serializer - The serializer to add. Must implement the {@link ISerializer} interface. * * @example * ```typescript * import { Config, ISerializer } from 'node-json-db'; * * const urlSerializer: ISerializer = { * type: "URL", * serialize: (value: URL) => value.href, * deserialize: (value: string) => new URL(value), * test: (value: any) => value instanceof URL, * }; * * const config = new Config('mydb'); * config.addSerializer(urlSerializer); * ``` */ addSerializer(serializer) { this._serializers = [...this._serializers, serializer]; this._rebuildAdapter(); } /** * Enable encryption for the database using AES-256-GCM. * * When encryption is enabled, the database filename automatically changes to use the `.enc.json` extension. * For example, `mydb.json` becomes `mydb.enc.json`. This prevents accidentally accessing encrypted * databases without proper encryption settings. * * This method is idempotent - calling it multiple times won't keep changing the filename. * * @param cipherKey - The encryption key. Must be exactly 32 bytes. Can be: * - A string of 32 characters * - A Buffer of 32 bytes * - A symmetric KeyObject with 256-bit key size (from Node.js crypto module) * * @throws {Error} If the key is asymmetric (not supported) * @throws {Error} If the key length is not exactly 32 bytes * * @example * ```typescript * import { Config } from 'node-json-db'; * import { randomBytes } from 'crypto'; * * const config = new Config('mydb', true); * const key = randomBytes(32); // 32-byte encryption key * config.setEncryption(key); * // Database will now be stored in 'mydb.enc.json' with encrypted data * ``` */ setEncryption(cipherKey) { if (cipherKey.asymmetricKeyType) throw new Error('Asymmetric key not supported'); let keyLength; if (typeof cipherKey === 'string') { keyLength = Buffer.byteLength(cipherKey); } else if (cipherKey instanceof Buffer) { keyLength = cipherKey.length; } else { keyLength = cipherKey.symmetricKeySize; } if (!keyLength || keyLength !== 32) { throw new Error(`Invalid key length. Expected 32 bytes for aes-256-gcm but got ${keyLength}.`); } // Change file extension to .enc.json (idempotent) if (!this._filename.endsWith('.enc.json')) { const currentExt = path.extname(this._filename); // Remove current extension and add .enc.json const baseName = currentExt ? this._filename.slice(0, -currentExt.length) : this._filename; this._filename = baseName + '.enc.json'; } this._cipherKey = cipherKey; this._rebuildAdapter(); } _rebuildAdapter() { if (this._cipherKey) { this.adapter = new JsonAdapter_1.JsonAdapter(new CipheredFileAdapter_1.CipheredFileAdapter(this._cipherKey, this._filename, this.syncOnSave), this.humanReadable, this._serializers); } else { this.adapter = new JsonAdapter_1.JsonAdapter(new FileAdapter_1.FileAdapter(this._filename, this.syncOnSave), this.humanReadable, this._serializers); } } } exports.Config = Config; class ConfigWithAdapter { adapter; saveOnPush; separator; constructor(adapter, saveOnPush = true, separator = '/') { this.adapter = adapter; this.saveOnPush = saveOnPush; this.separator = separator; } } exports.ConfigWithAdapter = ConfigWithAdapter; //# sourceMappingURL=JsonDBConfig.js.map