Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 136 additions & 20 deletions core/keyv/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ There are a few existing modules similar to Keyv, however Keyv is different beca
- [Third-party Storage Adapters](#third-party-storage-adapters)
- [Using BigMap to Scale](#using-bigmap-to-scale)
- [Compression](#compression)
- [Capability Detection](#capability-detection)
- [API](#api)
- [new Keyv([storage-adapter], [options]) or new Keyv([options])](#new-keyvstorage-adapter-options-or-new-keyvoptions)
- [.namespace](#namespace)
Expand Down Expand Up @@ -303,37 +304,42 @@ In `PRE_DELETE` and `POST_DELETE` hooks, the value could be a single item or an

By default, Keyv uses its built-in `KeyvJsonSerializer` — a JSON-based serializer with support for `Buffer` and `BigInt` types. This works out of the box with all storage adapters.

## Custom Serializers
## Official Serializers

You can provide your own serializer by implementing the `KeyvSerializationAdapter` interface:
In addition to the built-in serializer, Keyv offers two official serialization packages:

```typescript
interface KeyvSerializationAdapter {
stringify: (object: unknown) => string | Promise<string>;
parse: <T>(data: string) => T | Promise<T>;
}
```
### SuperJSON

For example, using the built-in `JSON` object:
[`@keyv/serialize-superjson`](https://github.com/jaredwray/keyv/tree/main/serialization/superjson) supports `Date`, `RegExp`, `Map`, `Set`, `BigInt`, `undefined`, `Error`, and `URL` types.

```js
const keyv = new Keyv({
serialization: { stringify: JSON.stringify, parse: JSON.parse },
});
import Keyv from 'keyv';
import { superJsonSerializer } from '@keyv/serialize-superjson'; // using the helper function that does new KeyvSuperJsonSerializer()

const keyv = new Keyv({ serialization: superJsonSerializer });
```

Or a custom async serializer:
### MessagePack (msgpackr)

[`@keyv/serialize-msgpackr`](https://github.com/jaredwray/keyv/tree/main/serialization/msgpackr) is a binary serializer that supports `Date`, `RegExp`, `Map`, `Set`, `Error`, `undefined`, `NaN`, and `Infinity` types.

```js
const keyv = new Keyv({
serialization: {
stringify: async (value) => JSON.stringify(value),
parse: async (data) => JSON.parse(data),
},
});
import Keyv from 'keyv';
import { KeyvMsgpackrSerializer } from '@keyv/serialize-msgpackr';

const keyv = new Keyv({ serialization: new KeyvMsgpackrSerializer() });
```

**Warning:** Using custom serializers means you lose any guarantee of data consistency. You should do extensive testing with your serialization functions and chosen storage engine.
## Custom Serializers

You can provide your own serializer by implementing the `KeyvSerializationAdapter` interface with `stringify` and `parse` methods:

```typescript
interface KeyvSerializationAdapter {
stringify: (object: unknown) => string | Promise<string>;
parse: <T>(data: string) => T | Promise<T>;
}
```

## Disabling Serialization

Expand Down Expand Up @@ -519,6 +525,116 @@ interface KeyvEncryptionAdapter {
}
```

# Capability Detection

Keyv exports helper functions to check whether an object implements the expected interface for a Keyv instance, storage adapter, compression adapter, serialization adapter, or encryption adapter. Each function returns an object with boolean flags for every capability, plus a top-level boolean indicating whether the object fully satisfies the interface.

```ts
import {
detectKeyv,
detectKeyvStorage,
detectKeyvCompression,
detectKeyvSerialization,
detectKeyvEncryption,
detectCapabilities,
} from 'keyv';
```

## detectKeyv(obj)

Returns a `KeyvCapability` with a boolean for each Keyv method/property. The `keyv` flag is `true` only when **all** capabilities are present.

```ts
import Keyv, { detectKeyv } from 'keyv';

detectKeyv(new Keyv());
// { keyv: true, get: true, set: true, delete: true, clear: true, has: true,
// getMany: true, setMany: true, deleteMany: true, hasMany: true,
// disconnect: true, getRaw: true, getManyRaw: true, setRaw: true,
// setManyRaw: true, hooks: true, stats: true, iterator: true }

detectKeyv(new Map());
// { keyv: false, get: true, set: true, ... }
```

## detectKeyvStorage(obj)

Returns a `KeyvStorageCapability`. The `keyvStorage` flag is `true` when the object has `get`, `set`, `delete`, `clear`, `has`, `setMany`, `deleteMany`, and `hasMany`.

The result also includes:
- **`mapLike`** — `true` when the object has synchronous `get`, `set`, `delete`, `has`, `entries`, and `keys` methods (i.e. it behaves like a `Map`)
- **`methodTypes`** — a record mapping each method name to `"sync"`, `"async"`, or `"none"` (not present)

```ts
import { detectKeyvStorage } from 'keyv';

// Map-like object
const result = detectKeyvStorage(new Map());
result.mapLike; // true
result.methodTypes.get; // "sync"
result.methodTypes.set; // "sync"

// Async storage adapter
const adapter = {
get: async () => {}, set: async () => {}, delete: async () => {},
clear: async () => {}, has: async () => {}, setMany: async () => {},
deleteMany: async () => {}, hasMany: async () => {},
};
const adapterResult = detectKeyvStorage(adapter);
adapterResult.keyvStorage; // true
adapterResult.mapLike; // false
adapterResult.methodTypes.get; // "async"
```

## detectKeyvCompression(obj)

Returns a `KeyvCompressionCapability`. The `keyvCompression` flag is `true` when both `compress` and `decompress` methods are present.

```ts
import { detectKeyvCompression } from 'keyv';

detectKeyvCompression({ compress: (d) => d, decompress: (d) => d });
// { keyvCompression: true, compress: true, decompress: true }
```

## detectKeyvSerialization(obj)

Returns a `KeyvSerializationCapability`. The `keyvSerialization` flag is `true` when both `stringify` and `parse` methods are present.

```ts
import { detectKeyvSerialization } from 'keyv';

detectKeyvSerialization(JSON);
// { keyvSerialization: true, stringify: true, parse: true }
```

## detectKeyvEncryption(obj)

Returns a `KeyvEncryptionCapability`. The `keyvEncryption` flag is `true` when both `encrypt` and `decrypt` methods are present.

```ts
import { detectKeyvEncryption } from 'keyv';

detectKeyvEncryption({ encrypt: (d) => d, decrypt: (d) => d });
// { keyvEncryption: true, encrypt: true, decrypt: true }
```

## detectCapabilities(obj, spec)

A generic helper for building your own capability checks. Accepts a `CapabilitySpec` describing which methods and properties to look for, which are required, and the name of the composite boolean key.

```ts
import { detectCapabilities } from 'keyv';

const result = detectCapabilities(myObject, {
methods: ['read', 'write'],
properties: ['name'],
requiredKeys: ['read', 'write', 'name'],
compositeKey: 'isValid',
});
// { isValid: true/false, read: true/false, write: true/false, name: true/false }
```

# API

## new Keyv([storage-adapter], [options]) or new Keyv([options])
Expand Down
Loading
Loading