Skip to content

The browser-cache-async package provides a highly customizable, asynchronous caching system for client-side data management. Leveraging the power of the browser's IndexedDB, it enables efficient storage and retrieval of API responses, significantly reducing network latency and improving application performance.

License

Notifications You must be signed in to change notification settings

jesusgraterol/browser-cache-async

Repository files navigation

Browser Cache Async

The browser-cache-async package provides a highly customizable, asynchronous caching system for client-side data management. Leveraging the power of the browser's IndexedDB, it enables efficient storage and retrieval of API responses, significantly reducing network latency and improving application performance.

With flexible configuration options for cache lifecycles, expiration strategies, and data management policies, browser-cache-async is the ideal solution for developers looking to optimize web applications, enhance offline capabilities, and deliver a smoother user experience.


Getting Started

Install the package:

npm install -S browser-cache-async

Usage

Cache the result of a fetch request:

import { BrowserCache } from 'browser-cache-async';
import { IProduct } from './types.js';

const cache = new BrowserCache<IProduct>('products');

// retrieve and cache the product. If revalidate is not provided, the data becomes stale after 24 hours
const id = 1;
const product = await cache.run({
  id,
  query: async () => {
    const res = await fetch(`https://fakestoreapi.com/products/${id}`);
    return res.json();
  }
});
// {
//   id: 1,
//   title: '...',
//   price: '...',
//   category: '...',
//   description: '...',
//   image: '...'
// }

Cache an article for 2 weeks if it has been published:

import { BrowserCache } from 'browser-cache-async';
import { BackendService } from './backend.js';
import { IArticle } from './types.js';

const cache = new BrowserCache<IArticle>('articles');

const id = 'db6d9d01-8d67-4765-8baa-2210cbc0470e';
const article = await cache.run({
  id,
  query: async () => BackendService.getArticle(id),
  cacheIf: (id: IRecordID, data: IArticle) => data.isDraft === false,
  revalidate: '2 weeks'
});
// {
//   id: 'db6d9d01-8d67-4765-8baa-2210cbc0470e',
//   heading: '...',
//   subHeading: '...',
//   content: '...',
//   isDraft: false
// }

// if the article is updated or removed, trigger a revalidation manually
await cache.revalidate(id);

Types

IRecordID

The identifier used to manage records. The store behaves differently based on the type:

  • undefined: the data will be stored at the root of the store
  • string | number: the value will be coerced into a string and can be used to locate the data
type IRecordID = undefined | string | number;

Note: this type is exposed by the browser-keyval-stores package.

IStringValue

The template literal types that prevents developers from passing invalid strings to the ms function.

type IUnit =
| 'Years'
| 'Year'
| 'Yrs'
| 'Yr'
| 'Y'
| 'Weeks'
| 'Week'
| 'W'
| 'Days'
| 'Day'
| 'D'
| 'Hours'
| 'Hour'
| 'Hrs'
| 'Hr'
| 'H'
| 'Minutes'
| 'Minute'
| 'Mins'
| 'Min'
| 'M'
| 'Seconds'
| 'Second'
| 'Secs'
| 'Sec'
| 's'
| 'Milliseconds'
| 'Millisecond'
| 'Msecs'
| 'Msec'
| 'Ms';

type IUnitAnyCase = IUnit | Uppercase<IUnit> | Lowercase<IUnit>;

type IStringValue =
| `${number}`
| `${number}${IUnitAnyCase}`
| `${number} ${IUnitAnyCase}`;

Note: this type is exposed by the ms package`.

ICacheIfFn

Utility type to indicate the function that will be invoked to evaluate if the data should be cached.

type ICacheIfFn<T> =
  ((id: IRecordID, data: T) => Promise<boolean>) | ((id: IRecordID, data: T) => boolean);
IQueryOptions

Object in charge of controlling how the query is executed and cached.

import { IRecordID } from 'browser-keyval-stores';

type IQueryOptions<T> = {
  // the record's identifier
  id?: IRecordID;

  // the function that will be invoked to retrieve the data
  query: () => Promise<T>;

  // the function that will be invoked to evaluate if the data should be cached. If not provided,
  // the data will always be cached.
  cacheIf?: ICacheIfFn | boolean;

  // the number of milliseconds the data will be fresh for before becoming stale. If not provided,
  // the data will become stale after 1 day.
  revalidate?: IStringValue | number;
};

// the result of processing the query options object passed by the developer
type IProcessedQueryOptions<T> = IQueryOptions<T> & { revalidate: number };
IBrowserCache

Object in charge of managing the caching of data in the browser.

interface IBrowserCache<T> {
  // properties
  // ...

  // actions
  run: (options: IQueryOptions<T>) => Promise<T>;
  revalidate(id?: IRecordID): Promise<void>;
}

Built With

  • TypeScript

Tests

# integration tests
npm run test:integration

# unit tests
npm run test:unit

License

MIT


Deployment

Install dependencies:

npm install

Build the library:

npm start

Publish to npm:

npm publish

About

The browser-cache-async package provides a highly customizable, asynchronous caching system for client-side data management. Leveraging the power of the browser's IndexedDB, it enables efficient storage and retrieval of API responses, significantly reducing network latency and improving application performance.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published