polystore 0.15.0 → 0.15.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polystore",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
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/readme.md CHANGED
@@ -700,7 +700,7 @@ await fsp.writeFile(file, serialValue);
700
700
 
701
701
  ### Folder
702
702
 
703
- Treat a single folder in your filesystem as the source for the KV store, with each key being within a file:
703
+ Treat a single folder in your filesystem as the store, where each key is a file:
704
704
 
705
705
  ```js
706
706
  import kv from "polystore";
@@ -708,6 +708,7 @@ import kv from "polystore";
708
708
  const store = kv(new URL("file:///Users/me/project/data/"));
709
709
 
710
710
  await store.set("key1", "Hello world", { expires: "1h" });
711
+ // Writes "./data/key1.json"
711
712
  console.log(await store.get("key1"));
712
713
  // "Hello world"
713
714
  ```
@@ -717,12 +718,14 @@ console.log(await store.get("key1"));
717
718
  You can also create multiple stores:
718
719
 
719
720
  ```js
720
- // Paths need to be absolute, but you can use process.cwd() to make
721
- // it relative to the current process:
721
+ // Paths need to be absolute, but you can use `process.cwd()` to make
722
+ // it relative to the current process, or `import.meta.dirname`:
722
723
  const store1 = kv(new URL(`file://${process.cwd()}/cache/`));
723
724
  const store2 = kv(new URL(`file://${import.meta.dirname}/data/`));
724
725
  ```
725
726
 
727
+ The folder is created if it doesn't exist. When a key is deleted, the corresponding file is also deleted. The data is serialized as JSON, with a meta wrapper to store the expiration date.
728
+
726
729
  <details>
727
730
  <summary>Why use polystore with a folder?</summary>
728
731
  <p>These benefits are for wrapping a folder with polystore:</p>
@@ -1,71 +1,39 @@
1
- // Use fetch()
1
+ const enc = encodeURIComponent; // Optimization of size
2
+
3
+ // Handle an API endpoint with fetch()
2
4
  export default class Api {
3
- // Indicate that the file handler does NOT handle expirations
5
+ // Indicate that the file handler DOES handle expirations
4
6
  EXPIRES = true;
5
7
 
6
- // Check whether the given store is a FILE-type
7
- static test(client) {
8
- return (
9
- typeof client === "string" &&
10
- (client.startsWith("https://") || client.startsWith("http://"))
11
- );
12
- }
8
+ static test = (client) =>
9
+ typeof client === "string" && /^https?:\/\//.test(client);
13
10
 
14
11
  constructor(client) {
15
- client = client.replace(/\/$/, "") + "/";
16
- this.client = async (path, opts = {}) => {
17
- const query = Object.entries(opts.query || {})
18
- .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
19
- .join("&");
20
- let url = client + path.replace(/^\//, "") + "?" + query;
21
- opts.headers = opts.headers || {};
22
- opts.headers.accept = "application/json";
23
- if (opts.body) opts.headers["content-type"] = "application/json";
24
- const res = await fetch(url, opts);
25
- if (!res.ok) return null;
26
- if (!res.headers["content-type"] !== "application/json") {
27
- console.warn("Not a JSON API");
28
- }
29
- return res.json();
12
+ client = client.replace(/\/$/, "");
13
+ this.client = async (path, method = "GET", body) => {
14
+ const url = `${client}/${path.replace(/^\//, "")}`;
15
+ const headers = { accept: "application/json" };
16
+ if (body) headers["content-type"] = "application/json";
17
+ const res = await fetch(url, { method, headers, body });
18
+ return res.ok ? res.json() : null;
30
19
  };
31
20
  }
32
21
 
33
- async get(key) {
34
- return await this.client(`/${key}`);
35
- }
22
+ get = (key) => this.client(`/${enc(key)}`);
36
23
 
37
- async set(key, value, { expires } = {}) {
38
- return await this.client(`/${encodeURIComponent(key)}`, {
39
- query: { expires },
40
- method: "put",
41
- body: JSON.stringify(value),
42
- });
43
- }
24
+ set = (key, value, { expires } = {}) =>
25
+ this.client(
26
+ `/${enc(key)}?expires=${enc(expires || "")}`,
27
+ "PUT",
28
+ JSON.stringify(value),
29
+ );
44
30
 
45
- async del(key) {
46
- return await this.client(`/${encodeURIComponent(key)}`, {
47
- method: "delete",
48
- });
49
- }
31
+ del = (key) => this.client(`/${enc(key)}`, "DELETE");
50
32
 
51
- // Since we have pagination, we don't want to get all of the
52
- // keys at once if we can avoid it
53
33
  async *iterate(prefix = "") {
54
- const data = await this.client("/", { query: { prefix } });
55
- if (!data) return [];
56
- for (let [key, value] of Object.entries(data)) {
34
+ const data = await this.client(`/?prefix=${enc(prefix)}`);
35
+ for (let [key, value] of Object.entries(data || {})) {
57
36
  yield [prefix + key, value];
58
37
  }
59
38
  }
60
-
61
- async keys(prefix = "") {
62
- const data = await this.client(`/`, { query: { prefix } });
63
- if (!data) return [];
64
- return Object.keys(data).map((k) => prefix + k);
65
- }
66
-
67
- async clear(prefix = "") {
68
- const list = await this.keys(prefix);
69
- return Promise.all(list.map((k) => this.del(k)));
70
- }
71
39
  }
@@ -29,7 +29,8 @@ export default class File {
29
29
  // We want to make sure the file already exists, so attempt to
30
30
  // create the folders and the file (but not OVERWRITE it, that's why the x flag)
31
31
  // It fails if it already exists, hence the catch case
32
- await fsp.mkdir(path.dirname(this.file), { recursive: true });
32
+ const folder = path.dirname(this.file);
33
+ await fsp.mkdir(folder, { recursive: true }).catch(() => {});
33
34
  await fsp.writeFile(this.file, "{}", { flag: "wx" }).catch((err) => {
34
35
  if (err.code !== "EEXIST") throw err;
35
36
  });
@@ -32,7 +32,7 @@ export default class Folder {
32
32
 
33
33
  // Make sure the folder already exists, so attempt to create it
34
34
  // It fails if it already exists, hence the catch case
35
- await fsp.mkdir(this.folder, { recursive: true }).catch((err) => {});
35
+ await fsp.mkdir(this.folder, { recursive: true }).catch(() => {});
36
36
  return fsp;
37
37
  })();
38
38
  }
package/src/server.js CHANGED
@@ -1,7 +1,6 @@
1
1
  // This is an example server implementation of the HTTP library!
2
2
  import http from "node:http";
3
3
  import kv from "./index.js";
4
- import { parse } from "./utils.js";
5
4
 
6
5
  // Modify this to use any sub-store as desired. It's nice
7
6
  // to use polystore itself for the polystore server library!'