diff --git a/README.md b/README.md
index 781f88b51..bdb53b076 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,4 @@
-
-
-
-
-
+
> Simple key-value storage with support for multiple backends
diff --git a/packages/compress-brotli/package.json b/packages/compress-brotli/package.json
index e058854af..67abbdcea 100644
--- a/packages/compress-brotli/package.json
+++ b/packages/compress-brotli/package.json
@@ -55,7 +55,7 @@
"dependencies": {
"@keyv/serialize": "*",
"compress-brotli": "^1.3.12",
- "keyv": "*"
+ "keyv": "^5.2.1"
},
"devDependencies": {
"@keyv/test-suite": "*",
diff --git a/packages/keyv/README.md b/packages/keyv/README.md
index 67c545489..266e2c911 100644
--- a/packages/keyv/README.md
+++ b/packages/keyv/README.md
@@ -1,4 +1,4 @@
-[](https://github.com/jaredwra/keyv)
+
> Simple key-value storage with support for multiple backends
diff --git a/packages/keyv/package.json b/packages/keyv/package.json
index 1408ed98a..0c7b5e0b7 100644
--- a/packages/keyv/package.json
+++ b/packages/keyv/package.json
@@ -1,6 +1,6 @@
{
"name": "keyv",
- "version": "5.2.0",
+ "version": "5.2.1",
"description": "Simple key-value storage with support for multiple backends",
"type": "module",
"main": "dist/index.cjs",
diff --git a/packages/keyv/src/index.ts b/packages/keyv/src/index.ts
index 4d814b2d2..293b56d57 100644
--- a/packages/keyv/src/index.ts
+++ b/packages/keyv/src/index.ts
@@ -12,6 +12,8 @@ export type DeserializedData = {
export interface CompressionAdapter {
compress(value: any, options?: any): Promise;
decompress(value: any, options?: any): Promise;
+ serialize(data: DeserializedData): Promise | string;
+ deserialize(data: string): Promise | undefined> | DeserializedData | undefined;
}
export type Serialize = (data: DeserializedData) => Promise | string;
diff --git a/packages/tiered/LICENSE b/packages/tiered/LICENSE
deleted file mode 100644
index a6bad1d22..000000000
--- a/packages/tiered/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-MIT License
-
-Copyright (c) 2017-2021 Luke Childs
-Copyright (c) 2021-2022 Jared Wray
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/packages/tiered/README.md b/packages/tiered/README.md
deleted file mode 100644
index a1fd5575a..000000000
--- a/packages/tiered/README.md
+++ /dev/null
@@ -1,74 +0,0 @@
-# @keyv/tiered [](https://github.com/jaredwra/keyv)
-
-> Tiered storage adapter for Keyv to manage local and remote store as one for Keyv
-
-[![build](https://github.com/jaredwray/keyv/actions/workflows/tests.yaml/badge.svg)](https://github.com/jaredwray/keyv/actions/workflows/tests.yaml)
-[![codecov](https://codecov.io/gh/jaredwray/keyv/branch/main/graph/badge.svg?token=bRzR3RyOXZ)](https://codecov.io/gh/jaredwray/keyv)
-[![npm](https://img.shields.io/npm/v/@keyv/tiered.svg)](https://www.npmjs.com/package/@keyv/tiered)
-[![npm](https://img.shields.io/npm/dm/@keyv/tiered)](https://npmjs.com/package/@keyv/tiered)
-
-# Feature is Deprecated
-
-This feature is deprecated and will be removed in 2025 as it is no longer needed.
-
-`offline` and `tiered` mode for caching is built into the core [Cacheable](https://cacheable.org) library which uses Keyv under the hood. Please use the `Cacheable` library for `offline` and `tiered` caching.
-
-## Install
-
-```shell
-npm install --save keyv @keyv/tiered
-```
-
-## Usage
-
-First, you need to provide your `local` and `remote` stores to be used, being possible to use any [Keyv storage adapter](https://github.com/jaredwray/keyv#storage-adapters):
-
-```js
-import Keyv from 'keyv';
-import KeyvTiered from '@keyv/tiered';
-import KeyvSqlite from '@keyv/sqlite';
-
-const remoteStore = () => new Keyv({
- store: new KeyvSqlite({
- uri: 'sqlite://test/testdb.sqlite',
- busyTimeout: 30_000,
- }),
-});
-const localStore = () => new Keyv();
-const remote = remoteStore();
-const local = localStore();
-const store = new KeyvTiered({remote, local});
-const keyv = new Keyv({store});
-keyv.on('error', handleConnectionError);
-```
-
-## API
-
-### KeyvTiered(\[options])
-
-#### options
-
-##### local
-
-Type: `Object`
-Default: `new Keyv()`
-
-A keyv instance to be used as local strategy.
-
-##### remote
-
-Type: `Object`
-Default: `new Keyv()`
-
-A keyv instance to be used as remote strategy.
-
-##### validator
-
-Type: `Function`
-Default: `() => true`
-
-The validator function is used as a precondition to determining is remote storage should be checked.
-
-## License
-
-[MIT © Jared Wray](LISCENCE)
\ No newline at end of file
diff --git a/packages/tiered/package.json b/packages/tiered/package.json
deleted file mode 100644
index 96bf2053b..000000000
--- a/packages/tiered/package.json
+++ /dev/null
@@ -1,78 +0,0 @@
-{
- "name": "@keyv/tiered",
- "version": "2.0.2",
- "description": "Tiered storage adapter for Keyv",
- "type": "module",
- "main": "dist/index.cjs",
- "module": "dist/index.js",
- "types": "dist/index.d.ts",
- "exports": {
- ".": {
- "require": "./dist/index.cjs",
- "import": "./dist/index.js"
- }
- },
- "scripts": {
- "build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
- "prepare": "pnpm build",
- "test": "xo --fix && vitest run --coverage",
- "test:ci": "xo && vitest --run --sequence.setupFiles=list",
- "clean": "rimraf ./node_modules ./coverage ./test/testdb.sqlite ./dist"
- },
- "xo": {
- "rules": {
- "import/no-named-as-default": "off",
- "unicorn/prefer-module": "off",
- "unicorn/prefer-event-target": "off",
- "n/file-extension-in-import": "off",
- "import/extensions": "off",
- "import/no-extraneous-dependencies": "off",
- "@typescript-eslint/no-unsafe-assignment": "off",
- "@typescript-eslint/no-unsafe-call": "off",
- "@typescript-eslint/no-unnecessary-type-arguments": "off"
- }
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/jaredwray/keyv.git"
- },
- "keywords": [
- "tiered",
- "mulit",
- "keyv",
- "storage",
- "adapter",
- "key",
- "value",
- "store",
- "cache",
- "ttl"
- ],
- "author": "Jared Wray (http://jaredwray.com)",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/jaredwray/keyv/issues"
- },
- "homepage": "https://github.com/jaredwray/keyv",
- "devDependencies": {
- "@keyv/sqlite": "*",
- "@keyv/test-suite": "*",
- "c8": "^10.1.2",
- "eslint": "^9.12.0",
- "keyv": "^5.0.3",
- "rimraf": "^6.0.1",
- "tsd": "^0.31.2",
- "typescript": "^5.6.2",
- "xo": "^0.59.3"
- },
- "tsd": {
- "directory": "test"
- },
- "engines": {
- "node": ">= 18"
- },
- "files": [
- "dist",
- "LICENSE"
- ]
-}
diff --git a/packages/tiered/src/index.ts b/packages/tiered/src/index.ts
deleted file mode 100644
index b2052146d..000000000
--- a/packages/tiered/src/index.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-import EventEmitter from 'node:events';
-import Keyv from 'keyv';
-import type {Options, Options_} from './types';
-
-type KeyvTieredIndex = 'local' | 'remote';
-
-export class KeyvTiered extends EventEmitter {
- opts: Options_;
- remote: Keyv;
- local: Keyv;
- iterationLimit?: string | number;
-
- constructor({remote = new Keyv(), local = new Keyv(), ...options}: Options) {
- super();
- this.opts = {
- validator: () => true,
- dialect: 'tiered',
- ...options,
- };
- this.remote = remote;
- this.local = local;
- }
-
- async get(key: string): Promise {
- const localResult: unknown = await this.local.get(key);
-
- if (localResult === undefined || !this.opts.validator(localResult, key)) {
- const remoteResult: unknown = await this.remote.get(key);
-
- if (remoteResult === localResult) {
- return remoteResult;
- }
-
- await this.local.set(key, remoteResult);
-
- return remoteResult;
- }
-
- return localResult;
- }
-
- async getMany(keys: string[]): Promise {
- const promises = [];
- for (const key of keys) {
- promises.push(this.get(key));
- }
-
- const values = await Promise.all(promises);
- const data: unknown[] = [];
- for (const value of values) {
- data.push(value);
- }
-
- return data;
- }
-
- async set(key: string, value: any, ttl?: number) {
- const toSet: KeyvTieredIndex[] = ['local', 'remote'];
- return Promise.all(toSet.map(async store => this[store].set(key, value, ttl)),
- );
- }
-
- async clear(): Promise {
- const toClear: KeyvTieredIndex[] = ['local'];
- if (!this.opts.localOnly) {
- toClear.push('remote');
- }
-
- await Promise.all(toClear
- .map(async store => this[store].clear()),
- );
-
- return undefined;
- }
-
- async delete(key: string): Promise {
- const toDelete: KeyvTieredIndex[] = ['local'];
- if (!this.opts.localOnly) {
- toDelete.push('remote');
- }
-
- const deleted = await Promise.all(toDelete
- .map(async store => this[store].delete(key)),
- );
-
- return deleted.every(Boolean);
- }
-
- async deleteMany(keys: string[]): Promise {
- const promises = [];
- for (const key of keys) {
- promises.push(this.delete(key));
- }
-
- const values = await Promise.all(promises);
-
- return values.every(Boolean);
- }
-
- async has(key: string): Promise {
- const response = await this.local.has(key);
-
- if (!response || !this.opts.validator(response, key)) {
- return this.remote.has(key);
- }
-
- return response;
- }
-
- async * iterator(namespace?: string): AsyncGenerator {
- // @ts-expect-error - iterationLimit doesn't exist on Keyv
- this.remote.opts.iterationLimit = Number.parseInt(this.iterationLimit as string, 10) || 10;
- for await (const entries of this.remote.iterator!(namespace)) {
- yield entries;
- }
- }
-}
-
-export default KeyvTiered;
diff --git a/packages/tiered/src/types.ts b/packages/tiered/src/types.ts
deleted file mode 100644
index f09ae1505..000000000
--- a/packages/tiered/src/types.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import type Keyv from 'keyv';
-
-export type Options = {
- local: Keyv;
- remote: Keyv;
- localOnly?: boolean;
- iterationLimit?: number | string;
-};
-
-// eslint-disable-next-line @typescript-eslint/naming-convention
-export type Options_ = {
- validator: (value: any, key: string) => boolean;
- dialect: string;
- iterationLimit?: number | string;
- localOnly?: boolean;
-};
diff --git a/packages/tiered/test/test.ts b/packages/tiered/test/test.ts
deleted file mode 100644
index 047a9fb5b..000000000
--- a/packages/tiered/test/test.ts
+++ /dev/null
@@ -1,206 +0,0 @@
-import * as test from 'vitest';
-import Keyv from 'keyv';
-import KeyvSqlite from '@keyv/sqlite';
-import keyvTestSuite, {delay, keyvIteratorTests} from '@keyv/test-suite';
-import KeyvTiered from '../src/index';
-
-const remoteStore = () => new Keyv({
- store: new KeyvSqlite({
- uri: 'sqlite://test/testdb.sqlite',
- busyTimeout: 30_000,
- }),
-});
-
-const localStore = () => new Keyv();
-const store = () => new KeyvTiered({remote: remoteStore(), local: localStore()});
-
-// @ts-expect-error - Store
-keyvTestSuite(test, Keyv, store);
-
-// @ts-expect-error - Store
-keyvIteratorTests(test, Keyv, store);
-
-test.beforeEach(async () => {
- const remote = remoteStore();
- const local = localStore();
- const store = new KeyvTiered({remote, local});
- await store.clear();
-});
-
-test.it('constructor on default', t => {
- // @ts-expect-error - KeyvTiered needs constructor options
- const store = new KeyvTiered({});
- t.expect(store.local.opts.store).toBeTruthy();
- t.expect(store.remote.opts.store).toBeTruthy();
-});
-
-test.it('.set() sets to both stores', async t => {
- const remote = remoteStore();
- const local = localStore();
- const store = new KeyvTiered({remote, local});
-
- await store.set('foo', 'bar');
-
- const [remoteResult, localResult, storeResult] = await Promise.all([
- remote.get('foo'),
- store.get('foo'),
- local.get('foo'),
- ]);
- const result = remoteResult === localResult && storeResult === localResult; // Check equality as 'bar' is just a string
- t.expect(result).toBeTruthy();
-});
-
-test.it('.has() returns boolean', async t => {
- const remote = remoteStore();
- const local = localStore();
- const store = new KeyvTiered({remote, local});
-
- await store.set('foo', 'bar');
-
- t.expect(await store.has('foo')).toBeTruthy();
-});
-
-test.it('.has() checks both stores', async t => {
- const remote = remoteStore();
- // @ts-expect-error - KeyvTiered needs local
- const store = new KeyvTiered({remote});
-
- await remote.set('fizz', 'buzz');
-
- t.expect(await store.has('fizz')).toBeTruthy();
-});
-
-test.it('.delete() deletes both stores', async t => {
- const remote = remoteStore();
- const local = localStore();
- const store = new KeyvTiered({remote, local});
-
- await store.set('fizz', 'buzz');
- await store.delete('fizz');
-
- t.expect(await store.get('fizz')).toBeUndefined();
- t.expect(await local.get('fizz')).toBeUndefined();
- t.expect(await remote.get('fizz')).toBeUndefined();
-});
-
-test.it('.deleteMany() deletes both stores', async t => {
- const remote = remoteStore();
- const local = localStore();
- const store = new KeyvTiered({remote, local});
-
- await store.set('fizz', 'buzz');
- await store.set('fizz1', 'buzz1');
- const value = await store.deleteMany(['fizz', 'fizz1']);
-
- t.expect(value).toBeTruthy();
- t.expect(await store.get('fizz')).toBeUndefined();
- t.expect(await local.get('fizz')).toBeUndefined();
- t.expect(await remote.get('fizz')).toBeUndefined();
- t.expect(await store.get('fizz1')).toBeUndefined();
- t.expect(await local.get('fizz1')).toBeUndefined();
- t.expect(await remote.get('fizz1')).toBeUndefined();
-});
-
-test.it('.getMany() deletes both stores', async t => {
- const remote = remoteStore();
- const local = localStore();
- const store = new KeyvTiered({remote, local});
-
- await store.set('fizz', 'buzz');
- await store.set('fizz1', 'buzz1');
- let value = await store.getMany(['fizz', 'fizz1']);
- t.expect(value).toStrictEqual(['buzz', 'buzz1']);
-
- value = await store.getMany(['fizz3', 'fizz4']);
- t.expect(value).toStrictEqual([undefined, undefined]);
-});
-
-test.it(
- '.delete({ localOnly: true }) deletes only local store',
- async t => {
- const remote = remoteStore();
- const local = localStore();
- const store = new KeyvTiered({remote, local, localOnly: true});
-
- await store.set('fizz', 'buzz');
- await store.delete('fizz');
-
- t.expect(await local.get('fizz')).toBeUndefined();
- t.expect(await remote.get('fizz')).toBeTruthy();
- },
-);
-
-test.it('.clear() clears both stores', async t => {
- const remote = remoteStore();
- const local = localStore();
- const store = new KeyvTiered({remote, local});
-
- await store.set('fizz', 'buzz');
- await store.clear();
-
- t.expect(await store.get('fizz')).toBeUndefined();
-});
-
-test.it('.clear({ localOnly: true }) clears local store alone', async t => {
- const remote = remoteStore();
- const local = localStore();
- const store = new KeyvTiered({remote, local, localOnly: true});
-
- await store.set('fizz', 'buzz');
- await store.clear();
-
- t.expect(await local.get('fizz')).toBeUndefined();
- t.expect(await remote.get('fizz')).toBeTruthy();
-});
-
-test.it('ttl is valid', async t => {
- const remote = remoteStore();
- const local = new Keyv({ttl: 100}); // Set local ttl
- const store = new KeyvTiered({remote, local});
-
- await store.set('foo', 'bar');
- await remote.set('foo', 'notbar');
-
- await delay(2000);
- t.expect(await store.get('foo')).toBe('notbar');
-});
-
-test.it('copy locally when is possible', async t => {
- const remote = remoteStore();
- const local = new Keyv();
- const store = new KeyvTiered({remote, local});
-
- await remote.set('foo', 'bar');
-
- t.expect(await store.get('foo')).toBe('bar');
- t.expect(await local.get('foo')).toBe('bar');
-});
-
-test.it('custom validator', async t => {
- const remote = remoteStore();
- const local = new Keyv();
- const store = new KeyvTiered({
- remote,
- local,
- // @ts-expect-error - Validator not need params
- validator(value: {timeSensitiveData: any}) {
- if (value.timeSensitiveData) {
- return false;
- } // Fetch from remote store only
-
- return true;
- },
- });
-
- await store.set('1', {timeSensitiveData: 'bar'});
- await store.set('2', {timeSensitiveData: false});
-
- t.expect(await store.get('1')).toStrictEqual({timeSensitiveData: 'bar'}); // Fetched from remote
- t.expect(await store.get('2')).toStrictEqual({timeSensitiveData: false});
-
- await remote.set('1', {timeSensitiveData: 'foo1'});
- await remote.set('2', {timeSensitiveData: 'foo2'}); // Set to remote so local has not been updated
-
- t.expect(await store.get('1')).toStrictEqual({timeSensitiveData: 'foo1'});
- t.expect(await store.get('2')).toStrictEqual({timeSensitiveData: false});
-});
diff --git a/packages/tiered/tsconfig.json b/packages/tiered/tsconfig.json
deleted file mode 100644
index 7e9400d2a..000000000
--- a/packages/tiered/tsconfig.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "compilerOptions": {
- "target": "ESNext",
- "module": "ESNext",
- "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
- "baseUrl": "./src", /* Specify the base directory to resolve non-relative module names. */
-
- /* Emit */
- "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
- "sourceMap": true, /* Create source map files for emitted JavaScript files. */
- "outDir": "./dist", /* Specify an output folder for all emitted files. */
-
- /* Interop Constraints */
- "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
- "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
-
- /* Type Checking */
- "strict": true, /* Enable all strict type-checking options. */
-
- /* Completeness */
- "skipLibCheck": true, /* Skip type checking all .d.ts files. */
- "lib": [
- "ESNext", "DOM"
- ]
- }
-}
diff --git a/packages/tiered/vitest.config.ts b/packages/tiered/vitest.config.ts
deleted file mode 100644
index 1ee8dcc07..000000000
--- a/packages/tiered/vitest.config.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import {defineConfig, mergeConfig} from 'vitest/config';
-import vitestConfig from '../../vitest.general.config';
-
-export default mergeConfig(vitestConfig, defineConfig({}));
diff --git a/packages/website/src/docs.ts b/packages/website/src/docs.ts
index fc96b71c1..dd9eab018 100644
--- a/packages/website/src/docs.ts
+++ b/packages/website/src/docs.ts
@@ -69,7 +69,7 @@ async function copyCompressionDocs() {
}
function cleanDocumentFromImage(document: string) {
- document = document.replace(`[](https://github.com/jaredwra/keyv)`, "");
+ document = document.replace(``, "");
document = document.replace(`[](https://github.com/jaredwra/keyv)`, "");
document = document.replace(`[](https://github.com/jaredwra/keyv)`, "");
return document;