chain-storage
TypeScript icon, indicating that this package has built-in type declarations

1.0.8 • Public • Published

ChainStorage

Example

import ChainStorage, {
    AssignRejecter
} from 'chain-storage';

function log(label, config) {
    const entries = `color: ${config.get("color")}; font-size: ${config.get("fontSize")}; font-weight: ${config.get("fontWeight")}`
    console.log(`%c${label} ==>`, entries, entries);
}

// Create a storage
var globalConfig = new ChainStorage({
    color: "#2b85e4",
    fontSize: 12,
    fontWeight: 500
});

// Monitor storage value changes Monitor storage value changes and print logs;
globalConfig.watch(function (key, value, oldValue) {
    console.log(`globalConfig.${key} has changed:`, oldValue, "==>", value);
})

// Register property assignment hijacking function, 
// if it does not conform to the specification, 
// return AssignRejecter to refuse assignment,
// otherwise return the new value
globalConfig.registerHandler("fontSize", function (value) {
    value = parseInt(value);
    if (Number.isNaN(value) || value < 8) return AssignRejecter;
    return value;
});

// Create a branch storage
var branchConfig = globalConfig.branch({
    fontSize: "14.5"
});

branchConfig.watch(function (key, value, oldValue) {
    console.log(`branchConfig.${key} has changed:`, oldValue, "==>", value);
})

// Create a leaf storage
var leafConfig = branchConfig.branch();
leafConfig.set({
    fontSize: "Invalid value",
    fontWeight: 700
});

console.log("\n\n\n==================  First round  ===================");
log("globalConfig", globalConfig);
log("branchConfig", branchConfig);
log("  leafConfig", leafConfig);
console.log("====================================================\n\n\n");

globalConfig.set({
    color: "#515a6e",
    fontSize: 10
});

leafConfig.set({
    color: "#ff9900"
});

console.log("\n\n\n================== Second round  ===================");
log("globalConfig", globalConfig);
log("branchConfig", branchConfig);
log("  leafConfig", leafConfig);
console.log("====================================================\n\n\n");

globalConfig.set("color", "#2db7f5");
branchConfig.set("color", "#ed4014")

console.log("\n\n\n==================  Third round  ===================");
log("globalConfig", globalConfig);
log("branchConfig", branchConfig);
log("  leafConfig", leafConfig);
console.log("====================================================\n\n\n");

Declare

declare const AssignRejecter: Readonly<{
    "@@Assign.rejecter": boolean;
}>;
declare class ChainStorage<S extends object = any, K extends keyof S = keyof S> {
    /**
     * @description Create an empty storage
     * @constructor
     */
    constructor();
    /**
     * @description Create a storage, use [[source]] as the value, and the prototype-chain is null
     * @constructor
     * @param { object } source
     */
    constructor(source: S);
    /**
     * @description Create a storage, use [[source]] as the value, use [[proto]] as the prototype-chain
     * @constructor
     * @param { object } source
     * @param { object | null } proto
     */
    constructor(source: S | undefined, proto: S | null);
    /**
     * @description Create a branch storage, the branch uses the current storage as the prototype-chain,
     * @description the modification on the branch will not affect the upper-level warehouse,
     * @description but the modification of the upper-level warehouse will affect the prototype-chain of its branch storage
     *
     * @description Create an empty branch storage
     * @returns { ChainStorage }
     */
    branch<T extends object = any>(): ChainStorage<S & T>;
    /**
     * @description Create an empty branch storage, use [[source]] as the value
     * @param { object } source
     * @returns { ChainStorage }
     */
    branch<T extends object = any>(source?: T): ChainStorage<S & T>;
    /**
     * @description Determine whether the storage has this property, it will go deep into the prototype-chain, similar to the "in" operator
     * @param { PropertyKey } key
     * @returns { boolean }
     */
    has(key: K): boolean;
    /**
     * @description Get storage object property [[key]]
     * @param { PropertyKey } key
     * @returns { any }
     */
    get(key: K): S[K] | undefined;
    /**
     * @description Use object to merge storage object,
     * @description will not merge deeply, just simply overwriting properties
     * @param { object } entries
     * @returns { this }
     */
    set(entries: Partial<S>): this;
    /**
     * @description Set a single property value
     * @param { PropertyKey } key
     * @param { any } value
     * @returns { this }
     */
    set(key: K, value: S[K]): this;
    /**
     * @description Delete a single property value
     * @param { PropertyKey } key
     * @returns { this }
     */
    delete(key: K): this;
    /**
     * @description Returns whether the storage is frozen
     * @returns { boolean }
     */
    isFrozen(): boolean;
    /**
     * @description Returns whether the storage is destroyed
     * @returns { boolean }
     */
    isDestroyed(): boolean;
    /**
     * @description To freeze the storage, you can provide a [[lock]] for unlocking.
     * @description If you don’t provide a [[lock]], this storage will not be unlocked.
     * @description Return true if the freeze is successful, false if the freeze fails (for example, it is already frozen by another lock)
     *
     * @description If you don't want your storage to be unlocked by others, please avoid using string / number / boolean / null.
     * @description If you use NaN as a [[lock]], this repository will never be unlocked, including yourself, because NaN !== NaN
     * @param { object? } lock
     * @returns { boolean }
     */
    freeze(lock?: any): boolean;
    /**
     * @description To unfreeze the storage, use the [[lock]] provided when locking to unlock
     * @description Return true if the unfreeze is successful, false if the unfreeze fails
     * @param { object? } lock
     * @returns { boolean }
     */
    unfreeze(lock: any): boolean;
    /**
     * @description Destroy the storage, the storage will be frozen but still readable,
     * @description all data monitoring on the warehouse will be cleared, and no new monitoring will be accepted
     * @returns { this }
     */
    destroy(): this;
    /**
     * @description Monitor changes in storage object properties
     * @param { PropertyKey } prop
     * @param { Function } watcher
     * @returns { this }
     */
    watch(prop: K, watcher: PropertyWatcher<S, K>): this;
    /**
     * @description Monitor changes in storage objects
     * @param { PropertyKey } prop
     * @param { Function } watcher
     * @returns { this }
     */
    watch(watcher: Watcher<S, K>): this;
    /**
     * @description Clear all monitors
     * @returns { this }
     */
    unwatch(): this;
    /**
     * @description Remove storage object monitoring
     * @param { Function } watcher
     * @returns { this }
     */
    unwatch(watcher: Watcher<S, K>): this;
    /**
     * @description Remove storage object properties monitoring
     * @param { Function } watcher
     * @returns { this }
     */
    unwatch(prop: K | Watcher<S, K>, watcher: PropertyWatcher<S, K>): this;
    /**
     * @description Register property assignment hijacking function to normalize attributes
     * @description After registration, if the property exists, it will be executed immediately
     * @param { PropertyKey } key
     * @param { Function } handler
     * @returns { this }
     */
    registerHandler(key: K, handler: PropertyHandler): this;
}
declare type AssignRejecter = object;
interface Watcher<S extends object = any, K extends keyof S = keyof S> {
    /**
     * @description Monitor object changes
     * @param { PropertyKey } key - Modified property
     * @param { any } value - New value
     * @param { any } oldValue - Old value
     */
    (key: K, value: S[K] | undefined, oldValue: S[K] | undefined): void;
}
interface PropertyWatcher<S extends object = any, K extends keyof S = keyof S> {
    /**
     * @description Monitor property changes
     * @param { any } value - New value
     * @param { any } oldValue - Old value
     */
    (value: S[K] | undefined, oldValue: S[K] | undefined): void;
}
interface PropertyHandler<S extends object = any, K extends keyof S = keyof S> {
    /**
     * @description Monitor property changes
     * @param { any } value - New value
     * @param { any } oldValue - Old value
     */
    (value: S[K], key: K): S[K] | AssignRejecter;
}
export default ChainStorage;
export { AssignRejecter };

Readme

Keywords

none

Package Sidebar

Install

npm i chain-storage

Weekly Downloads

0

Version

1.0.8

License

none

Unpacked Size

38.3 kB

Total Files

7

Last publish

Collaborators

  • galadrielme