"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDefaultOptions = exports.resetDefaultOptions = exports.setDefaultOption = exports.isProtected = exports.flush = exports.unsetValue = exports.isSet = exports.getAllMetadata = exports.getAllValues = exports.setValue = exports.getMetadata = exports.getValue = void 0;
/**
 * Core storage object where data is stored
 */
const datastore = new Map();
/**
 * Default parameters to use for all transactions.
 * It can be overridden by using the {@link setDefaultOption} function and
 * reset to the initial values by using the {@link resetDefaultOptions} function.
 */
const initialDefaultOptions = {
    protected: false,
    force: false,
    onUpdate: undefined,
    onDelete: undefined,
    silent: false,
};
/**
 * Default options for all transactions
 */
let defaultOptions = Object.assign({}, initialDefaultOptions);
/**
 * @private
 * @name getStorageItem
 * @description Returns the storage item for the provided key name
 * @param {string} key - Key name to get the data from
 * @return {StorageItem} - Storage item
 */
function getStorageItem(key) {
    return datastore.get(key);
}
/**
 * @name getValue
 * @description Returns the value for the given key name
 * @param {string} key - Key name to store the data to
 * @param {GetOptions} options - Options for the transaction
 * @return {T} - Stored value
 * @example
 * ```typescript
 * const key = "myKey";
 * const value = "myValue";
 *
 * setValue(key, value);
 *
 * const storedValue = getValue(key); // "myValue"
 * ```
 */
function getValue(key) {
    var _a;
    return (_a = getStorageItem(key)) === null || _a === void 0 ? void 0 : _a.value;
}
exports.getValue = getValue;
/**
 * @name getMetadata
 * @description Returns the full {@link StorageItem} of the provided key name
 * @param {string} key - Key name to get the StorageItem from
 * @return {StorageItem} - Storage item
 * @example
 * ```typescript
 * const key = "myKey";
 * const value = "myValue";
 *
 * setValue(key, value);
 *
 * const metadata = getMetadata(key); // { value: "myValue", createdAt: Date, updatedAt: Date, protected: false, onUpdate: undefined, onDelete: undefined }
 * ```
 */
function getMetadata(key) {
    return getStorageItem(key);
}
exports.getMetadata = getMetadata;
/**
 * @name setValue<T>
 * @description Sets the value for a given key in the global storage.
 * @param {sting} key - Key to set the value for
 * @param {T} value - Value to set
 * @param {SetOptions} options - Optional settings for the operation
 * @return {T} Value that was set
 * @example
 * ```typescript
 * const key = "myKey";
 * const value = "myValue";
 *
 * setValue(key, value);
 *
 * const storedValue = getValue(key); // "myValue"
 * ```
 */
function setValue(key, value, options) {
    var _a, _b, _c, _d, _e;
    const item = getStorageItem(key) || {};
    const force = (_a = options === null || options === void 0 ? void 0 : options.force) !== null && _a !== void 0 ? _a : defaultOptions.force;
    const silent = (_b = options === null || options === void 0 ? void 0 : options.silent) !== null && _b !== void 0 ? _b : defaultOptions.silent;
    if (item.protected && !force) {
        return item.value;
    }
    if (item.onUpdate && !silent) {
        item.onUpdate(key, value, item.value);
    }
    item.value = value;
    item.protected = (_c = options === null || options === void 0 ? void 0 : options.protected) !== null && _c !== void 0 ? _c : defaultOptions.protected;
    item.onUpdate || (item.onUpdate = (_d = options === null || options === void 0 ? void 0 : options.onUpdate) !== null && _d !== void 0 ? _d : defaultOptions.onUpdate);
    item.onDelete || (item.onDelete = (_e = options === null || options === void 0 ? void 0 : options.onDelete) !== null && _e !== void 0 ? _e : defaultOptions.onDelete);
    const now = new Date();
    item.createdAt || (item.createdAt = now);
    item.updatedAt = now;
    datastore.set(key, item);
    return value;
}
exports.setValue = setValue;
/**
 * @name getAllValues
 * @description Returns all stored values
 * @return {Record<string, unknown>} - All stored values
 * @example
 * ```typescript
 * const key1 = "key1";
 * const key2 = "key2";
 * const value1 = "value1";
 * const value2 = "value2";
 *
 * setValue(key1, value1);
 * setValue(key2, value2);
 *
 * const allValues = getAllValues(); // { key1: "value1", key2: "value2" }
 * ```
 */
function getAllValues() {
    return Array.from(datastore).reduce((memo, [key, storageItem]) => (Object.assign(Object.assign({}, memo), { [key]: storageItem.value })), {});
}
exports.getAllValues = getAllValues;
/**
 * @name getAllMetadata
 * @description Returns all stored metadata
 * @return {Record<string, StorageItem>} - All stored metadata
 * @example
 * ```typescript
 * const key1 = "key1";
 * const key2 = "key2";
 * const value1 = "value1";
 * const value2 = "value2";
 *
 * setValue(key1, value1);
 * setValue(key2, value2);
 *
 * const allMetadata = getAllMetadata(); // { key1: { value: "value1", createdAt: Date, updatedAt: Date, protected: false, onUpdate: undefined, onDelete: undefined }, key2: { value: "value2", createdAt: Date, updatedAt: Date, protected: false, onUpdate: undefined, onDelete: undefined } }
 * ```
 */
function getAllMetadata() {
    return Array.from(datastore).reduce((memo, [key, storageItem]) => (Object.assign(Object.assign({}, memo), { [key]: storageItem })), {});
}
exports.getAllMetadata = getAllMetadata;
/**
 * @name isSet
 * @description Checks if a key has been set
 * @param {string} key - Key to check
 * @return {boolean} - Whether the key has been set
 * @example
 * ```typescript
 * const key1 = "myKey1";
 * const key2 = "myKey2";
 * const value1 = "myValue1";
 *
 * setValue(key1, value1);
 *
 * const isKey1Set = isSet(key1); // true
 * const isKey2Set = isSet(key2); // false
 * ```
 */
function isSet(key) {
    return datastore.has(key);
}
exports.isSet = isSet;
/**
 * @name unsetValue
 * @description Removes the value for a given key in the global storage.
 * It triggers the `onDelete` callback if it exists unless the `silent` option is set to `true`.
 * @param {sting} key - Key to set the value for
 * @param {T} value - Value to set
 * @param {SetOptions} options - Optional settings for the operation
 * @return {T} Value that was set
 * @example
 * ```typescript
 * const key = "myKey";
 * const value = "myValue";
 *
 * setValue(key, value);
 *
 * const storedValue = getValue(key); // "myValue"
 *
 * unsetValue(key);
 *
 * const storedValue = getValue(key); // undefined
 * ```
 */
function unsetValue(key, options) {
    var _a;
    const item = getStorageItem(key);
    if (!item) {
        return;
    }
    const silent = (_a = options === null || options === void 0 ? void 0 : options.silent) !== null && _a !== void 0 ? _a : defaultOptions.silent;
    if (!silent && item.onDelete) {
        item.onDelete(key, item.value);
    }
    datastore.delete(key);
}
exports.unsetValue = unsetValue;
/**
 * @name flush
 * @description Unsets all stored values
 * @param {FlushOptions} options - Optional settings for the operation
 * @return {void}
 * @example
 * ```typescript
 * const key1 = "key1";
 * const key2 = "key2";
 * const value1 = "value1";
 * const value2 = "value2";
 *
 * setValue(key1, value1);
 * setValue(key2, value2);
 *
 * const allValuesBefore = getAllValues(); // { key1: "value1", key2: "value2" }
 *
 * flush();
 *
 * const allValuesAfter = getAllValues(); // {}
 * ```
 */
function flush(options) {
    for (const key of datastore.keys()) {
        unsetValue(key, options);
    }
}
exports.flush = flush;
/**
 * @name isProtected
 * @description Checks if a key is protected
 * @param {string} key - Key to check
 * @return {boolean} - Whether the key is protected
 * @example
 * ```typescript
 * const key1 = "myKey1";
 * const value1 = "myValue2";
 * const protected1 = true;
 *
 * setValue(key1, value1, { protected: protected1 });
 * const isKey1Protected = isProtected(key1); // true
 *
 * const key2 = "myKey2";
 * const value2 = "myValue2";
 * const protected2 = false;
 *
 * setValue(key2, value2, { protected: protected2 });
 *
 * const isKey2Protected = isProtected(key2); // false
 * ```
 */
function isProtected(key) {
    var _a;
    return Boolean((_a = getStorageItem(key)) === null || _a === void 0 ? void 0 : _a.protected);
}
exports.isProtected = isProtected;
/**
 * @name setDefaultOption
 * @description Sets the default option for all transactions
 * @param {keyof DefaultOptions} key - Option to set
 * @param {DefaultOptions[keyof DefaultOptions]} value - Value to set
 * @return {void}
 * @example
 * ```typescript
 * setDefaultOption("protected", true);
 *
 * const key = "myKey";
 * const value = "myValue";
 *
 * setValue(key, value);
 *
 * const isKeyProtected = isProtected(key); // true
 * ```
 */
function setDefaultOption(key, value) {
    defaultOptions[key] = value;
}
exports.setDefaultOption = setDefaultOption;
/**
 * @private
 * @name resetDefaultOptions
 * @description Resets the default options to the initial default values
 * @return {void}
 * @example
 * ```typescript
 * setDefaultOption("protected", true);
 *
 * const key1 = "myKey1";
 * const value1 = "myValue1";
 *
 * setValue(key1, value1);
 *
 * const isKey1Protected = isProtected(key1); // true
 *
 * resetDefaultOptions();
 *
 * const key2 = "myKey2";
 * const value2 = "myValue2";
 *
 * setValue(key2, value2);
 *
 * const isKey2Protected = isProtected(key2); // false
 * ```
 */
function resetDefaultOptions() {
    defaultOptions = Object.assign({}, initialDefaultOptions);
}
exports.resetDefaultOptions = resetDefaultOptions;
/**
 * @name getDefaultOptions
 * @description Returns the default options
 * @return {DefaultOptions} - Default options
 * @example
 * ```typescript
 * const defaultOptions = getDefaultOptions(); // { protected: false, force: false, onUpdate: undefined, onDelete: undefined, silent: false }
 * ```
 */
function getDefaultOptions() {
    return Object.assign({}, defaultOptions);
}
exports.getDefaultOptions = getDefaultOptions;
