polystore 0.9.3 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/home.html +4 -2
- package/package.json +15 -4
- package/readme.md +46 -21
- package/src/index.d.ts +167 -7
- package/src/index.js +46 -29
- package/src/test/setup.js +12 -8
package/assets/home.html
CHANGED
|
@@ -77,7 +77,8 @@ console.log(await store.get(key));
|
|
|
77
77
|
<a href="/documentation#getting-started">Getting started</a>,
|
|
78
78
|
<a href="/documentation#api">API</a>,
|
|
79
79
|
<a href="/documentation#clients">Clients</a> and
|
|
80
|
-
<a href="/documentation#
|
|
80
|
+
<a href="/documentation#creating-a-store">custom stores</a> for your
|
|
81
|
+
convenience.
|
|
81
82
|
</p>
|
|
82
83
|
</div>
|
|
83
84
|
</div>
|
|
@@ -152,7 +153,7 @@ console.log(await store.get(key));
|
|
|
152
153
|
<p>
|
|
153
154
|
At
|
|
154
155
|
<a href="https://bundlephobia.com/package/polystore" target="_blank"
|
|
155
|
-
>just <strong>
|
|
156
|
+
>just <strong>3kb</strong></a
|
|
156
157
|
>
|
|
157
158
|
(min+gzip), the impact on your app loading time is minimal.
|
|
158
159
|
</p>
|
|
@@ -180,6 +181,7 @@ console.log(await store.get(key));
|
|
|
180
181
|
<h3>Intuitive expirations</h3>
|
|
181
182
|
</header>
|
|
182
183
|
<p>Write the expiration as <code>100s</code>, <code>1week</code>, etc.</p>
|
|
184
|
+
and forget time-related bugs.
|
|
183
185
|
</div>
|
|
184
186
|
</div>
|
|
185
187
|
</section>
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polystore",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "A small compatibility layer for many popular KV stores like localStorage, Redis, FileSystem, etc.",
|
|
5
|
-
"homepage": "https://
|
|
5
|
+
"homepage": "https://polystore.dev/",
|
|
6
6
|
"repository": "https://github.com/franciscop/polystore.git",
|
|
7
7
|
"bugs": "https://github.com/franciscop/polystore/issues",
|
|
8
8
|
"funding": "https://www.paypal.me/franciscopresencia/19",
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
],
|
|
26
26
|
"license": "MIT",
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"
|
|
28
|
+
"@deno/kv": "^0.8.1",
|
|
29
|
+
"check-dts": "^0.8.0",
|
|
29
30
|
"dotenv": "^16.3.1",
|
|
30
31
|
"edge-mock": "^0.0.15",
|
|
31
|
-
"esbuild": "^0.19.4",
|
|
32
32
|
"etcd3": "^1.1.2",
|
|
33
33
|
"jest": "^29.7.0",
|
|
34
34
|
"jest-environment-jsdom": "^29.7.0",
|
|
@@ -36,6 +36,17 @@
|
|
|
36
36
|
"localforage": "^1.10.0",
|
|
37
37
|
"redis": "^4.6.10"
|
|
38
38
|
},
|
|
39
|
+
"documentation": {
|
|
40
|
+
"title": "🏬 Polystore - A universal library for standardizing any KV-store",
|
|
41
|
+
"home": "assets/home.html",
|
|
42
|
+
"homepage": "https://polystore.dev/",
|
|
43
|
+
"menu": {
|
|
44
|
+
"Documentation": "/documentation",
|
|
45
|
+
"Issues": "https://github.com/franciscop/polystore/issues",
|
|
46
|
+
"Get help": "https://superpeer.com/francisco/-/javascript-and-react-help",
|
|
47
|
+
"Github": "https://github.com/franciscop/polystore"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
39
50
|
"jest": {
|
|
40
51
|
"testEnvironment": "jsdom",
|
|
41
52
|
"setupFiles": [
|
package/readme.md
CHANGED
|
@@ -36,13 +36,13 @@ Available clients for the KV store:
|
|
|
36
36
|
- [**File** `new URL('file:///...')`](#file) (be): store the data in a single JSON file in your FS
|
|
37
37
|
- [**Redis Client** `redisClient`](#redis-client) (be): use the Redis instance that you connect to
|
|
38
38
|
- [**Cloudflare KV** `env.KV_NAMESPACE`](#cloudflare-kv) (be): use Cloudflare's KV store
|
|
39
|
-
- [**Level** `new Level('example', { valueEncoding: 'json' })`](#level): support the whole Level ecosystem
|
|
40
|
-
- [**Etcd** `new Etcd3()`](#etcd): the Microsoft's high performance KV store.
|
|
39
|
+
- [**Level** `new Level('example', { valueEncoding: 'json' })`](#level) (fe+be): support the whole Level ecosystem
|
|
40
|
+
- [**Etcd** `new Etcd3()`](#etcd) (be): the Microsoft's high performance KV store.
|
|
41
41
|
- [**_Custom_** `{}`](#creating-a-store) (?): create your own store with just 3 methods!
|
|
42
42
|
|
|
43
43
|
> This library should be as performant as the client you use with the item methods (GET/SET/ADD/HAS/DEL). For other and advanced cases, see [the performance considerations](#performance) and read the docs on your client.
|
|
44
44
|
|
|
45
|
-
I made this library to be used as a "building block" of other libraries, so that _your library_ can accept many cache stores effortlessly! It's isomorphic (Node.js and the Browser) and tiny (~2KB). For example, let's say you create an API library, then you can accept the stores from your client:
|
|
45
|
+
I made this library to be used as a "building block" of other libraries, so that _your library_ can accept many cache stores effortlessly! It's isomorphic (Node.js, Bun and the Browser) and tiny (~2KB). For example, let's say you create an API library, then you can accept the stores from your client:
|
|
46
46
|
|
|
47
47
|
```js
|
|
48
48
|
import MyApi from "my-api";
|
|
@@ -54,6 +54,38 @@ MyApi({ cache: env.KV_NAMESPACE }); // OR
|
|
|
54
54
|
// ...
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
## Getting started
|
|
58
|
+
|
|
59
|
+
First, install `polystore` and whatever [supported client](#clients) that you prefer. Let's see Redis as an example here:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
npm i polystore redis
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Then import both, initialize the Redis client and pass it to Polystore:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
import kv from "polystore";
|
|
69
|
+
import { createClient } from "redis";
|
|
70
|
+
|
|
71
|
+
// Import the Redis configuration
|
|
72
|
+
const REDIS = process.env.REDIS_URL;
|
|
73
|
+
|
|
74
|
+
// Wrap the redis creation with Polystore (kv())
|
|
75
|
+
const store = kv(createClient(REDIS).connect());
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Now your store is ready to use! Add, set, get, del different keys. [See full API](#api).
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
const key = await store.add("Hello");
|
|
82
|
+
|
|
83
|
+
console.log(await store.get(key));
|
|
84
|
+
// Hello
|
|
85
|
+
|
|
86
|
+
await store.del(key);
|
|
87
|
+
```
|
|
88
|
+
|
|
57
89
|
## API
|
|
58
90
|
|
|
59
91
|
See how to initialize each store [in the Clients list documentation](#clients). But basically for every store, it's like this:
|
|
@@ -79,7 +111,7 @@ client.connect();
|
|
|
79
111
|
const store = kv(client);
|
|
80
112
|
```
|
|
81
113
|
|
|
82
|
-
While you can keep a reference to the store and access it directly, we strongly recommend if you are going to use a store, to only access it through `polystore`, since we
|
|
114
|
+
While you can keep a reference to the store and access it directly, we strongly recommend if you are going to use a store, to only access it through `polystore`, since we might add custom serialization and extra properties for e.g. expiration time:
|
|
83
115
|
|
|
84
116
|
```js
|
|
85
117
|
const map = new Map();
|
|
@@ -515,19 +547,19 @@ Please see the [creating a store](#creating-a-store) section for more details!
|
|
|
515
547
|
|
|
516
548
|
## Performance
|
|
517
549
|
|
|
518
|
-
> TL;DR: if you only use the item operations (add,set,get,has,del) and your
|
|
550
|
+
> TL;DR: if you only use the item operations (add,set,get,has,del) and your client supports expiration natively, you have nothing to worry about!
|
|
519
551
|
|
|
520
552
|
While all of our stores support `expires`, `.prefix()` and group operations, the nature of those makes them to have different performance characteristics.
|
|
521
553
|
|
|
522
|
-
**Expires** we polyfill expiration when the underlying library does not support it. The impact on read/write operations and on data size of each key should be minimal. However, it can have a big impact in storage size, since the expired keys are not evicted automatically. Note that when attempting to read an expired key, polystore **will delete that key**. However, if an expired key is never read, it would remain in the datastore and could create some old-data issues. This is **especially important where sensitive data is involved**! To fix this, the easiest way is calling `await store.entries();` on a cron job and that should evict all of the old keys (this operation is O(n) though, so not suitable for calling it on EVERY API call, see the next point).
|
|
554
|
+
**Expires** we polyfill expiration when the underlying client library does not support it. The impact on read/write operations and on data size of each key should be minimal. However, it can have a big impact in storage size, since the expired keys are not evicted automatically. Note that when attempting to read an expired key, polystore **will delete that key**. However, if an expired key is never read, it would remain in the datastore and could create some old-data issues. This is **especially important where sensitive data is involved**! To fix this, the easiest way is calling `await store.entries();` on a cron job and that should evict all of the old keys (this operation is O(n) though, so not suitable for calling it on EVERY API call, see the next point).
|
|
523
555
|
|
|
524
|
-
**Group operations** these are there mostly for small datasets only, for one-off scripts or for dev purposes, since by their own nature they can _never_ be high performance. But this is normal if you think about traditional DBs, reading a single record by its ID is O(1), while reading all of the IDs in the DB into an array is going to be O(n). Same applies with polystore.
|
|
556
|
+
**Group operations** these are there mostly for small datasets only, for one-off scripts or for dev purposes, since by their own nature they can _never_ be high performance in the general case. But this is normal if you think about traditional DBs, reading a single record by its ID is O(1), while reading all of the IDs in the DB into an array is going to be O(n). Same applies with polystore.
|
|
525
557
|
|
|
526
558
|
**Substores** when dealing with a `.prefix()` substore, the same applies. Item operations should see no performance degradation from `.prefix()`, but group operations follow the above performance considerations. Some engines might have native prefix support, so performance in those is better for group operations in a substore than the whole store. But in general you should consider `.prefix()` as a convenient way of classifying your keys and not as a performance fix for group operations.
|
|
527
559
|
|
|
528
560
|
## Expires
|
|
529
561
|
|
|
530
|
-
> Warning: if a client doesn't support expiration natively, we will hide expired keys on the API calls for a nice DX, but _old data might not be evicted automatically_
|
|
562
|
+
> Warning: if a client doesn't support expiration natively, we will hide expired keys on the API calls for a nice DX, but _old data might not be evicted automatically_. See [the notes in Performance](#performance) for details on how to work around this.
|
|
531
563
|
|
|
532
564
|
We unify all of the clients diverse expiration methods into a single, easy one with `expires`:
|
|
533
565
|
|
|
@@ -572,7 +604,7 @@ For these and more situations, you can use `.prefix()` to simplify your life fur
|
|
|
572
604
|
|
|
573
605
|
## Creating a store
|
|
574
606
|
|
|
575
|
-
To create a store, you define a class with these methods:
|
|
607
|
+
To create a store, you define a class with these properties and methods:
|
|
576
608
|
|
|
577
609
|
```js
|
|
578
610
|
class MyClient {
|
|
@@ -580,7 +612,7 @@ class MyClient {
|
|
|
580
612
|
// the `.set()` and `.add()` receive a `expires` that is a `null` or `number`:
|
|
581
613
|
EXPIRES = false;
|
|
582
614
|
|
|
583
|
-
// Mandatory methods
|
|
615
|
+
// Mandatory methods
|
|
584
616
|
get (key): Promise<any>;
|
|
585
617
|
set (key, value, { expires: null|number }): Promise<null>;
|
|
586
618
|
entries (prefix): Promise<[string, any][]>;
|
|
@@ -600,7 +632,7 @@ class MyClient {
|
|
|
600
632
|
}
|
|
601
633
|
```
|
|
602
634
|
|
|
603
|
-
Note that this is NOT the public API, it's the internal **client** API. It's simpler than the public API since we do some of the heavy lifting as an intermediate layer (e.g. the `expires` will always be a `null` or `number`, never `undefined` or a `string`), but also it differs from polystore's API, like `.add()` has a different signature, and the group methods all take a explicit prefix.
|
|
635
|
+
Note that this is NOT the public API, it's the internal **client** API. It's simpler than the public API since we do some of the heavy lifting as an intermediate layer (e.g. for the client, the `expires` will always be a `null` or `number`, never `undefined` or a `string`), but also it differs from polystore's public API, like `.add()` has a different signature, and the group methods all take a explicit prefix.
|
|
604
636
|
|
|
605
637
|
**Expires**: if you set the `EXPIRES = true`, then you are indicating that the client WILL manage the lifecycle of the data. This includes all methods, for example if an item is expired, then its key should not be returned in `.keys()`, it's value should not be returned in `.values()`, and the method `.has()` will return `false`. The good news is that you will always receive the option `expires`, which is either `null` (no expiration) or a `number` indicating the time when it will expire.
|
|
606
638
|
|
|
@@ -619,22 +651,15 @@ const value = await store.entries();
|
|
|
619
651
|
// client.entries("hello:world:");
|
|
620
652
|
```
|
|
621
653
|
|
|
622
|
-
> Note: all of the _group methods_ that return keys, should return them **with the prefix
|
|
654
|
+
> Note: all of the _group methods_ that return keys, should return them **with the prefix**:
|
|
623
655
|
|
|
624
656
|
```js
|
|
625
|
-
// Example if your client works around a simple object {}, we want to remove
|
|
626
|
-
// the `prefix` from the beginning of the keys returned:
|
|
627
657
|
client.keys = (prefix) => {
|
|
628
|
-
return
|
|
629
|
-
|
|
630
|
-
.map((key) => key.slice(prefix.length)); // <= Important!
|
|
658
|
+
// Filter the keys, and return them INCLUDING the prefix!
|
|
659
|
+
return Object.keys(subStore).filter((key) => key.startsWith(prefix));
|
|
631
660
|
};
|
|
632
661
|
```
|
|
633
662
|
|
|
634
|
-
You can and should just concatenate the `key + options.prefix`. We don't do it for two reasons: in some cases, like `.add()`, there's no key that we can use to concatenate, and also you might
|
|
635
|
-
|
|
636
|
-
For example, if the user of `polystore` does `kv(client).prefix('hello:').get('a')`, your store will be directly called with `client.get('a', { prefix: 'hello:' })`. You can safely concatenate `options.prefix + key` since this library always ensures that the prefix is defined and defaults to `''`. We don't concatenate it interally because in some cases (like in `.add()`) it makes more sense that this is handled by the client as an optimization.
|
|
637
|
-
|
|
638
663
|
While the signatures are different, you can check each entries on the output of Polystore API to see what is expected for the methods of the client to do, e.g. `.clear()` will remove all of the items that match the prefix (or everything if there's no prefix).
|
|
639
664
|
|
|
640
665
|
**Example: Plain Object client**
|
package/src/index.d.ts
CHANGED
|
@@ -1,21 +1,181 @@
|
|
|
1
1
|
type Options = { expires?: number | string | null };
|
|
2
2
|
type Value = null | string | { [key: string]: Value } | Value[];
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
interface Store {
|
|
5
|
+
/**
|
|
6
|
+
* Save the data on an autogenerated key, can add expiration as well:
|
|
7
|
+
*
|
|
8
|
+
* ```js
|
|
9
|
+
* const key1 = await store.add("value1");
|
|
10
|
+
* const key2 = await store.add({ hello: "world" });
|
|
11
|
+
* const key3 = await store.add("value3", { expires: "1h" });
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* **[→ Full .add() Docs](https://polystore.dev/documentation#add)**
|
|
15
|
+
*/
|
|
16
|
+
add: (value: Value, options?: Options) => Promise<string>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Save the data on the given key, can add expiration as well:
|
|
20
|
+
*
|
|
21
|
+
* ```js
|
|
22
|
+
* const key = await store.set("key1", "value1");
|
|
23
|
+
* await store.set("key2", { hello: "world" });
|
|
24
|
+
* await store.set("key3", "value3", { expires: "1h" });
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* **[→ Full .set() Docs](https://polystore.dev/documentation#set)**
|
|
28
|
+
*/
|
|
29
|
+
set: (key: string, value: Value, options?: Options) => Promise<string>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Read a single value from the KV store:
|
|
33
|
+
*
|
|
34
|
+
* ```js
|
|
35
|
+
* const value1 = await store.get("key1");
|
|
36
|
+
* // null (doesn't exist or has expired)
|
|
37
|
+
* const value2 = await store.get("key2");
|
|
38
|
+
* // "value2"
|
|
39
|
+
* const value3 = await store.get("key3");
|
|
40
|
+
* // { hello: "world" }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* **[→ Full .get() Docs](https://polystore.dev/documentation#get)**
|
|
44
|
+
*/
|
|
5
45
|
get: (key: string) => Promise<Value>;
|
|
6
|
-
|
|
7
|
-
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check whether a key exists or not:
|
|
49
|
+
*
|
|
50
|
+
* ```js
|
|
51
|
+
* if (await store.has("key1")) { ... }
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* If you are going to use the value, it's better to just read it:
|
|
55
|
+
*
|
|
56
|
+
* ```js
|
|
57
|
+
* const val = await store.get("key1");
|
|
58
|
+
* if (val) { ... }
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
*
|
|
62
|
+
* **[→ Full .has() Docs](https://polystore.dev/documentation#has)**
|
|
63
|
+
*/
|
|
8
64
|
has: (key: string) => Promise<boolean>;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Remove a single key and its value from the store:
|
|
68
|
+
*
|
|
69
|
+
* ```js
|
|
70
|
+
* const key = await store.del("key1");
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* **[→ Full .del() Docs](https://polystore.dev/documentation#del)**
|
|
74
|
+
*/
|
|
9
75
|
del: (key: string) => Promise<null>;
|
|
10
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Return an array of the entries, in the [key, value] format:
|
|
79
|
+
*
|
|
80
|
+
* ```js
|
|
81
|
+
* const entries = await store.entries();
|
|
82
|
+
* // [["key1", "value1"], ["key2", { hello: "world" }], ...]
|
|
83
|
+
*
|
|
84
|
+
* // To limit it to a given prefix, use `.prefix()`:
|
|
85
|
+
* const sessions = await store.prefix("session:").entries();
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* **[→ Full .entries() Docs](https://polystore.dev/documentation#entries)**
|
|
89
|
+
*/
|
|
90
|
+
entries: () => Promise<[key: string, value: Value][]>;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Return an array of the keys in the store:
|
|
94
|
+
*
|
|
95
|
+
* ```js
|
|
96
|
+
* const keys = await store.keys();
|
|
97
|
+
* // ["key1", "key2", ...]
|
|
98
|
+
*
|
|
99
|
+
* // To limit it to a given prefix, use `.prefix()`:
|
|
100
|
+
* const sessions = await store.prefix("session:").keys();
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* **[→ Full .keys() Docs](https://polystore.dev/documentation#keys)**
|
|
104
|
+
*/
|
|
11
105
|
keys: () => Promise<string[]>;
|
|
12
|
-
values: () => Promise<any[]>;
|
|
13
|
-
entries: () => Promise<[key: string, value: any][]>;
|
|
14
106
|
|
|
15
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Return an array of the values in the store:
|
|
109
|
+
*
|
|
110
|
+
* ```js
|
|
111
|
+
* const values = await store.values();
|
|
112
|
+
* // ["value1", { hello: "world" }, ...]
|
|
113
|
+
*
|
|
114
|
+
* // To limit it to a given prefix, use `.prefix()`:
|
|
115
|
+
* const sessions = await store.prefix("session:").values();
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* **[→ Full .values() Docs](https://polystore.dev/documentation#values)**
|
|
119
|
+
*/
|
|
120
|
+
values: () => Promise<Value[]>;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Return an object with the keys:values in the store:
|
|
124
|
+
*
|
|
125
|
+
* ```js
|
|
126
|
+
* const obj = await store.all();
|
|
127
|
+
* // { key1: "value1", key2: { hello: "world" }, ... }
|
|
128
|
+
*
|
|
129
|
+
* // To limit it to a given prefix, use `.prefix()`:
|
|
130
|
+
* const sessions = await store.prefix("session:").all();
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
133
|
+
* **[→ Full .all() Docs](https://polystore.dev/documentation#all)**
|
|
134
|
+
*/
|
|
135
|
+
all: () => Promise<{ [key: string]: Value }>;
|
|
16
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Delete all of the records of the store:
|
|
139
|
+
*
|
|
140
|
+
* ```js
|
|
141
|
+
* await store.clear();
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* It's useful for cache invalidation, clearing the data, and testing.
|
|
145
|
+
*
|
|
146
|
+
* **[→ Full .clear() Docs](https://polystore.dev/documentation#clear)**
|
|
147
|
+
*/
|
|
17
148
|
clear: () => Promise<null>;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Create a substore where all the keys are stored with
|
|
152
|
+
* the given prefix:
|
|
153
|
+
*
|
|
154
|
+
* ```js
|
|
155
|
+
* const session = store.prefix("session:");
|
|
156
|
+
* await session.set("key1", "value1");
|
|
157
|
+
* console.log(await session.entries()); // session.
|
|
158
|
+
* // [["key1", "value1"]]
|
|
159
|
+
* console.log(await store.entries()); // store.
|
|
160
|
+
* // [["session:key1", "value1"]]
|
|
161
|
+
* ```
|
|
162
|
+
*
|
|
163
|
+
* **[→ Full .prefix() Docs](https://polystore.dev/documentation#prefix)**
|
|
164
|
+
*/
|
|
165
|
+
prefix: (prefix: string) => Store;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Stop the connection to the store, if any:
|
|
169
|
+
*
|
|
170
|
+
* ```js
|
|
171
|
+
* await session.set("key1", "value1");
|
|
172
|
+
* await store.close();
|
|
173
|
+
* await session.set("key2", "value2"); // error
|
|
174
|
+
* ```
|
|
175
|
+
*
|
|
176
|
+
* **[→ Full .close() Docs](https://polystore.dev/documentation#close)**
|
|
177
|
+
*/
|
|
18
178
|
close?: () => Promise<null>;
|
|
19
|
-
}
|
|
179
|
+
}
|
|
20
180
|
|
|
21
181
|
export default function (store?: any): Store;
|
package/src/index.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A number, or a string containing a number.
|
|
3
|
+
* @typedef {(number|string|object|array)} Value
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
import clients from "./clients/index.js";
|
|
2
7
|
import { createId, isClass, parse } from "./utils.js";
|
|
3
8
|
|
|
@@ -151,7 +156,7 @@ class Store {
|
|
|
151
156
|
*
|
|
152
157
|
* ```js
|
|
153
158
|
* const value1 = await store.get("key1");
|
|
154
|
-
* // null (
|
|
159
|
+
* // null (doesn't exist or has expired)
|
|
155
160
|
* const value2 = await store.get("key2");
|
|
156
161
|
* // "value2"
|
|
157
162
|
* const value3 = await store.get("key3");
|
|
@@ -302,6 +307,34 @@ class Store {
|
|
|
302
307
|
.map(([key, data]) => [key, data.value]);
|
|
303
308
|
}
|
|
304
309
|
|
|
310
|
+
// #region .keys()
|
|
311
|
+
/**
|
|
312
|
+
* Return an array of the keys in the store:
|
|
313
|
+
*
|
|
314
|
+
* ```js
|
|
315
|
+
* const keys = await store.keys();
|
|
316
|
+
* // ["key1", "key2", ...]
|
|
317
|
+
*
|
|
318
|
+
* // To limit it to a given prefix, use `.prefix()`:
|
|
319
|
+
* const sessions = await store.prefix("session:").keys();
|
|
320
|
+
* ```
|
|
321
|
+
*
|
|
322
|
+
* **[→ Full .keys() Docs](https://polystore.dev/documentation#keys)**
|
|
323
|
+
* @returns {Promise<string[]>}
|
|
324
|
+
*/
|
|
325
|
+
async keys() {
|
|
326
|
+
await this.promise;
|
|
327
|
+
|
|
328
|
+
if (this.client.keys) {
|
|
329
|
+
const list = await this.client.keys(this.PREFIX);
|
|
330
|
+
if (!this.PREFIX) return list;
|
|
331
|
+
return list.map((k) => k.slice(this.PREFIX.length));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const entries = await this.entries();
|
|
335
|
+
return entries.map((e) => e[0]);
|
|
336
|
+
}
|
|
337
|
+
|
|
305
338
|
// #region .values()
|
|
306
339
|
/**
|
|
307
340
|
* Return an array of the values in the store:
|
|
@@ -347,34 +380,6 @@ class Store {
|
|
|
347
380
|
return entries.map((e) => e[1]);
|
|
348
381
|
}
|
|
349
382
|
|
|
350
|
-
// #region .keys()
|
|
351
|
-
/**
|
|
352
|
-
* Return an array of the keys in the store:
|
|
353
|
-
*
|
|
354
|
-
* ```js
|
|
355
|
-
* const keys = await store.keys();
|
|
356
|
-
* // ["key1", "key2", ...]
|
|
357
|
-
*
|
|
358
|
-
* // To limit it to a given prefix, use `.prefix()`:
|
|
359
|
-
* const sessions = await store.prefix("session:").keys();
|
|
360
|
-
* ```
|
|
361
|
-
*
|
|
362
|
-
* **[→ Full .keys() Docs](https://polystore.dev/documentation#keys)**
|
|
363
|
-
* @returns {Promise<string[]>}
|
|
364
|
-
*/
|
|
365
|
-
async keys() {
|
|
366
|
-
await this.promise;
|
|
367
|
-
|
|
368
|
-
if (this.client.keys) {
|
|
369
|
-
const list = await this.client.keys(this.PREFIX);
|
|
370
|
-
if (!this.PREFIX) return list;
|
|
371
|
-
return list.map((k) => k.slice(this.PREFIX.length));
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
const entries = await this.entries();
|
|
375
|
-
return entries.map((e) => e[0]);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
383
|
// #region .all()
|
|
379
384
|
/**
|
|
380
385
|
* Return an object with the keys:values in the store:
|
|
@@ -458,6 +463,18 @@ class Store {
|
|
|
458
463
|
}
|
|
459
464
|
|
|
460
465
|
// #region .close()
|
|
466
|
+
/**
|
|
467
|
+
* Stop the connection to the store, if any:
|
|
468
|
+
*
|
|
469
|
+
* ```js
|
|
470
|
+
* await session.set("key1", "value1");
|
|
471
|
+
* await store.close();
|
|
472
|
+
* await session.set("key2", "value2"); // error
|
|
473
|
+
* ```
|
|
474
|
+
*
|
|
475
|
+
* **[→ Full .close() Docs](https://polystore.dev/documentation#close)**
|
|
476
|
+
* @returns {Store}
|
|
477
|
+
*/
|
|
461
478
|
async close() {
|
|
462
479
|
await this.promise;
|
|
463
480
|
|
package/src/test/setup.js
CHANGED
|
@@ -2,11 +2,15 @@ import * as util from "util";
|
|
|
2
2
|
|
|
3
3
|
// ref: https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
|
|
4
4
|
// ref: https://github.com/jsdom/jsdom/issues/2524
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
if (typeof TextEncoder === "undefined") {
|
|
6
|
+
Object.defineProperty(window, "TextEncoder", {
|
|
7
|
+
writable: true,
|
|
8
|
+
value: util.TextEncoder,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
if (typeof TextDecoder === "undefined") {
|
|
12
|
+
Object.defineProperty(window, "TextDecoder", {
|
|
13
|
+
writable: true,
|
|
14
|
+
value: util.TextDecoder,
|
|
15
|
+
});
|
|
16
|
+
}
|