polystore 0.15.4 → 0.15.6
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/file.js +3 -4
- package/src/clients/folder.js +32 -53
- package/src/clients/redis.js +22 -36
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polystore",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.6",
|
|
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/file.js
CHANGED
|
@@ -32,13 +32,13 @@ export default class File {
|
|
|
32
32
|
// Internal
|
|
33
33
|
#read = async () => {
|
|
34
34
|
const fsp = await this.promise;
|
|
35
|
-
const
|
|
36
|
-
return JSON.parse(
|
|
35
|
+
const text = await fsp.readFile(this.file, "utf8");
|
|
36
|
+
return text ? JSON.parse(text) : {};
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
#write = async (data) => {
|
|
40
40
|
const fsp = await this.promise;
|
|
41
|
-
fsp.writeFile(this.file, JSON.stringify(data, null, 2));
|
|
41
|
+
return fsp.writeFile(this.file, JSON.stringify(data, null, 2));
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
get = async (key) => {
|
|
@@ -54,7 +54,6 @@ export default class File {
|
|
|
54
54
|
data[key] = value;
|
|
55
55
|
}
|
|
56
56
|
await this.#write(data);
|
|
57
|
-
return key;
|
|
58
57
|
};
|
|
59
58
|
|
|
60
59
|
async *iterate(prefix = "") {
|
package/src/clients/folder.js
CHANGED
|
@@ -1,67 +1,56 @@
|
|
|
1
|
-
const
|
|
2
|
-
if (error.code === "ENOENT") return null;
|
|
3
|
-
throw error;
|
|
4
|
-
};
|
|
1
|
+
const json = (data) => JSON.stringify(data, null, 2);
|
|
5
2
|
|
|
6
3
|
// A client that uses a single file (JSON) as a store
|
|
7
4
|
export default class Folder {
|
|
8
5
|
// Check if this is the right class for the given client
|
|
9
6
|
static test(client) {
|
|
10
|
-
if (
|
|
7
|
+
if (client instanceof URL) client = client.href;
|
|
8
|
+
return (
|
|
11
9
|
typeof client === "string" &&
|
|
12
|
-
client.startsWith("file
|
|
10
|
+
client.startsWith("file://") &&
|
|
13
11
|
client.endsWith("/")
|
|
14
|
-
)
|
|
15
|
-
return true;
|
|
16
|
-
return (
|
|
17
|
-
client instanceof URL &&
|
|
18
|
-
client.protocol === "file:" &&
|
|
19
|
-
client.pathname.endsWith("/")
|
|
20
12
|
);
|
|
21
13
|
}
|
|
22
14
|
|
|
23
15
|
constructor(folder) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
? folder.slice("file://".length).replace(/\/$/, "") + "/"
|
|
27
|
-
: folder.pathname.replace(/\/$/, "") + "/";
|
|
16
|
+
if (folder instanceof URL) folder = folder.href;
|
|
17
|
+
folder = folder.replace(/^file:\/\//, "");
|
|
28
18
|
|
|
29
19
|
// Run this once on launch; import the FS module and reset the file
|
|
30
|
-
|
|
31
|
-
const fsp = await import("node:fs/promises");
|
|
32
|
-
|
|
20
|
+
const prom = import("node:fs/promises").then((fsp) => {
|
|
33
21
|
// Make sure the folder already exists, so attempt to create it
|
|
34
22
|
// It fails if it already exists, hence the catch case
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
23
|
+
return fsp.mkdir(folder, { recursive: true }).then(
|
|
24
|
+
() => fsp,
|
|
25
|
+
() => {},
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const getter = (_, name) => {
|
|
30
|
+
return async (key, ...props) => {
|
|
31
|
+
const file = folder + (key ? key + ".json" : "");
|
|
32
|
+
const method = (await prom)[name];
|
|
33
|
+
return method(file, ...props).catch((error) => {
|
|
34
|
+
if (error.code === "ENOENT") return null;
|
|
35
|
+
throw error;
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
this.fs = new Proxy({}, { get: getter });
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
async
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!text) return null;
|
|
45
|
-
return JSON.parse(text);
|
|
46
|
-
}
|
|
43
|
+
get = async (key) => {
|
|
44
|
+
const text = await this.fs.readFile(key, "utf8");
|
|
45
|
+
return text ? JSON.parse(text) : null;
|
|
46
|
+
};
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
const fsp = await this.promise;
|
|
50
|
-
const file = this.folder + key + ".json";
|
|
51
|
-
await fsp.writeFile(file, JSON.stringify(value, null, 2), "utf8");
|
|
52
|
-
return file;
|
|
53
|
-
}
|
|
48
|
+
set = (key, value) => this.fs.writeFile(key, json(value), "utf8");
|
|
54
49
|
|
|
55
|
-
|
|
56
|
-
const file = this.folder + key + ".json";
|
|
57
|
-
const fsp = await this.promise;
|
|
58
|
-
await fsp.unlink(file).catch(noFileOk);
|
|
59
|
-
return file;
|
|
60
|
-
}
|
|
50
|
+
del = (key) => this.fs.unlink(key);
|
|
61
51
|
|
|
62
52
|
async *iterate(prefix = "") {
|
|
63
|
-
const
|
|
64
|
-
const all = await fsp.readdir(this.folder);
|
|
53
|
+
const all = await this.fs.readdir();
|
|
65
54
|
const keys = all
|
|
66
55
|
.filter((f) => f.startsWith(prefix) && f.endsWith(".json"))
|
|
67
56
|
.map((name) => name.slice(0, -".json".length));
|
|
@@ -70,14 +59,4 @@ export default class Folder {
|
|
|
70
59
|
yield [key, data];
|
|
71
60
|
}
|
|
72
61
|
}
|
|
73
|
-
|
|
74
|
-
// async clear(prefix = "") {
|
|
75
|
-
// const data = await this.#read();
|
|
76
|
-
// for (let key in data) {
|
|
77
|
-
// if (key.startsWith(prefix)) {
|
|
78
|
-
// delete data[key];
|
|
79
|
-
// }
|
|
80
|
-
// }
|
|
81
|
-
// await this.#write(data);
|
|
82
|
-
// }
|
|
83
62
|
}
|
package/src/clients/redis.js
CHANGED
|
@@ -4,37 +4,25 @@ export default class Redis {
|
|
|
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 && client.pSubscribe && client.sSubscribe;
|
|
9
|
-
}
|
|
7
|
+
static test = (client) => client && client.pSubscribe && client.sSubscribe;
|
|
10
8
|
|
|
11
9
|
constructor(client) {
|
|
12
10
|
this.client = client;
|
|
13
11
|
}
|
|
14
12
|
|
|
15
|
-
async
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
13
|
+
get = async (key) => {
|
|
14
|
+
const text = await this.client.get(key);
|
|
15
|
+
return text ? JSON.parse(text) : null;
|
|
16
|
+
};
|
|
20
17
|
|
|
21
|
-
async
|
|
18
|
+
set = async (key, value, { expires } = {}) => {
|
|
22
19
|
const EX = expires ? Math.round(expires) : undefined;
|
|
23
20
|
return this.client.set(key, JSON.stringify(value), { EX });
|
|
24
|
-
}
|
|
21
|
+
};
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
return this.client.del(key);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async has(key) {
|
|
31
|
-
return Boolean(await this.client.exists(key));
|
|
32
|
-
}
|
|
23
|
+
del = (key) => this.client.del(key);
|
|
33
24
|
|
|
34
|
-
|
|
35
|
-
async keys(prefix = "") {
|
|
36
|
-
return this.client.keys(prefix + "*");
|
|
37
|
-
}
|
|
25
|
+
has = async (key) => Boolean(await this.client.exists(key));
|
|
38
26
|
|
|
39
27
|
// Go through each of the [key, value] in the set
|
|
40
28
|
async *iterate(prefix = "") {
|
|
@@ -47,32 +35,30 @@ export default class Redis {
|
|
|
47
35
|
}
|
|
48
36
|
}
|
|
49
37
|
|
|
50
|
-
// Optimizing the retrieval of them all in bulk by loading the values
|
|
51
|
-
// in parallel
|
|
52
|
-
async entries(prefix = "") {
|
|
53
|
-
const keys = await this.keys(prefix);
|
|
54
|
-
const values = await Promise.all(keys.map((k) => this.get(k)));
|
|
55
|
-
return keys.map((k, i) => [k, values[i]]);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
38
|
// Optimizing the retrieval of them by not getting their values
|
|
59
|
-
async
|
|
39
|
+
keys = async (prefix = "") => {
|
|
60
40
|
const MATCH = prefix + "*";
|
|
61
41
|
const keys = [];
|
|
62
42
|
for await (const key of this.client.scanIterator({ MATCH })) {
|
|
63
43
|
keys.push(key);
|
|
64
44
|
}
|
|
65
45
|
return keys;
|
|
66
|
-
}
|
|
46
|
+
};
|
|
67
47
|
|
|
68
|
-
|
|
48
|
+
// Optimizing the retrieval of them all in bulk by loading the values
|
|
49
|
+
// in parallel
|
|
50
|
+
entries = async (prefix = "") => {
|
|
51
|
+
const keys = await this.keys(prefix);
|
|
52
|
+
const values = await Promise.all(keys.map((k) => this.get(k)));
|
|
53
|
+
return keys.map((k, i) => [k, values[i]]);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
clear = async (prefix = "") => {
|
|
69
57
|
if (!prefix) return this.client.flushAll();
|
|
70
58
|
|
|
71
59
|
const list = await this.keys(prefix);
|
|
72
60
|
return Promise.all(list.map((k) => this.client.del(k)));
|
|
73
|
-
}
|
|
61
|
+
};
|
|
74
62
|
|
|
75
|
-
|
|
76
|
-
return this.client.quit();
|
|
77
|
-
}
|
|
63
|
+
close = () => this.client.quit();
|
|
78
64
|
}
|