polystore 0.15.6 → 0.15.7
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/package.json +1 -1
- package/src/clients/api.js +0 -2
- package/src/clients/cloudflare.js +14 -25
- package/src/clients/cookie.js +7 -13
- package/src/clients/etcd.js +9 -23
- package/src/clients/file.js +3 -4
- package/src/clients/folder.js +2 -4
- package/src/clients/forage.js +8 -24
- package/src/clients/level.js +16 -27
- package/src/clients/memory.js +6 -25
- package/src/clients/redis.js +1 -7
- package/src/clients/storage.js +7 -21
- package/src/index.js +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polystore",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.7",
|
|
4
4
|
"description": "A small compatibility layer for many popular KV stores like localStorage, Redis, FileSystem, etc.",
|
|
5
5
|
"homepage": "https://polystore.dev/",
|
|
6
6
|
"repository": "https://github.com/franciscop/polystore.git",
|
package/src/clients/api.js
CHANGED
|
@@ -20,14 +20,12 @@ export default class Api {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
get = (key) => this.client(`/${enc(key)}`);
|
|
23
|
-
|
|
24
23
|
set = (key, value, { expires } = {}) =>
|
|
25
24
|
this.client(
|
|
26
25
|
`/${enc(key)}?expires=${enc(expires || "")}`,
|
|
27
26
|
"PUT",
|
|
28
27
|
JSON.stringify(value),
|
|
29
28
|
);
|
|
30
|
-
|
|
31
29
|
del = (key) => this.client(`/${enc(key)}`, "DELETE");
|
|
32
30
|
|
|
33
31
|
async *iterate(prefix = "") {
|
|
@@ -4,34 +4,28 @@ export default class Cloudflare {
|
|
|
4
4
|
EXPIRES = true;
|
|
5
5
|
|
|
6
6
|
// Check whether the given store is a FILE-type
|
|
7
|
-
static test(client)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
client?.constructor?.name === "EdgeKVNamespace"
|
|
11
|
-
);
|
|
12
|
-
}
|
|
7
|
+
static test = (client) =>
|
|
8
|
+
client?.constructor?.name === "KvNamespace" ||
|
|
9
|
+
client?.constructor?.name === "EdgeKVNamespace";
|
|
13
10
|
|
|
14
11
|
constructor(client) {
|
|
15
12
|
this.client = client;
|
|
16
13
|
}
|
|
17
14
|
|
|
18
|
-
async
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
15
|
+
get = async (key) => {
|
|
16
|
+
const text = await this.client.get(key);
|
|
17
|
+
return text ? JSON.parse(text) : null;
|
|
18
|
+
};
|
|
23
19
|
|
|
24
|
-
|
|
20
|
+
set = (key, value, { expires } = {}) => {
|
|
25
21
|
const expirationTtl = expires ? Math.round(expires) : undefined;
|
|
26
22
|
if (expirationTtl && expirationTtl < 60) {
|
|
27
23
|
throw new Error("Cloudflare's min expiration is '60s'");
|
|
28
24
|
}
|
|
29
25
|
return this.client.put(key, JSON.stringify(value), { expirationTtl });
|
|
30
|
-
}
|
|
26
|
+
};
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
return this.client.delete(key);
|
|
34
|
-
}
|
|
28
|
+
del = (key) => this.client.delete(key);
|
|
35
29
|
|
|
36
30
|
// Since we have pagination, we don't want to get all of the
|
|
37
31
|
// keys at once if we can avoid it
|
|
@@ -50,7 +44,7 @@ export default class Cloudflare {
|
|
|
50
44
|
} while (cursor);
|
|
51
45
|
}
|
|
52
46
|
|
|
53
|
-
async
|
|
47
|
+
keys = async (prefix = "") => {
|
|
54
48
|
const keys = [];
|
|
55
49
|
let cursor;
|
|
56
50
|
do {
|
|
@@ -59,16 +53,11 @@ export default class Cloudflare {
|
|
|
59
53
|
cursor = raw.list_complete ? null : raw.cursor;
|
|
60
54
|
} while (cursor);
|
|
61
55
|
return keys;
|
|
62
|
-
}
|
|
56
|
+
};
|
|
63
57
|
|
|
64
|
-
async
|
|
58
|
+
entries = async (prefix = "") => {
|
|
65
59
|
const keys = await this.keys(prefix);
|
|
66
60
|
const values = await Promise.all(keys.map((k) => this.get(k)));
|
|
67
61
|
return keys.map((k, i) => [k, values[i]]);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async clear(prefix = "") {
|
|
71
|
-
const list = await this.keys(prefix);
|
|
72
|
-
return Promise.all(list.map((k) => this.del(k)));
|
|
73
|
-
}
|
|
62
|
+
};
|
|
74
63
|
}
|
package/src/clients/cookie.js
CHANGED
|
@@ -4,12 +4,10 @@ export default class Cookie {
|
|
|
4
4
|
EXPIRES = true;
|
|
5
5
|
|
|
6
6
|
// Check if this is the right class for the given client
|
|
7
|
-
static test(client)
|
|
8
|
-
return client === "cookie" || client === "cookies";
|
|
9
|
-
}
|
|
7
|
+
static test = (client) => client === "cookie" || client === "cookies";
|
|
10
8
|
|
|
11
9
|
// Group methods
|
|
12
|
-
#read() {
|
|
10
|
+
#read = () => {
|
|
13
11
|
const all = {};
|
|
14
12
|
for (let entry of document.cookie.split(";")) {
|
|
15
13
|
try {
|
|
@@ -22,14 +20,12 @@ export default class Cookie {
|
|
|
22
20
|
}
|
|
23
21
|
}
|
|
24
22
|
return all;
|
|
25
|
-
}
|
|
23
|
+
};
|
|
26
24
|
|
|
27
25
|
// For cookies, an empty value is the same as null, even `""`
|
|
28
|
-
get(key)
|
|
29
|
-
return this.#read()[key] || null;
|
|
30
|
-
}
|
|
26
|
+
get = (key) => this.#read()[key] || null;
|
|
31
27
|
|
|
32
|
-
set(key, data = null, { expires } = {}) {
|
|
28
|
+
set = (key, data = null, { expires } = {}) => {
|
|
33
29
|
// Setting it to null deletes it
|
|
34
30
|
let expireStr = "";
|
|
35
31
|
// NOTE: 0 is already considered here!
|
|
@@ -40,11 +36,9 @@ export default class Cookie {
|
|
|
40
36
|
|
|
41
37
|
const value = encodeURIComponent(JSON.stringify(data || ""));
|
|
42
38
|
document.cookie = encodeURIComponent(key) + "=" + value + expireStr;
|
|
43
|
-
}
|
|
39
|
+
};
|
|
44
40
|
|
|
45
|
-
del(key) {
|
|
46
|
-
this.set(key, "", { expires: -100 });
|
|
47
|
-
}
|
|
41
|
+
del = (key) => this.set(key, "", { expires: -100 });
|
|
48
42
|
|
|
49
43
|
async *iterate(prefix = "") {
|
|
50
44
|
for (let [key, value] of Object.entries(this.#read())) {
|
package/src/clients/etcd.js
CHANGED
|
@@ -1,25 +1,15 @@
|
|
|
1
1
|
// Use a redis client to back up the store
|
|
2
2
|
export default class Etcd {
|
|
3
3
|
// Check if this is the right class for the given client
|
|
4
|
-
static test(client)
|
|
5
|
-
return client?.constructor?.name === "Etcd3";
|
|
6
|
-
}
|
|
4
|
+
static test = (client) => client?.constructor?.name === "Etcd3";
|
|
7
5
|
|
|
8
6
|
constructor(client) {
|
|
9
7
|
this.client = client;
|
|
10
8
|
}
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
async set(key, value) {
|
|
17
|
-
return this.client.put(key).value(JSON.stringify(value));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async del(key) {
|
|
21
|
-
return this.client.delete().key(key).exec();
|
|
22
|
-
}
|
|
10
|
+
get = (key) => this.client.get(key).json();
|
|
11
|
+
set = (key, value) => this.client.put(key).value(JSON.stringify(value));
|
|
12
|
+
del = (key) => this.client.delete().key(key).exec();
|
|
23
13
|
|
|
24
14
|
async *iterate(prefix = "") {
|
|
25
15
|
const keys = await this.client.getAll().prefix(prefix).keys();
|
|
@@ -28,18 +18,14 @@ export default class Etcd {
|
|
|
28
18
|
}
|
|
29
19
|
}
|
|
30
20
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async entries(prefix = "") {
|
|
21
|
+
keys = (prefix = "") => this.client.getAll().prefix(prefix).keys();
|
|
22
|
+
entries = async (prefix = "") => {
|
|
36
23
|
const keys = await this.keys(prefix);
|
|
37
24
|
const values = await Promise.all(keys.map((k) => this.get(k)));
|
|
38
25
|
return keys.map((k, i) => [k, values[i]]);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async clear(prefix = "") {
|
|
26
|
+
};
|
|
27
|
+
clear = async (prefix = "") => {
|
|
42
28
|
if (!prefix) return this.client.delete().all();
|
|
43
29
|
return this.client.delete().prefix(prefix);
|
|
44
|
-
}
|
|
30
|
+
};
|
|
45
31
|
}
|
package/src/clients/file.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// A client that uses a single file (JSON) as a store
|
|
2
2
|
export default class File {
|
|
3
3
|
// Check if this is the right class for the given client
|
|
4
|
-
static test(client) {
|
|
4
|
+
static test = (client) => {
|
|
5
5
|
if (client instanceof URL) client = client.href;
|
|
6
6
|
return (
|
|
7
7
|
typeof client === "string" &&
|
|
8
8
|
client.startsWith("file://") &&
|
|
9
9
|
client.includes(".")
|
|
10
10
|
);
|
|
11
|
-
}
|
|
11
|
+
};
|
|
12
12
|
|
|
13
13
|
constructor(file) {
|
|
14
14
|
if (file instanceof URL) file = file.href;
|
|
@@ -65,9 +65,8 @@ export default class File {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// Bulk updates are worth creating a custom method here
|
|
68
|
+
clearAll = () => this.#write({});
|
|
68
69
|
clear = async (prefix = "") => {
|
|
69
|
-
if (!prefix) return this.#write({});
|
|
70
|
-
|
|
71
70
|
const data = await this.#read();
|
|
72
71
|
for (let key in data) {
|
|
73
72
|
if (key.startsWith(prefix)) {
|
package/src/clients/folder.js
CHANGED
|
@@ -3,14 +3,14 @@ const json = (data) => JSON.stringify(data, null, 2);
|
|
|
3
3
|
// A client that uses a single file (JSON) as a store
|
|
4
4
|
export default class Folder {
|
|
5
5
|
// Check if this is the right class for the given client
|
|
6
|
-
static test(client) {
|
|
6
|
+
static test = (client) => {
|
|
7
7
|
if (client instanceof URL) client = client.href;
|
|
8
8
|
return (
|
|
9
9
|
typeof client === "string" &&
|
|
10
10
|
client.startsWith("file://") &&
|
|
11
11
|
client.endsWith("/")
|
|
12
12
|
);
|
|
13
|
-
}
|
|
13
|
+
};
|
|
14
14
|
|
|
15
15
|
constructor(folder) {
|
|
16
16
|
if (folder instanceof URL) folder = folder.href;
|
|
@@ -44,9 +44,7 @@ export default class Folder {
|
|
|
44
44
|
const text = await this.fs.readFile(key, "utf8");
|
|
45
45
|
return text ? JSON.parse(text) : null;
|
|
46
46
|
};
|
|
47
|
-
|
|
48
47
|
set = (key, value) => this.fs.writeFile(key, json(value), "utf8");
|
|
49
|
-
|
|
50
48
|
del = (key) => this.fs.unlink(key);
|
|
51
49
|
|
|
52
50
|
async *iterate(prefix = "") {
|
package/src/clients/forage.js
CHANGED
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
// Use localForage for managing the KV
|
|
2
2
|
export default class Forage {
|
|
3
3
|
// Check if this is the right class for the given client
|
|
4
|
-
static test(client)
|
|
5
|
-
|
|
6
|
-
}
|
|
4
|
+
static test = (client) =>
|
|
5
|
+
client?.defineDriver && client?.dropInstance && client?.INDEXEDDB;
|
|
7
6
|
|
|
8
7
|
constructor(client) {
|
|
9
8
|
this.client = client;
|
|
10
9
|
}
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
async set(key, value) {
|
|
17
|
-
return this.client.setItem(key, value);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async del(key) {
|
|
21
|
-
return this.client.removeItem(key);
|
|
22
|
-
}
|
|
11
|
+
get = (key) => this.client.getItem(key);
|
|
12
|
+
set = (key, value) => this.client.setItem(key, value);
|
|
13
|
+
del = (key) => this.client.removeItem(key);
|
|
23
14
|
|
|
24
15
|
async *iterate(prefix = "") {
|
|
25
16
|
const keys = await this.client.keys();
|
|
@@ -29,19 +20,12 @@ export default class Forage {
|
|
|
29
20
|
}
|
|
30
21
|
}
|
|
31
22
|
|
|
32
|
-
async
|
|
23
|
+
entries = async (prefix = "") => {
|
|
33
24
|
const all = await this.client.keys();
|
|
34
25
|
const keys = all.filter((k) => k.startsWith(prefix));
|
|
35
26
|
const values = await Promise.all(keys.map((key) => this.get(key)));
|
|
36
27
|
return keys.map((key, i) => [key, values[i]]);
|
|
37
|
-
}
|
|
28
|
+
};
|
|
38
29
|
|
|
39
|
-
|
|
40
|
-
// Delete the whole dataset
|
|
41
|
-
if (!prefix) return this.client.clear();
|
|
42
|
-
|
|
43
|
-
// Delete them in a map
|
|
44
|
-
const list = await this.entries(prefix);
|
|
45
|
-
return Promise.all(list.map((e) => this.set(e[0], null)));
|
|
46
|
-
}
|
|
30
|
+
clearAll = () => this.client.clear();
|
|
47
31
|
}
|
package/src/clients/level.js
CHANGED
|
@@ -1,30 +1,21 @@
|
|
|
1
|
+
const valueEncoding = "json";
|
|
2
|
+
const notFound = (error) => {
|
|
3
|
+
if (error?.code === "LEVEL_NOT_FOUND") return null;
|
|
4
|
+
throw error;
|
|
5
|
+
};
|
|
6
|
+
|
|
1
7
|
// Level KV DB - https://github.com/Level/level
|
|
2
8
|
export default class Level {
|
|
3
9
|
// Check if this is the right class for the given client
|
|
4
|
-
static test(client)
|
|
5
|
-
return client?.constructor?.name === "ClassicLevel";
|
|
6
|
-
}
|
|
10
|
+
static test = (client) => client?.constructor?.name === "ClassicLevel";
|
|
7
11
|
|
|
8
12
|
constructor(client) {
|
|
9
13
|
this.client = client;
|
|
10
14
|
}
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} catch (error) {
|
|
16
|
-
if (error?.code === "LEVEL_NOT_FOUND") return null;
|
|
17
|
-
throw error;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async set(key, value) {
|
|
22
|
-
return this.client.put(key, value, { valueEncoding: "json" });
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async del(key) {
|
|
26
|
-
return this.client.del(key);
|
|
27
|
-
}
|
|
16
|
+
get = (key) => this.client.get(key, { valueEncoding }).catch(notFound);
|
|
17
|
+
set = (key, value) => this.client.put(key, value, { valueEncoding });
|
|
18
|
+
del = (key) => this.client.del(key);
|
|
28
19
|
|
|
29
20
|
async *iterate(prefix = "") {
|
|
30
21
|
const keys = await this.client.keys().all();
|
|
@@ -34,20 +25,18 @@ export default class Level {
|
|
|
34
25
|
}
|
|
35
26
|
}
|
|
36
27
|
|
|
37
|
-
async
|
|
28
|
+
entries = async (prefix = "") => {
|
|
38
29
|
const keys = await this.client.keys().all();
|
|
39
30
|
const list = keys.filter((k) => k.startsWith(prefix));
|
|
40
31
|
return Promise.all(list.map(async (k) => [k, await this.get(k)]));
|
|
41
|
-
}
|
|
32
|
+
};
|
|
42
33
|
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
clearAll = () => this.client.clear();
|
|
35
|
+
clear = async (prefix = "") => {
|
|
45
36
|
const keys = await this.client.keys().all();
|
|
46
37
|
const list = keys.filter((k) => k.startsWith(prefix));
|
|
47
38
|
return this.client.batch(list.map((key) => ({ type: "del", key })));
|
|
48
|
-
}
|
|
39
|
+
};
|
|
49
40
|
|
|
50
|
-
|
|
51
|
-
return await this.client.close();
|
|
52
|
-
}
|
|
41
|
+
close = () => this.client.close();
|
|
53
42
|
}
|
package/src/clients/memory.js
CHANGED
|
@@ -1,40 +1,21 @@
|
|
|
1
1
|
// Use a Map() as an in-memory client
|
|
2
2
|
export default class Memory {
|
|
3
3
|
// Check if this is the right class for the given client
|
|
4
|
-
static test(client)
|
|
5
|
-
return client instanceof Map;
|
|
6
|
-
}
|
|
4
|
+
static test = (client) => client instanceof Map;
|
|
7
5
|
|
|
8
6
|
constructor(client) {
|
|
9
7
|
this.client = client;
|
|
10
8
|
}
|
|
11
9
|
|
|
12
|
-
get(key)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
set(key, data) {
|
|
17
|
-
return this.client.set(key, data);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
del(key) {
|
|
21
|
-
return this.client.delete(key);
|
|
22
|
-
}
|
|
10
|
+
get = (key) => this.client.get(key) ?? null;
|
|
11
|
+
set = (key, data) => this.client.set(key, data);
|
|
12
|
+
del = (key) => this.client.delete(key);
|
|
23
13
|
|
|
24
14
|
*iterate(prefix = "") {
|
|
25
15
|
for (const entry of this.client.entries()) {
|
|
26
|
-
if (
|
|
27
|
-
yield entry;
|
|
16
|
+
if (entry[0].startsWith(prefix)) yield entry;
|
|
28
17
|
}
|
|
29
18
|
}
|
|
30
19
|
|
|
31
|
-
|
|
32
|
-
// Delete the whole dataset
|
|
33
|
-
if (!prefix) return this.client.clear();
|
|
34
|
-
|
|
35
|
-
// Delete them in a map
|
|
36
|
-
return [...this.client.keys()]
|
|
37
|
-
.filter((k) => k.startsWith(prefix))
|
|
38
|
-
.map((k) => this.del(k));
|
|
39
|
-
}
|
|
20
|
+
clearAll = () => this.client.clear();
|
|
40
21
|
}
|
package/src/clients/redis.js
CHANGED
|
@@ -53,12 +53,6 @@ export default class Redis {
|
|
|
53
53
|
return keys.map((k, i) => [k, values[i]]);
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
if (!prefix) return this.client.flushAll();
|
|
58
|
-
|
|
59
|
-
const list = await this.keys(prefix);
|
|
60
|
-
return Promise.all(list.map((k) => this.client.del(k)));
|
|
61
|
-
};
|
|
62
|
-
|
|
56
|
+
clearAll = () => this.client.flushAll();
|
|
63
57
|
close = () => this.client.quit();
|
|
64
58
|
}
|
package/src/clients/storage.js
CHANGED
|
@@ -11,18 +11,12 @@ export default class WebStorage {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
// Item methods
|
|
14
|
-
get(key) {
|
|
15
|
-
const
|
|
16
|
-
return
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return this.client.setItem(key, JSON.stringify(data));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
del(key) {
|
|
24
|
-
return this.client.removeItem(key);
|
|
25
|
-
}
|
|
14
|
+
get = (key) => {
|
|
15
|
+
const text = this.client[key];
|
|
16
|
+
return text ? JSON.parse(text) : null;
|
|
17
|
+
};
|
|
18
|
+
set = (key, data) => this.client.setItem(key, JSON.stringify(data));
|
|
19
|
+
del = (key) => this.client.removeItem(key);
|
|
26
20
|
|
|
27
21
|
*iterate(prefix = "") {
|
|
28
22
|
for (const key of Object.keys(this.client)) {
|
|
@@ -33,13 +27,5 @@ export default class WebStorage {
|
|
|
33
27
|
}
|
|
34
28
|
}
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
// Delete the whole store
|
|
38
|
-
if (!prefix) return this.client.clear();
|
|
39
|
-
|
|
40
|
-
// Delete them in a map
|
|
41
|
-
return Object.keys(this.client)
|
|
42
|
-
.filter((k) => k.startsWith(prefix))
|
|
43
|
-
.map((k) => this.del(k));
|
|
44
|
-
}
|
|
30
|
+
clearAll = () => this.client.clear();
|
|
45
31
|
}
|
package/src/index.js
CHANGED