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

soon-storage

v3.0.0

Published

A type-safe storage solution for localStorage and sessionStorage with built-in TypeScript support, ensuring robust and scalable browser data persistence.

Readme

soon-storage 🚀

Language / 语言

English

A type-safe storage solution for localStorage, sessionStorage, and IndexedDB with built-in TypeScript support, ensuring robust and scalable browser data persistence.

Features ✨

  • 🔐 Type-Safe: Built with TypeScript for strong typing and better developer experience.
  • 📦 Flexible Storage: Supports localStorage, sessionStorage, and IndexedDB.
  • ⚙️ Customizable: Easily define custom data transformations.
  • Expiration Support: Set expiration times for stored items.
  • 🔒 Encryption/Decryption: Built-in support for data encryption and decryption.
  • 🚀 Batch Operations: Support for batch get, set, and remove operations for improved performance.

Installation

npm install soon-storage

Usage

1. Synchronous Storage (localStorage/sessionStorage)

import { createStorage, parsers as p } from "soon-storage";

const storage = createStorage({
  // stored key prefix
  prefix: "soon-",
  // choose localStorage or SessionStorage
  provider: () => localStorage,
  // string,number,boolean,json  are built-in transform method
  // you can define your own transform like below for a Date type
  transforms: {
    name: p.string("Guest"), // field with default value
    age: p.number(() => Math.random() * 100), // field with default value function
    birth: p.any({
      getter: (val) => (val === null ? null : new Date(val)),
      setter: (val) => val.toISOString(),
    }),
    graduated: p.boolean(false), // field with default value
    school: p.json<{
      name: string;
      address: string;
    }>(), // field without default value
  },
});

// set a key-value
storage.birth.set(new Date("2008-08-08"));
// get a key-value
storage.birth.get();
// remove a key-value
storage.birth.remove();

// Get values with and without defaults
console.log(storage.name.get()); // Returns "Guest" if not set
console.log(storage.age.get()); // Returns random number if not set
console.log(storage.graduated.get()); // Returns false if not set
console.log(storage.school.get()); // Returns null if not set



// Using expires parser for explicit expiration support
const storageWithExpires = createStorage({
  prefix: "expires-",
  provider: () => localStorage,
  define: {
    // Using expires parser
    userSession: p.expires<{ userId: string; token: string }>(),
    tempData: p.expires<string>("default"),
  },
});

// Set with expiration
storageWithExpires.userSession.set({ userId: "123", token: "abc123" }, expirationTime);

// Set without expiration
storageWithExpires.tempData.set("temporary value");

// Get values
const userSession = storageWithExpires.userSession.get();
const tempData = storageWithExpires.tempData.get();

//set all key-values
storage.$.setAll({
  name: "Lucy",
  age: 100,
  birth: new Date(),
  graduated: false,
  school: {
    name: "Green Land",
    address: "Qingdao",
  },
});

// get all key-values
const allData = storage.$.getAll();
console.log(allData);

// remove all key-values
// only this instance keys would be removed
storage.$.removeAll();

2. Asynchronous Storage (IndexedDB)

import { createStorageAsync, parsers as p, indexedDBProvider } from "soon-storage";

// Create IndexedDB storage instance
const indexedDbStorage = indexedDBProvider('my-db', 'my-store');

const asyncStorage = createStorageAsync({
  prefix: "async-",
  provider: () => indexedDbStorage,
  transforms: {
    name: p.string("Guest"),
    age: p.number(18),
    isAdmin: p.boolean(false),
  },
});

// Async operations
await asyncStorage.name.set("John");
const name = await asyncStorage.name.get();
await asyncStorage.name.remove();

// Batch operations
await asyncStorage.$.setAll({ name: "Alice", age: 25, isAdmin: true });
const allData = await asyncStorage.$.getAll();
await asyncStorage.$.removeAll();

3. Encryption/Decryption

import { createStorage, parsers as p } from "soon-storage";

// Simple encryption/decryption functions
const encrypt = (data: string) => btoa(data);
const decrypt = (data: string) => atob(data);

const secureStorage = createStorage({
  prefix: "secure-",
  provider: () => localStorage,
  define: {
    // Add encryption/decryption to parsers
    token: p.string(null, [encrypt, decrypt]),
    userData: p.json<{ id: number; name: string }>(null, [encrypt, decrypt]),
  },
});

// Data will be encrypted when stored and decrypted when retrieved
secureStorage.token.set("secret-token-123");
const token = secureStorage.token.get(); // Returns "secret-token-123"

4. Key Encryption

Per-key Key Encryption

You can now specify different key encryption processors for each key:

import { createStorage, parsers as p } from "soon-storage";

// Different key encryption functions for different keys
const encryptUserKey = (key: string) => btoa(key);
const encryptTokenKey = (key: string) => btoa(btoa(key)); // Double encryption for token

const storageWithPerKeyEncryption = createStorage({
  prefix: "app-",
  provider: () => localStorage,
  define: {
    // Username with its own key encryption
    username: p.string(null, undefined, encryptUserKey),
    // Token with double encryption
    token: p.string(null, undefined, encryptTokenKey),
    // Age with no key encryption
    age: p.number(),
  },
});

// Keys will be encrypted with their respective encryption methods
storageWithPerKeyEncryption.username.set("john");
storageWithPerKeyEncryption.token.set("secret-token");
storageWithPerKeyEncryption.age.set(30);

// Keys will be automatically decrypted when retrieved
const username = storageWithPerKeyEncryption.username.get();
const token = storageWithPerKeyEncryption.token.get();
const age = storageWithPerKeyEncryption.age.get();

API Reference

createStorage(config)

Creates a synchronous storage instance.

Parameters

  • config: Configuration object
    • prefix: Optional key prefix for stored items
    • provider: Function that returns a storage provider (localStorage or sessionStorage)
    • define: Object defining data transformations for each field

Returns

  • A storage object with methods for each defined field and batch operations.

createStorageAsync(config)

Creates an asynchronous storage instance.

Parameters

  • config: Configuration object (same as createStorage)

Returns

  • A storage object with async methods for each defined field and batch operations.

indexedDBProvider(dbName, storeName)

Creates an IndexedDB storage provider.

Parameters

  • dbName: Optional database name (default: 'soon-storage')
  • storeName: Optional object store name (default: 'storage')

Returns

  • An IndexedDB storage provider with batch support.

Parsers

  • p.string(defaultValue?, [beforeSet, afterGet]?, keyProcessor?): String parser
  • p.number(defaultValue?, [beforeSet, afterGet]?, keyProcessor?): Number parser
  • p.boolean(defaultValue?, [beforeSet, afterGet]?, keyProcessor?): Boolean parser
  • p.json<T>(defaultValue?, [beforeSet, afterGet]?, keyProcessor?): JSON parser
  • p.expires<T>(defaultValue?, [beforeSet, afterGet]?, keyProcessor?): Expiring value parser
  • p.any<T>({ getter, setter }, [beforeSet, afterGet]?, keyProcessor?): Custom parser

Processor Functions

  • beforeSet(value): Process value before storage
  • afterGet(value): Process value after retrieval
  • keyProcessor(key): Process key before storage (optional, used for key encryption)

License

MIT License


中文

一个类型安全的存储解决方案,支持 localStorage、sessionStorage 和 IndexedDB,内置 TypeScript 支持,确保健壮且可扩展的浏览器数据持久化。

特性 ✨

  • 🔐 类型安全:使用 TypeScript 构建,提供强大的类型检查和更好的开发体验。
  • 📦 灵活存储:支持 localStoragesessionStorageIndexedDB
  • ⚙️ 可定制:轻松定义自定义数据转换。
  • 过期支持:为存储项设置过期时间。
  • 🔒 加密/解密:内置数据加密和解密支持。
  • 🚀 批量操作:支持批量获取、设置和删除操作,提高性能。

snap.png

安装

npm install soon-storage

使用

1. 同步存储 (localStorage/sessionStorage)

import { createStorage, parsers as p } from "soon-storage";

const storage = createStorage({
  // 存储键前缀
  prefix: "soon-",
  // 选择 localStorage 或 SessionStorage
  provider: () => localStorage,
  // string,number,boolean,json 是内置的转换方法
  // 你可以像下面这样为 Date 类型定义自己的转换
  define: {
    name: p.string("Guest"), // 带默认值的字段
    age: p.number(() => Math.random() * 100), // 带默认值函数的字段
    birth: p.any({
      getter: (val) => (val === null ? null : new Date(val)),
      setter: (val) => val.toISOString(),
    }),
    graduated: p.boolean(false), // 带默认值的字段
    school: p.json<{
      name: string;
      address: string;
    }>(), // 不带默认值的字段
  },
});

// 设置键值对
storage.birth.set(new Date("2008-08-08"));
// 获取键值对
storage.birth.get();
// 删除键值对
storage.birth.remove();

// 获取带默认值和不带默认值的值
console.log(storage.name.get()); // 如果未设置,返回 "Guest"
console.log(storage.age.get()); // 如果未设置,返回随机数
console.log(storage.graduated.get()); // 如果未设置,返回 false
console.log(storage.school.get()); // 如果未设置,返回 null



// 使用 expires 解析器获得显式过期支持
const storageWithExpires = createStorage({
  prefix: "expires-",
  provider: () => localStorage,
  define: {
    // 使用 expires 解析器
    userSession: p.expires<{ userId: string; token: string }>(),
    tempData: p.expires<string>("default"),
  },
});

// 设置带过期时间的值
storageWithExpires.userSession.set({ userId: "123", token: "abc123" }, expirationTime);

// 设置不带过期时间的值
storageWithExpires.tempData.set("temporary value");

// 获取值
const userSession = storageWithExpires.userSession.get();
const tempData = storageWithExpires.tempData.get();

// 设置所有键值对
storage.$.setAll({
  name: "Lucy",
  age: 100,
  birth: new Date(),
  graduated: false,
  school: {
    name: "Green Land",
    address: "Qingdao",
  },
});

// 获取所有键值对
const allData = storage.$.getAll();
console.log(allData);

// 删除所有键值对
// 只会删除此实例的键
storage.$.removeAll();

2. 异步存储 (IndexedDB)

import { createStorageAsync, parsers as p, indexedDBProvider } from "soon-storage";

// 创建 IndexedDB 存储实例
const indexedDbStorage = indexedDBProvider('my-db', 'my-store');

const asyncStorage = createStorageAsync({
  prefix: "async-",
  provider: () => indexedDbStorage,
  define: {
    name: p.string("Guest"),
    age: p.number(18),
    isAdmin: p.boolean(false),
  },
});

// 异步操作
await asyncStorage.name.set("John");
const name = await asyncStorage.name.get();
await asyncStorage.name.remove();

// 批量操作
await asyncStorage.$.setAll({ name: "Alice", age: 25, isAdmin: true });
const allData = await asyncStorage.$.getAll();
await asyncStorage.$.removeAll();

3. 加密/解密

import { createStorage, parsers as p } from "soon-storage";

// 简单的加密/解密函数
const encrypt = (data: string) => btoa(data);
const decrypt = (data: string) => atob(data);

const secureStorage = createStorage({
  prefix: "secure-",
  provider: () => localStorage,
  define: {
    // 为解析器添加加密/解密
    token: p.string(null, [encrypt, decrypt]),
    userData: p.json<{ id: number; name: string }>(null, [encrypt, decrypt]),
  },
});

// 数据存储时会被加密,检索时会被解密
secureStorage.token.set("secret-token-123");
const token = secureStorage.token.get(); // 返回 "secret-token-123"

4. 键加密

每个键的独立键加密

现在你可以为每个键指定不同的键加密处理器:

import { createStorage, parsers as p } from "soon-storage";

// 不同键的不同加密函数
const encryptUserKey = (key: string) => btoa(key);
const encryptTokenKey = (key: string) => btoa(btoa(key)); // Token 使用双重加密

const storageWithPerKeyEncryption = createStorage({
  prefix: "app-",
  provider: () => localStorage,
  define: {
    // 用户名使用自己的键加密
    username: p.string(null, undefined, encryptUserKey),
    // Token 使用双重加密
    token: p.string(null, undefined, encryptTokenKey),
    // 年龄不使用键加密
    age: p.number(),
  },
});

// 键会使用各自的加密方法加密
storageWithPerKeyEncryption.username.set("john");
storageWithPerKeyEncryption.token.set("secret-token");
storageWithPerKeyEncryption.age.set(30);

// 键会自动解密
const username = storageWithPerKeyEncryption.username.get();
const token = storageWithPerKeyEncryption.token.get();
const age = storageWithPerKeyEncryption.age.get();

API 参考

createStorage(config)

创建一个同步存储实例。

参数
  • config: 配置对象
    • prefix: 存储项的可选键前缀
    • provider: 返回存储提供者的函数(localStorage 或 sessionStorage)
    • define: 定义每个字段的数据转换的对象
返回值
  • 一个存储对象,具有每个定义字段的方法和批量操作。

createStorageAsync(config)

创建一个异步存储实例。

参数
  • config: 配置对象(与 createStorage 相同)
返回值
  • 一个存储对象,具有每个定义字段的异步方法和批量操作。

indexedDBProvider(dbName, storeName)

创建一个 IndexedDB 存储提供者。

参数
  • dbName: 可选的数据库名称(默认: 'soon-storage')
  • storeName: 可选的对象存储名称(默认: 'storage')
返回值
  • 一个带有批量支持的 IndexedDB 存储提供者。

解析器

  • p.string(defaultValue?, [beforeSet, afterGet]?, keyProcessor?): 字符串解析器
  • p.number(defaultValue?, [beforeSet, afterGet]?, keyProcessor?): 数字解析器
  • p.boolean(defaultValue?, [beforeSet, afterGet]?, keyProcessor?): 布尔值解析器
  • p.json<T>(defaultValue?, [beforeSet, afterGet]?, keyProcessor?): JSON 解析器
  • p.expires<T>(defaultValue?, [beforeSet, afterGet]?, keyProcessor?): 带过期时间的解析器
  • p.any<T>({ getter, setter }, [beforeSet, afterGet]?, keyProcessor?): 自定义解析器
处理器函数
  • beforeSet(value): 存储前处理值
  • afterGet(value): 检索后处理值
  • keyProcessor(key): 存储前处理键(可选,用于键加密)

许可证

MIT 许可证