npm package: @iotux/uni-cache
Description: A versatile caching library with support for in-memory, file, ValKey, Redis, and MongoDB backends, offering flexible storage and synchronization options.
Author: iotux
Latest version: 0.3.0

# Uni-Cache

Uni-Cache is a caching library for Node.js applications. It presents a single API across in-memory, file, SQLite, Redis, MongoDB, and ValKey backends, making it straightforward to switch storage engines without rewriting business logic.

## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Usage](#usage)
- [API](#api)
- [Backend Guides](#backend-guides)
- [Troubleshooting](#troubleshooting)
- [License](#license)
- [Contributing](#contributing)

## Features
- Multiple backends: memory, filesystem, SQLite, Redis, MongoDB, and ValKey.
- Consistent CRUD helpers for both nested keys and entire objects.
- Configurable persistence: sync eagerly on every write, on demand, or on a fixed interval.
- Optional logging hook for integrating with your existing observability tools.

## Installation

```bash
npm install @iotux/uni-cache
```

### Optional dependencies
- SQLite backend: `npm install sqlite sqlite3`
- Redis backend: provide a compatible Redis/ValKey client configuration.
- MongoDB backend: supply a MongoDB URI and collection details.

## Quick Start

```javascript
const UniCache = require('@iotux/uni-cache');

async function demo() {
  const cache = new UniCache('demo-cache', { cacheType: 'memory' });
  await cache.init({ counter: 0 }); // Seeds the cache on first run.

  await cache.add('counter', 5);
  await cache.set('user.name', 'Ada Lovelace');

  console.log(await cache.get('counter')); // 5
  console.log(await cache.get('user.name')); // "Ada Lovelace"
}

demo().catch(console.error);
```

## Usage

### Choosing a backend
- `memory`: Fastest option when persistence is not required.
- `file`: Stores aggregate data in a single JSON file; per-object data is written to separate files.
- `sqlite`: Lightweight relational persistence suited to single-host deployments.
- `redis` / `valkey`: External in-memory datastores for shared caches.
- `mongodb`: Durable document storage with horizontal scalability.

### Aggregate keys vs. object storage
- Use `set`, `get`, and `delete` for scalar values or nested properties (`await cache.set('user.profile.email', 'ada@example.com')`).
- Use `createObject`, `retrieveObject`, and `deleteObject` to persist full JSON documents by top-level key (for example one file or SQLite row per customer record).
- The module tracks object-backed keys separately so that nested updates (`await cache.set('customer-42.balance', 100)`) operate directly on objects stored via `createObject`.

### Sync strategies
- `syncOnWrite: true` writes through to the backend on every mutation.
- `syncOnWrite: false` batches writes until `await cache.sync()` is called.
- `syncInterval` (seconds) enables periodic flushes.

## API

### Lifecycle
- `new UniCache(name, options)` – create an instance.
- `init(initialData)` – prepare the backend and optionally seed data.
- `sync(force)` – persist dirty aggregate data and pending object work.
- `close()` – flush remaining work (if `syncOnClose` is set) and tear down backend connections.

### Aggregate operations
- `get(path)` – retrieve a value (supports dot notation).
- `set(path, value, syncNow)` – store a value.
- `delete(path, syncNow)` – remove a value.
- `add(path, count, syncNow)` / `subtract(path, count, syncNow)` – numeric adjustments.
- `push(path, element, syncNow)` – append to an array.

### Whole-object helpers
- `createObject(key, payload, syncNow)` – persist a top-level object.
- `retrieveObject(key)` – fetch an object created with `createObject`.
- `deleteObject(key, syncNow)` – remove a stored object.

### Introspection
- `has(path)` – determine if a value exists.
- `keys()` – list top-level keys (aggregate and object-backed).
- `count()` – count top-level keys.
- `clear(syncNow)` – remove all data.
- `existsObject()` / `getInMemorySize()` – simple state queries.

## Backend Guides

### In-memory
```javascript
const cache = new UniCache('session-cache', { cacheType: 'memory', debug: true });
await cache.init();
await cache.set('activeUsers', 10);
```

### File
```javascript
const cache = new UniCache('settings', {
  cacheType: 'file',
  savePath: './data/settings',
  syncOnWrite: false,
});

await cache.init();
await cache.set('ui.theme', 'dark');
await cache.sync(); // Flush batched changes to disk.
```

### SQLite
```javascript
const cache = new UniCache('telemetry', {
  cacheType: 'sqlite',
  savePath: './data/sqlite',
  syncOnWrite: false,
});

await cache.init();
await cache.createObject('meter-001', { watts: 1200, lastUpdated: Date.now() }, false);
await cache.set('meter-001.lastUpdated', Date.now(), false);
await cache.sync(); // Uses incremental upserts to avoid rewriting the whole table.
```

### Redis / ValKey
```javascript
const cache = new UniCache('sessions', {
  cacheType: 'redis',
  redisConfig: { host: '127.0.0.1', port: 6379 },
  syncOnWrite: true,
});

await cache.init();
await cache.set('user:42.token', 'abc123');
await cache.close();
```

### MongoDB
```javascript
const cache = new UniCache('feature-flags', {
  cacheType: 'mongodb',
  mongoUri: 'mongodb://localhost:27017',
  dbName: 'configs',
  collectionName: 'flags',
  syncOnWrite: true,
});

await cache.init();
await cache.set('flags.betaUsers', ['ada', 'grace']);
```

## Troubleshooting
- **SQLite:** Uni-Cache enables WAL mode for better concurrency. Ensure the user running your app can create the database file and parent directories. Install both `sqlite` and `sqlite3` packages before initialising the backend.
- **File backend:** Keep object keys free of path separators; each object is written to `<savePath>/<key>.json`.
- **Redis/ValKey:** Provide a reachable host/port combination and close the cache to release the connection cleanly.

## License

Distributed under the MIT License. See [LICENSE](LICENSE) for details.

## Contributing

Issues and pull requests are welcome. Please describe the backend(s) involved and any reproduction steps when reporting bugs.