npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@peter.naydenov/data-pool

v2.1.1

Published

Data-pool is a data-layer for node apps and single page application

Downloads

6

Readme

Data-pool (@peter.naydenov/data-pool)

version license GitHub issues npm bundle size

Data-pool is a data-layer for node apps and single page application (SPA). Data-pool will simplify data maintanance with:

  • Multiple data stores;
  • Stores with immutable data;
  • Signal stores with computed properties and effects;
  • API based stores;
  • Caching data records from Api requests;
  • Optional TTL for each data record;
  • Optional update schedule for each data record;
  • A mechanism to fake Api request response;

Instalation

Install for node.js projects by writing in your terminal:

npm i @peter.naydenov/data-pool

Once it has been installed, it can be used by writing this line of JavaScript:

import dataPool from '@peter.naydenov/data-pool'

How to use it

Create a data-pool instance:

const pool = dataPool ();

Now you are free to add and manipulate stores and data. For more details read the 'Methods' section

Methods

  set            : 'Create new record'
, setComputed    : 'Create a computed property. Works only in signal stores'
, setEffect      : 'Create an signal effect'
, setSignalStore : 'Define one or more store names as signal stores'
, get            : 'Returns existing data, or requesting it from related API'
, addApi         : 'Associate one or more APIs with data-pool'
, removeApi      : 'Remove associated API or APIs'
, list           : 'List stores with data'
, has            : 'Checks if store or store-key exist. Returns a boolean: true/false'
, importStore    : 'Add data as a store' 
, exportStore    : 'Export store as a data'
, on             : 'Watch for store changes. Events' 
, setDummy       : 'Define dummy source-data for store-key. Expect dummy as a function'
, removeDummy    : 'Remove dummy source-data.'
, setTTL         : 'Set a TTL for a store-key record.'
, removeTTL      : 'Remove a ttl record'
, setUpdate      : 'Set recurring updates for specific API related record'
, removeUpdate   : 'Remove recurring updates requests'
, setNoCache     : 'Specify store-key records that should not have cache'
, removeNoCache  : 'Remove no cache setting per store-key'
, flush          : 'Flush data from data-pool'

pool.set

Creates a new data record in data pool.

pool.set ( [key, storeName], data, validationFn )
/**
 *  Arguments:
 *    - key: string (required). 
 *             if it's a string -> data identifier
 *             string can contain '/'. First element is the data identifier, 
 *             second is the extension.
 *      Extension should be available because some Api calls can return different
 *      results and we want to keep instead of overwrite them. Example: "getProduct"
 *      method can return product specification but we have a lot of products. We want
 *      to keep them in data-pool as a separate objects.
 *    - storeName: string(optional). Name of the store. Default value is 'default';
 *    - data: Any(required). Provide any data that should be saved;
 *    - validationFn: function(optional). Function will be executed always when we have 
 *      specified storeName/key. Function should returns a boolean(true/false).
 * 
 *   Returns: Boolean
 */

Example:

 // Validation function.
 let checkName = ( data ) => {
                       // Let's pretend that the right value could be only 'John', 'Peter' or 'Mark'
                       const list = [ 'John', 'Peter', 'Mark' ]
                       if ( list.includes ( data ) ) return true
                       else return false
                   }

 let first = pool.set ( ['name', 'demo'], 'Peter', checkName )
 // first => true
 /**
  * 1: No store 'demo': 
  *  Will create store 'demo' and will set property 'name' to 'Peter'
  * 2: There is store 'demo':
  * Will create a property 'name' for store 'demo'
  * 3: There is store 'demo' with a property 'name'
  * Will overwrite the property 'name' with 'Peter'
  * Validation function is optional. Will not work during initialization. Once is set up, it will be called.
  * Trying to provide a new validation function will be ignored.
  */
  
 // Validation is already setted for ['name', 'demo'] and will be used on every change request
 let second = pool.set ( ['name', 'demo'], 'Ivan' )
 // second => false
 // Name 'Ivan' will not pass the validation and will return false. No changes will be made in the store.
 
 

 // When 'set' method returns boolean you can use it as a condition
 if ( pool.set( ['name', 'demo'], 'John' ) ) {
        // Do something if success
    }
 else {
        // Do something if fail
    }

pool.get

Returns a requested data. If there is no value and there is associated Api, will send request to the Api. Dummy values per store/key will overwrite the Api if they exists.

pool.get ( [ key, storeName], ...other )
/**
 *  Arguments:
 *     - storeName: string(required). Name of the store;
 *     - key: string (required). 
 *             if it's a string -> data identifier
 *             key can contains the symbol '/' that will separate key from extensions
 *   Returns: Any. The data
 */

With pool.get is possible to get multiple properties of different stores and receive the result as an array.

// here is the long way
pool.get ( [ ['name', 'demo'], ['age', 'demo'], ['height', 'demo'], ['weight', 'metrics'] ] )

// requests to same store can be organized like this
let [ name, age, height, weight ] = pool.get ([ 
              [ 'name,age,height', 'demo']
            , ['weight', 'metrics'] 
        ])

// the response always will be an array
// ---> [ 'Peter', 20, 180 , 80 ]
// With distructuring we can get name='Peter', age=20, height=180, weight=80
// if requested value does not exist, it will return null

// if all requested values are from the same store you can simplify the request
pool.get ( [ 'name,age,height', 'demo' ] )
// single square bracket set is enough

pool.addApi

Register api in data-pool as source of information. Api name will become a store name and api methods will become keys. Key as a tuple represents methods that can return more that one result and records will need specification. For example - key:[ getProduct, 2443 ]. getProduct can return all items in the system, but extension specifies the exact product ID.

 pool.addApi ( apiList )
 /**
  *  Arguments:
  *  - apiList: object(required). List of Api that should work into data-pool
  *  Returns: void
  */
 

Example:

// we have api for users(userAPI) and api for products(productAPI)
pool.addApi ({ 
            user:userAPI, 
            product:productAPI 
        })

// userApi has method 'getDetails'. Here is an example how we can call that method
let r = pool.get ( [ 'getDetails', 'user'] )
// r will contain result of userAPI.getDetails()

pool.removeApi

Removes conection of data-pool to api. Removes all 'updates' related to these api methods.


pool.removeApi ( apiName )
/**
 *  Arguments:
 *  - apiName - string(required). Api name that should be removed;
 *  Returns: void
 *
 */

// Remove multiple apis - single string of api names separated by comma.
pool.removeApi ( 'apiName1, apiName2' )

Example:

  pool.removeApi ( 'user' )
 // Will remove association with userAPI from prev. example
 let r = pool.getAsync ([ 'getDetails', 'user'] )
  // Relation to the api is removed but store still exists!
  // 1. If store 'user' has record for 'getDetails' -> will return the result
  // 2. If there is no record -> will return null.    

pool.list

Returns list of all existing stores.

pool.list ()
/**
 *  no arguments
 *  Returns: string[]. 
 */

Example:

// If we have association to userAPI and productAPI, and we have called once a
// pool.get ( 'user','getDetails' )
const list = pool.list ()
// list => [ 'user' ]

Accociation of the productAPI with data-pool will not create the store automatically. Store will be created when we have data for it.

pool.has

Check if store or store/key exists.

  pool.has ( [ keyList, storeName ] )
  /**
   *  Arguments
   *  - storeName - string(required). Name of the store.
   *  - keyList: coma separated strings(requested properties) or just a string(single requested property). 
   *             if string has '/', first element is the data identifier, other elements are extensions.
   *  Returns: boolean.
   */

Example:

  const hasStore = pool.has ( 'user' )
  // hasStore => true

  // check for multiple stores (comma separated values)
  const hasStores = pool.has ( 'user, product' )
  // hasStores => false (if product or user store does not exist)

  // check for single property
  const hasProperty = pool.has ( ['name', 'user'] )
  // hasProperty => true ( check if store 'user' has property 'name'. If has, will return true)

pool.importStore

Converts a javascript object to data-pool store.

 pool.importStore ( storeName, data )
 /**
  *   Arguments:
  *     - storeName - string(required). Data will become a store
  *     - data - object(required). Any data 
  * 
  *   Returns : void
  */

Example:

const data = {
                name : 'Peter'
              , age : 48
            }
pool.importStore ( 'yo', data )
let name = pool.get ( [ 'name', 'yo'] )
// name === 'Peter'

pool.exportStore

Returns a store as a javascript object

pool.exportStore ( storeName )
/**
 *  Arguments:
 *  - storeName - string(required). Name of the store for export
 *  Returns : object
 */

pool.on

Data-pool events are triggered on store's data changes.

pool.on ( nameOfStore, callback )
function callback ( key, oldData, newData ) {
                // ....
        }
/**
 *   Method 'on' Arguments
 *   - nameOfStore - string(required). Listen for changes in the specified store.
 *   - callback - function(required). Fn will be executed on every data field change;
 *   Returns : void
 * 
 *  Callback Arguments:
 *   - key     -  Name of the changed field
 *   - oldData - field value at until now
 *   - newData - field upcoming value
 *  Returns : void
 */

pool.setDummy

Set a dummy source of information for specific store/key. Used for testing and development purposes. If Api is not ready we can provide expected data as using a dummy function. To get back to real api call remove the dummy. Dummy will always overwrite default source of information.

pool.setDummy ( [ key, storeName], dummyFn )
/**
 *  Arguments:
 *     - storeName: string(required). Name of the store;
 *     - key: string or tuple(required). 
 *             if it's a string -> data identifier
 *             if it's a tuple -> first element is the data identifier, 
 *                                second is the extension. 
 *     - dummyFn: function. Function will be executed always when we have
 *                specified storeName/key. Function should return a promise.
 * 
 *  Returns: void
 */

pool.removeDummy

Cancel dummy source of information.

pool.removeDummy ( [ key, storeName] )
/**
 *  Arguments:
 *     - storeName: string(required). Name of the store;
 *     - key: string or tuple(required). 
 *             if it's a string -> data identifier
 */

pool.setTTL

Set a 'time to live'(TTL) to specific store/key.

 pool.setTTL ( [ key, storeName], ttl )
 /**
  *  Arguments: 
  *  - storeName : string(required). Name of the store;
  *  - key: string(required). Data identifier
  *  - ttl: number(required). Time to live in ms. 
  *  Returns: void
  */ 

pool.removeTTL

Cancel TTL for specific store/key.

pool.removeTTL ( storeName, key )
/**
 *  Arguments:
 *  - storeName: string(required). Name of the store;
 *  - key: string(required). Data identifier;
 *  Returns: void
 */

pool.setUpdate

Set interval to update record for api related stores.

pool.setUpdate ( [ key, storeName], interval )
/**
 *  Arguments:
 *  - storeName: string(required). Name of the store;
 *  - key: string(required). Data identifier;
 *  - interval: number(required). Interval for next update in ms.
 *  Returns: void;
 */

pool.removeUpdate

Cancel automatic update for api related stores.

pool.removeUpdate ( [key, storeName] )
/**
 *  Arguments:
 *  - storeName: string(required). Name of the store;
 *  - key: string(required). Data identifier;
 *  Returns: void
 */

pool.setNoCache

Use 'setNoCache' method with api related stores. Set store-key as no-cache and every data request will hit the api.

 pool.setNoCache ([ key, storeName ])
 /**
  *  Arguments:
  *  - storeName : string(required). Name of the store;
  *  - key: string(required). Data identifier;
  *  Returns: void
  */

pool.removeNoCache

Cancel no-cache request.

pool.removeNoCache ([ key, storeName ])
/**
 * Arguments:
 *  - key: string(required). Data identifier;
 *  - storeName: string(required). Name of the store;
 *  Returns : void
 */

pool.flush

Flush data from data pool.

pool.flush ()
/**
 *  no arguments
 *  Will remove the content from all available storages;
 *  Returns: void
 */

pool.flush ( 'storeName, storeName2' )
/**
 *  Arguments:
 *  - string. List of stores that should be flushed separated by comma.
 * 
 *  Will remove the content of counted stores.
 *  Returns: void
 */
pool.flush ( [ 'key', 'storeName' ])
/**
 *  Arguments:
 * - array [ key, storeName]. Will remove the specific data from specific store.
 */

Credits

'@peter.naydenov/data-pool' was created and supported by Peter Naydenov.

License

'@peter.naydenov/data-pool' is released under the MIT License.