# @tni/cache

> 浏览器端模块化缓存与存储抽象（localStorage / sessionStorage / Cookie / IndexedDB）。

Latest version **2.0.2** (published 2026-04-13) · MIT license · 0 weekly downloads

## Install

```sh
npm install @tni/cache
pnpm add @tni/cache
yarn add @tni/cache
bun add @tni/cache
```

## Health

**Score 60/100 (C)** — status: active.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 2.0.2 |
| Published | 2026-04-13 |
| First published | 2022-01-22 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 37 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | dt-terry |
| Maintainers | dt-terry |

## Links

- npm: https://www.npmjs.com/package/@tni/cache
- Repository: https://gitee.com/core-design/tni
- npm.io page: https://npm.io/package/@tni/cache

## Recent versions

- 2.0.2 (latest) — 2026-04-13
- 2.0.0 — 2026-03-26
- 1.0.6 — 2022-02-10
- 1.0.5 — 2022-02-10
- 1.0.4 — 2022-01-27
- 1.0.3 — 2022-01-26
- 1.0.2 — 2022-01-22
- 1.0.1 — 2022-01-22
- 1.0.0 — 2022-01-22

## README

# @tni/cache

浏览器端模块化缓存与存储抽象：在 **localStorage**、**sessionStorage**、**Cookie**、**IndexedDB** 上提供统一的 **`StorageAdapter`** 异步接口，便于按场景切换后端而少改业务代码。

## 设计目标

- **统一契约**：`set` / `get` / `remove` / `getAll` / `clear` / `getSize` 等行为在各后端一致，均为 Promise。
- **可扩展**：Web Storage 场景可通过 `createWebStorageAdapter` + `createCachedStorageResolver` 接入自定义 `Storage` 实现（含测试替身）。
- **可维护**：序列化、过期（ttl / expires）、键前缀、配额相关工具集中在内部管线，各后端只处理字符串载荷。
- **无内置加解密**：若要对落盘字符串加密，由业务实现 `encrypt` / `decrypt` 或 `cipher` 并传入配置；本包不提供算法实现。
- **零运行时依赖**：发布产物不捆绑第三方库；需在支持 `window` / `document` / `indexedDB` 的浏览器（或等价 polyfill）中使用。

## 包结构（源码）

```text
src/
  index.ts                 # 对外统一导出
  shared/
    types.ts               # StorageAdapter、BaseStorageOptions、错误类型等
    base.ts                # 序列化/过期/配额辅助（含 estimateQuota 等）
  modules/
    browser/               # localStorage / sessionStorage / 通用 Web Storage 适配器
    cookie/                # document.cookie 封装
    indexed-db/            # 单库单 object store 的 KV 封装
```

## 安装

```bash
pnpm add @tni/cache
```

（Monorepo 内也可通过 workspace 协议引用本包。）

## 快速开始

### localStorage / sessionStorage

```ts
import { createLocalStorage, createSessionStorage } from "@tni/cache";

const local = createLocalStorage<{ token: string }>({ prefix: "myapp:" });
await local.set("token", "xxx", { ttl: 3600 });
const token = await local.get("token");

const session = createSessionStorage<number>({ prefix: "myapp:" });
await session.set("step", 2);
```

包内也导出默认实例 `localStorage`、`sessionStorage`（与全局同名，建议按需 **as 别名** 导入，避免与 `window.localStorage` 混淆）：

```ts
import { localStorage as appLocal } from "@tni/cache";
await appLocal.set("k", "v");
```

### Cookie

```ts
import { createCookieStorage } from "@tni/cache";

const cookies = createCookieStorage<string>({
  prefix: "app_",
  defaultAttributes: { path: "/", sameSite: "lax" },
});

await cookies.set("sid", "abc123", { maxAge: 86400 });
const sid = await cookies.get("sid");
```

`set` 支持第三个参数覆盖单次写入的 Cookie 属性（`path`、`domain`、`secure`、`sameSite`、`maxAge`、`expires`、`ttl` 等）。

### IndexedDB

```ts
import { createIndexedDBStorage } from "@tni/cache";

const idb = createIndexedDBStorage<Record<string, unknown>>({
  dbName: "my_app_kv",
  storeName: "entries",
  version: 1,
  prefix: "cache:",
});

await idb.set("prefs", { theme: "dark" });
const prefs = await idb.get("prefs");
```

默认库名为 `__tni_cache__`，仓库名为 `kv`；同一站点多业务建议显式设置 `dbName` / `prefix` 隔离。

## 统一接口 `StorageAdapter`

| 方法                     | 说明                                                                                |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `set(key, value, opts?)` | 写入；`opts` 可含 `ttl`（秒）或 `expires`（`Date` 或毫秒时间戳）                    |
| `get(key)`               | 读取；无键或已过期返回 `null`（Cookie / Web Storage 等对「无值」可能表现为 `null`） |
| `remove(key)`            | 删除单键                                                                            |
| `getAll()`               | 当前前缀下键值对（已过期条目会在读取时尽量清理）                                    |
| `clear()`                | 清空当前前缀（无前缀的 Web Storage 会 `storage.clear()`）                           |
| `getSize()`              | 当前命名空间占用估算（UTF-16 字符长度 ×2）；IndexedDB 上为异步                      |
| `isAvailable()`          | 当前环境是否可使用该后端                                                            |
| `isQuotaExceeded()`      | 最近一次写入是否因配额失败（具体行为因后端略有差异）                                |

## 通用配置 `BaseStorageOptions`

| 字段                             | 说明                                                           |
| -------------------------------- | -------------------------------------------------------------- |
| `prefix`                         | 键前缀，隔离命名空间                                           |
| `defaultTtl`                     | 默认存活时间（秒），可被单次 `set` 的选项覆盖                  |
| `serialize` / `deserialize`      | 自定义序列化，默认 `JSON.stringify` / `JSON.parse`             |
| `cipher` / `encrypt` / `decrypt` | 对「序列化后的字符串」再加工；需**自行实现**，本包无内置加解密 |
| `isAvailable`                    | 额外开关（例如 SSR 下返回 `false`）                            |

## 错误与配额

- 写入时若判定为存储配额不足，可能抛出 **`StorageQuotaExceededError`**（`storage` 字段标识后端，如 `localStorage`、`indexedDB`）。
- 工具函数 **`isQuotaExceededError(error)`** 用于统一识别原生 `QuotaExceededError` 与上述包装错误。
- **`estimateQuota()`** / **`formatBytes()`** 基于 `navigator.storage?.estimate()`，用于展示或监控（不支持时返回 `null`）。

## 扩展 Web Storage

若需在测试或非浏览器环境挂载自定义 `Storage`：

```ts
import { createCachedStorageResolver, createWebStorageAdapter } from "@tni/cache";

const getStorage = createCachedStorageResolver("localStorage");

const adapter = createWebStorageAdapter({
  storageName: "memory",
  getStorage: () => myFakeStorage,
  prefix: "t:",
});
```

## 开发与构建

本仓库使用 [Vite+](https://github.com/voidzero-dev/vite-plus)（`vp`）。

```bash
vp install          # 在仓库根目录安装依赖
cd packages/cache
vp test             # 单元测试
vp check            # 格式、Lint、类型检查
vp pack             # 构建 dist（ESM + CJS + 类型声明），对应 package.json 中 build 脚本
```

库包**推荐**使用 **`vp pack`** 作为发布构建；`vp build` 面向带 `index.html` 的应用入口，在未单独配置库模式时可能报错。

## 许可证

MIT

---
_Source: https://npm.io/package/@tni/cache · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
