UNPKG

@heliomarpm/kvs

Version:

A simple and robust KeyValues Storage's library

337 lines (336 loc) 10 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.KeyValues = void 0; const lodash_1 = require("lodash"); const utils_1 = require("./utils"); /** @internal */ const defaultOptions = { atomicSave: true, dir: utils_1.DEFAULT_DIR_NAME, fileName: utils_1.DEFAULT_FILE_NAME, prettify: false, numSpaces: 2, }; /** * * KeyValues is a class that provides a simple key-value storage system. * It allows you to set, get, check existence, and remove key-value pairs in a JSON file. * It supports nested keys and complex data types, and provides both asynchronous and synchronous methods * * It is designed to be used in Node.js applications * and can be easily configured to use a custom directory * and file name for storing key-value pairs. * * @author Heliomar Marques * @example * * import { KeyValues } from '@heliomarpm/kvs'; * * // Create a new instance of KeyValues with custom options * const keyValues = new KeyValues({ * fileName: 'config.json', * prettify: true, * numSpaces: 4 * }); * * // Set a key-value pair * await keyValues.set('color.name', 'sapphire'); * * // Get the value at a specific key path * const value = await keyValues.get('color.name'); * // output: 'sapphire' * * // Get the nested key * const value = await keyValues.get('color'); * // output: { name: 'sapphire' } * * // Get all * const value = await keyValues.get(); * // output: { color: { name: 'sapphire' } } * * // Check if a key path exists * const exists = await keyValues.has('color.name'); * * // Remove a key-value pair * await keyValues.unset('color.name'); * * @category Core */ class KeyValues { /** * Sets the configuration for KeyValues Storage's. * * To reset to defaults, use [`reset()`]. * * ```js * Defaults: * { * atomicSave: true, * dir: 'localdb', * fileName: 'keyvalues.json', * numSpaces: 2, * prettify: false * } * ``` * @param options {@link Options} The custom configuration to use. * @example * * Update the filename to `config.json` and prettify the output. * ```js * new KeyValues({ fileName: 'config.json', prettify: true }); * ``` */ constructor(options) { /** * @internal */ Object.defineProperty(this, "options", { enumerable: true, configurable: true, writable: true, value: Object.assign({}, defaultOptions) }); /** * @internal */ Object.defineProperty(this, "jsonHelper", { enumerable: true, configurable: true, writable: true, value: void 0 }); if (options) this.options = Object.assign(Object.assign({}, this.options), options); this.jsonHelper = new utils_1.JsonFileHelper(this.options); } /** * Returns the path to the json file. * * In general, the json file is stored * in then install location of your app's * user data directory in a file called `keyvalues.json`. * The default user data directory varies by system. * * - **macOS** - `~/Library/Application\ Support/<Your App>` * - **Windows** - `%LOCALAPPDATA%/PROGRAMS/<Your App>` * - **Linux** - Either `$XDG_CONFIG_HOME/<Your App>` or `~/.config/<Your App>` * * Although it is not recommended, you may change the name * or location of the keyvalues file using * * new KeyValye({dir: 'newpath'}) * * @returns The path to the keyvalues file. * * @example * * Get the path to the keyvalues file. * ```js * keyValues.file(); * // => c:/users/<userprofile>/appdata/local/programs/<AppName>/keyvalues.json * ``` * * @category Auxiliary Methods */ file() { return this.jsonHelper.getJsonFilePath(); } /** * Resets the KeyValues Storage's configuration to defaults. * * @example * * Reset configuration to defaults. * ```js * keyValues.resetOptions(); * ``` * * @category Auxiliary Methods * @see {@link Options} */ resetOptions() { this.options = Object.assign({}, defaultOptions); } set(...args) { return __awaiter(this, void 0, void 0, function* () { if (args.length === 1) { const [value] = args; return this.jsonHelper.saveKeyValues(value); } const [keyPath, value] = args; const obj = yield this.jsonHelper.loadKeyValues(); (0, lodash_1.set)(obj, keyPath, value); return this.jsonHelper.saveKeyValues(obj); }); } setSync(...args) { if (args.length === 1) { const [value] = args; this.jsonHelper.saveKeyValuesSync(value); } else { const [keyPath, value] = args; const obj = this.jsonHelper.loadKeyValuesSync(); (0, lodash_1.set)(obj, keyPath, value); this.jsonHelper.saveKeyValuesSync(obj); } } get(keyPath) { return __awaiter(this, void 0, void 0, function* () { try { const obj = yield this.jsonHelper.loadKeyValues(); if (keyPath) { return (0, lodash_1.get)(obj, keyPath); } return obj; } catch (error) { // Add proper error handling if (error instanceof Error) { throw new Error(`Failed to get value: ${error.message}`); } throw new Error("Failed to get value: Unknown error"); } }); } getSync(keyPath) { const obj = this.jsonHelper.loadKeyValuesSync(); if (keyPath) { return (0, lodash_1.get)(obj, keyPath); } return obj; } /** * Checks if the given key path exists. * * _For sync method, use_ [`hasSync()`]. * * @param keyPath The key path to check. * @returns A promise which resolves to `true` if the `keyPath` exists, else `false`. * @example * * Check if the value at `color.name` exists. * ```js * // Given: * { * "color": { * "name": "cerulean", * "code": { * "rgb": [0, 179, 230], * "hex": "#003BE6" * } * } * } * * const exists = await keyValues.has('color.name'); * // => true * ``` * @example * * Check if the value at `color.hue` exists. * ```js * const exists = await keyValues.has(['color', 'hue']); * // => false * ``` * @example * * Check if the value at `color.code.rgb[1]` exists. * ```js * const exists = await keyValues.has(color.code.rgb[1]); * // => true * ``` * * @category Has Methods */ has(keyPath) { return __awaiter(this, void 0, void 0, function* () { const obj = yield this.jsonHelper.loadKeyValues(); return (0, lodash_1.has)(obj, keyPath); }); } /** * Checks if the given key path exists. * * _For async method, use_ [`has()`]. * * @param keyPath The key path to check. * @returns `true` if the `keyPath` exists, else `false`. * @example * * Check if the value at `color.name` exists. * ```js * // Given: * { * "color": { * "name": "cerulean", * "code": { * "rgb": [0, 179, 230], * "hex": "#003BE6" * } * } * } * * const exists = keyValues.hasSync('color.name'); * // => true * ``` * @example * * Check if the value at `color.hue` exists. * ```js * const exists = keyValues.hasSync(['color', 'hue']); * // => false * ``` * @example * * Check if the value at `color.code.rgb[1]` exists. * ```js * const exists = keyValues.hasSync(color.code.rgb[1]); * // => true * ``` * * @category Has Methods */ hasSync(keyPath) { const obj = this.jsonHelper.loadKeyValuesSync(); return (0, lodash_1.has)(obj, keyPath); } unset(keyPath) { return __awaiter(this, void 0, void 0, function* () { const obj = yield this.jsonHelper.loadKeyValues(); if (JSON.stringify(obj) !== "{}") { if (keyPath && (0, lodash_1.unset)(obj, keyPath)) { yield this.jsonHelper.saveKeyValues(obj); } else { yield this.jsonHelper.saveKeyValues({}); } return true; } return false; }); } unsetSync(keyPath) { const obj = this.jsonHelper.loadKeyValuesSync(); if (JSON.stringify(obj) !== "{}") { if (keyPath && (0, lodash_1.unset)(obj, keyPath)) { this.jsonHelper.saveKeyValuesSync(obj); } else { // Unset all keyValues by saving empty object. this.jsonHelper.saveKeyValuesSync({}); } return true; } return false; } } exports.KeyValues = KeyValues;