@optimystic/db-p2p-storage-fs 0.9.3 → 0.11.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/dist/src/file-kv-store.d.ts +13 -0
- package/dist/src/file-kv-store.d.ts.map +1 -0
- package/dist/src/file-kv-store.js +65 -0
- package/dist/src/file-kv-store.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/package.json +3 -3
- package/src/file-kv-store.ts +62 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IKVStore } from '@optimystic/db-p2p';
|
|
2
|
+
/** Filesystem-backed IKVStore. Keys may contain `/` separators which become subdirectories. */
|
|
3
|
+
export declare class FileKVStore implements IKVStore {
|
|
4
|
+
private readonly basePath;
|
|
5
|
+
constructor(basePath: string);
|
|
6
|
+
get(key: string): Promise<string | undefined>;
|
|
7
|
+
set(key: string, value: string): Promise<void>;
|
|
8
|
+
delete(key: string): Promise<void>;
|
|
9
|
+
list(prefix: string): Promise<string[]>;
|
|
10
|
+
private listRecursive;
|
|
11
|
+
private keyToPath;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=file-kv-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-kv-store.d.ts","sourceRoot":"","sources":["../../src/file-kv-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,+FAA+F;AAC/F,qBAAa,WAAY,YAAW,QAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAEvC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAS7C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAS/B,aAAa;IAkB3B,OAAO,CAAC,SAAS;CAGjB"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
/** Filesystem-backed IKVStore. Keys may contain `/` separators which become subdirectories. */
|
|
4
|
+
export class FileKVStore {
|
|
5
|
+
basePath;
|
|
6
|
+
constructor(basePath) {
|
|
7
|
+
this.basePath = basePath;
|
|
8
|
+
}
|
|
9
|
+
async get(key) {
|
|
10
|
+
try {
|
|
11
|
+
return await fs.readFile(this.keyToPath(key), 'utf-8');
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
if (err?.code === 'ENOENT')
|
|
15
|
+
return undefined;
|
|
16
|
+
throw err;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async set(key, value) {
|
|
20
|
+
const filePath = this.keyToPath(key);
|
|
21
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
22
|
+
await fs.writeFile(filePath, value);
|
|
23
|
+
}
|
|
24
|
+
async delete(key) {
|
|
25
|
+
try {
|
|
26
|
+
await fs.unlink(this.keyToPath(key));
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (err?.code !== 'ENOENT')
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async list(prefix) {
|
|
34
|
+
// prefix like "coordinator/" → scan basePath/coordinator/ directory
|
|
35
|
+
const parts = prefix.split('/').filter(Boolean);
|
|
36
|
+
const dirPath = path.join(this.basePath, ...parts);
|
|
37
|
+
const results = [];
|
|
38
|
+
await this.listRecursive(dirPath, prefix, results);
|
|
39
|
+
return results;
|
|
40
|
+
}
|
|
41
|
+
async listRecursive(dirPath, prefix, results) {
|
|
42
|
+
let entries;
|
|
43
|
+
try {
|
|
44
|
+
entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
if (err?.code === 'ENOENT')
|
|
48
|
+
return;
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
if (entry.isDirectory()) {
|
|
53
|
+
const subPrefix = prefix + entry.name + '/';
|
|
54
|
+
await this.listRecursive(path.join(dirPath, entry.name), subPrefix, results);
|
|
55
|
+
}
|
|
56
|
+
else if (entry.isFile() && entry.name.endsWith('.json')) {
|
|
57
|
+
results.push(prefix + entry.name.slice(0, -5));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
keyToPath(key) {
|
|
62
|
+
return path.join(this.basePath, ...key.split('/')) + '.json';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=file-kv-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-kv-store.js","sourceRoot":"","sources":["../../src/file-kv-store.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC"}
|
package/dist/src/index.js
CHANGED
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optimystic/db-p2p-storage-fs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Node.js filesystem storage backend for @optimystic/db-p2p",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"typescript": "^5.9.3"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@optimystic/db-core": "^0.
|
|
48
|
-
"@optimystic/db-p2p": "^0.
|
|
47
|
+
"@optimystic/db-core": "^0.11.0",
|
|
48
|
+
"@optimystic/db-p2p": "^0.11.0",
|
|
49
49
|
"debug": "^4.4.3"
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import type { IKVStore } from '@optimystic/db-p2p';
|
|
4
|
+
|
|
5
|
+
/** Filesystem-backed IKVStore. Keys may contain `/` separators which become subdirectories. */
|
|
6
|
+
export class FileKVStore implements IKVStore {
|
|
7
|
+
constructor(private readonly basePath: string) {}
|
|
8
|
+
|
|
9
|
+
async get(key: string): Promise<string | undefined> {
|
|
10
|
+
try {
|
|
11
|
+
return await fs.readFile(this.keyToPath(key), 'utf-8');
|
|
12
|
+
} catch (err) {
|
|
13
|
+
if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') return undefined;
|
|
14
|
+
throw err;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async set(key: string, value: string): Promise<void> {
|
|
19
|
+
const filePath = this.keyToPath(key);
|
|
20
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
21
|
+
await fs.writeFile(filePath, value);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async delete(key: string): Promise<void> {
|
|
25
|
+
try {
|
|
26
|
+
await fs.unlink(this.keyToPath(key));
|
|
27
|
+
} catch (err) {
|
|
28
|
+
if ((err as NodeJS.ErrnoException)?.code !== 'ENOENT') throw err;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async list(prefix: string): Promise<string[]> {
|
|
33
|
+
// prefix like "coordinator/" → scan basePath/coordinator/ directory
|
|
34
|
+
const parts = prefix.split('/').filter(Boolean);
|
|
35
|
+
const dirPath = path.join(this.basePath, ...parts);
|
|
36
|
+
const results: string[] = [];
|
|
37
|
+
await this.listRecursive(dirPath, prefix, results);
|
|
38
|
+
return results;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private async listRecursive(dirPath: string, prefix: string, results: string[]): Promise<void> {
|
|
42
|
+
let entries;
|
|
43
|
+
try {
|
|
44
|
+
entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
45
|
+
} catch (err) {
|
|
46
|
+
if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') return;
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
for (const entry of entries) {
|
|
50
|
+
if (entry.isDirectory()) {
|
|
51
|
+
const subPrefix = prefix + entry.name + '/';
|
|
52
|
+
await this.listRecursive(path.join(dirPath, entry.name), subPrefix, results);
|
|
53
|
+
} else if (entry.isFile() && entry.name.endsWith('.json')) {
|
|
54
|
+
results.push(prefix + entry.name.slice(0, -5));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private keyToPath(key: string): string {
|
|
60
|
+
return path.join(this.basePath, ...key.split('/')) + '.json';
|
|
61
|
+
}
|
|
62
|
+
}
|
package/src/index.ts
CHANGED