@hashtree/core 0.1.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/LICENSE +21 -0
- package/dist/bep52.d.ts +179 -0
- package/dist/bep52.d.ts.map +1 -0
- package/dist/bep52.js +384 -0
- package/dist/bep52.js.map +1 -0
- package/dist/builder.d.ts +137 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +281 -0
- package/dist/builder.js.map +1 -0
- package/dist/codec.d.ts +37 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +109 -0
- package/dist/codec.js.map +1 -0
- package/dist/crypto.d.ts +92 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +212 -0
- package/dist/crypto.js.map +1 -0
- package/dist/encrypted.d.ts +114 -0
- package/dist/encrypted.d.ts.map +1 -0
- package/dist/encrypted.js +446 -0
- package/dist/encrypted.js.map +1 -0
- package/dist/hash.d.ts +14 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +27 -0
- package/dist/hash.js.map +1 -0
- package/dist/hashtree.d.ts +237 -0
- package/dist/hashtree.d.ts.map +1 -0
- package/dist/hashtree.js +557 -0
- package/dist/hashtree.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/nhash.d.ts +94 -0
- package/dist/nhash.d.ts.map +1 -0
- package/dist/nhash.js +293 -0
- package/dist/nhash.js.map +1 -0
- package/dist/resolver/index.d.ts +5 -0
- package/dist/resolver/index.d.ts.map +1 -0
- package/dist/resolver/index.js +5 -0
- package/dist/resolver/index.js.map +1 -0
- package/dist/resolver/nostr.d.ts +82 -0
- package/dist/resolver/nostr.d.ts.map +1 -0
- package/dist/resolver/nostr.js +868 -0
- package/dist/resolver/nostr.js.map +1 -0
- package/dist/store/blossom.d.ts +100 -0
- package/dist/store/blossom.d.ts.map +1 -0
- package/dist/store/blossom.js +355 -0
- package/dist/store/blossom.js.map +1 -0
- package/dist/store/dexie.d.ts +44 -0
- package/dist/store/dexie.d.ts.map +1 -0
- package/dist/store/dexie.js +196 -0
- package/dist/store/dexie.js.map +1 -0
- package/dist/store/fallback.d.ts +40 -0
- package/dist/store/fallback.d.ts.map +1 -0
- package/dist/store/fallback.js +71 -0
- package/dist/store/fallback.js.map +1 -0
- package/dist/store/index.d.ts +6 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +6 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/memory.d.ts +29 -0
- package/dist/store/memory.d.ts.map +1 -0
- package/dist/store/memory.js +66 -0
- package/dist/store/memory.js.map +1 -0
- package/dist/store/opfs.d.ts +56 -0
- package/dist/store/opfs.d.ts.map +1 -0
- package/dist/store/opfs.js +200 -0
- package/dist/store/opfs.js.map +1 -0
- package/dist/streaming.d.ts +74 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +199 -0
- package/dist/streaming.js.map +1 -0
- package/dist/tree/create.d.ts +35 -0
- package/dist/tree/create.d.ts.map +1 -0
- package/dist/tree/create.js +90 -0
- package/dist/tree/create.js.map +1 -0
- package/dist/tree/edit.d.ts +28 -0
- package/dist/tree/edit.d.ts.map +1 -0
- package/dist/tree/edit.js +115 -0
- package/dist/tree/edit.js.map +1 -0
- package/dist/tree/editEncrypted.d.ts +46 -0
- package/dist/tree/editEncrypted.d.ts.map +1 -0
- package/dist/tree/editEncrypted.js +225 -0
- package/dist/tree/editEncrypted.js.map +1 -0
- package/dist/tree/index.d.ts +7 -0
- package/dist/tree/index.d.ts.map +1 -0
- package/dist/tree/index.js +7 -0
- package/dist/tree/index.js.map +1 -0
- package/dist/tree/read.d.ts +75 -0
- package/dist/tree/read.d.ts.map +1 -0
- package/dist/tree/read.js +389 -0
- package/dist/tree/read.js.map +1 -0
- package/dist/tree/writeAt.d.ts +44 -0
- package/dist/tree/writeAt.d.ts.map +1 -0
- package/dist/tree/writeAt.js +282 -0
- package/dist/tree/writeAt.js.map +1 -0
- package/dist/types.d.ts +274 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +47 -0
- package/dist/types.js.map +1 -0
- package/dist/verify.d.ts +12 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +32 -0
- package/dist/verify.js.map +1 -0
- package/dist/visibility.d.ts +50 -0
- package/dist/visibility.d.ts.map +1 -0
- package/dist/visibility.js +111 -0
- package/dist/visibility.js.map +1 -0
- package/dist/webrtc/index.d.ts +4 -0
- package/dist/webrtc/index.d.ts.map +1 -0
- package/dist/webrtc/index.js +4 -0
- package/dist/webrtc/index.js.map +1 -0
- package/dist/webrtc/lruCache.d.ts +20 -0
- package/dist/webrtc/lruCache.d.ts.map +1 -0
- package/dist/webrtc/lruCache.js +59 -0
- package/dist/webrtc/lruCache.js.map +1 -0
- package/dist/webrtc/peer.d.ts +122 -0
- package/dist/webrtc/peer.d.ts.map +1 -0
- package/dist/webrtc/peer.js +583 -0
- package/dist/webrtc/peer.js.map +1 -0
- package/dist/webrtc/protocol.d.ts +76 -0
- package/dist/webrtc/protocol.d.ts.map +1 -0
- package/dist/webrtc/protocol.js +167 -0
- package/dist/webrtc/protocol.js.map +1 -0
- package/dist/webrtc/store.d.ts +190 -0
- package/dist/webrtc/store.d.ts.map +1 -0
- package/dist/webrtc/store.js +1043 -0
- package/dist/webrtc/store.js.map +1 -0
- package/dist/webrtc/types.d.ts +196 -0
- package/dist/webrtc/types.d.ts.map +1 -0
- package/dist/webrtc/types.js +46 -0
- package/dist/webrtc/types.js.map +1 -0
- package/dist/worker/protocol.d.ts +493 -0
- package/dist/worker/protocol.d.ts.map +1 -0
- package/dist/worker/protocol.js +15 -0
- package/dist/worker/protocol.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dexie-based IndexedDB store for hashtree blobs
|
|
3
|
+
* More robust than raw IndexedDB - handles errors, upgrades, and stuck connections better
|
|
4
|
+
*/
|
|
5
|
+
import Dexie from 'dexie';
|
|
6
|
+
import { toHex, fromHex } from '../types.js';
|
|
7
|
+
class HashTreeDB extends Dexie {
|
|
8
|
+
blobs;
|
|
9
|
+
constructor(dbName) {
|
|
10
|
+
super(dbName);
|
|
11
|
+
// Version 1: Original schema without lastAccess
|
|
12
|
+
this.version(1).stores({
|
|
13
|
+
blobs: '&hashHex',
|
|
14
|
+
});
|
|
15
|
+
// Version 2: Add lastAccess field for LRU eviction
|
|
16
|
+
this.version(2).stores({
|
|
17
|
+
blobs: '&hashHex, lastAccess',
|
|
18
|
+
}).upgrade(tx => {
|
|
19
|
+
// Add lastAccess to existing entries
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
return tx.table('blobs').toCollection().modify(blob => {
|
|
22
|
+
blob.lastAccess = now;
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Dexie-based Store implementation
|
|
29
|
+
* Drop-in replacement for IndexedDBStore with better error handling
|
|
30
|
+
*/
|
|
31
|
+
export class DexieStore {
|
|
32
|
+
db;
|
|
33
|
+
constructor(dbName = 'hashtree') {
|
|
34
|
+
this.db = new HashTreeDB(dbName);
|
|
35
|
+
}
|
|
36
|
+
async put(hash, data) {
|
|
37
|
+
const hashHex = toHex(hash);
|
|
38
|
+
try {
|
|
39
|
+
// Store directly - IDB will clone the data internally
|
|
40
|
+
await this.db.blobs.put({ hashHex, data, lastAccess: Date.now() });
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
console.error('[DexieStore] put error:', e);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async get(hash) {
|
|
49
|
+
if (!hash)
|
|
50
|
+
return null;
|
|
51
|
+
const hashHex = toHex(hash);
|
|
52
|
+
try {
|
|
53
|
+
const entry = await this.db.blobs.get(hashHex);
|
|
54
|
+
if (!entry)
|
|
55
|
+
return null;
|
|
56
|
+
// Update lastAccess timestamp for LRU tracking (fire-and-forget)
|
|
57
|
+
// We need to re-put the entry to avoid fake-indexeddb corruption issues with partial updates
|
|
58
|
+
this.db.blobs.put({ ...entry, lastAccess: Date.now() }).catch(() => { });
|
|
59
|
+
// Return directly - IDB returns a fresh copy already
|
|
60
|
+
// Only slice if the view doesn't match the buffer (rare edge case)
|
|
61
|
+
const data = entry.data;
|
|
62
|
+
if (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength) {
|
|
63
|
+
return data;
|
|
64
|
+
}
|
|
65
|
+
// Rare: view is a subset of a larger buffer, need to copy
|
|
66
|
+
return new Uint8Array(data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength));
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
console.error('[DexieStore] get error:', e);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async has(hash) {
|
|
74
|
+
const hashHex = toHex(hash);
|
|
75
|
+
try {
|
|
76
|
+
// Use count with where clause - doesn't load the blob data
|
|
77
|
+
const count = await this.db.blobs.where('hashHex').equals(hashHex).count();
|
|
78
|
+
return count > 0;
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
console.error('[DexieStore] has error:', e);
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async delete(hash) {
|
|
86
|
+
const hashHex = toHex(hash);
|
|
87
|
+
try {
|
|
88
|
+
const existed = await this.has(hash);
|
|
89
|
+
if (existed) {
|
|
90
|
+
await this.db.blobs.delete(hashHex);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
console.error('[DexieStore] delete error:', e);
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get all stored hashes
|
|
102
|
+
*/
|
|
103
|
+
async keys() {
|
|
104
|
+
try {
|
|
105
|
+
// Only fetch the primary keys, not the blob data
|
|
106
|
+
const hashHexes = await this.db.blobs.toCollection().primaryKeys();
|
|
107
|
+
return hashHexes.map(hex => fromHex(hex));
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
console.error('[DexieStore] keys error:', e);
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Clear all data
|
|
116
|
+
*/
|
|
117
|
+
async clear() {
|
|
118
|
+
try {
|
|
119
|
+
await this.db.blobs.clear();
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
console.error('[DexieStore] clear error:', e);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get count of stored items
|
|
127
|
+
*/
|
|
128
|
+
async count() {
|
|
129
|
+
try {
|
|
130
|
+
return await this.db.blobs.count();
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
console.error('[DexieStore] count error:', e);
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get total bytes stored
|
|
139
|
+
* Uses cursor to avoid loading all blobs into memory at once
|
|
140
|
+
*/
|
|
141
|
+
async totalBytes() {
|
|
142
|
+
try {
|
|
143
|
+
let total = 0;
|
|
144
|
+
await this.db.blobs.each(entry => {
|
|
145
|
+
total += entry.data.byteLength;
|
|
146
|
+
});
|
|
147
|
+
return total;
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
console.error('[DexieStore] totalBytes error:', e);
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Evict least-recently-used entries until totalBytes is below maxBytes.
|
|
156
|
+
* Returns the number of entries deleted.
|
|
157
|
+
*/
|
|
158
|
+
async evict(maxBytes) {
|
|
159
|
+
try {
|
|
160
|
+
const currentBytes = await this.totalBytes();
|
|
161
|
+
if (currentBytes <= maxBytes)
|
|
162
|
+
return 0;
|
|
163
|
+
// Get entries sorted by lastAccess (oldest first)
|
|
164
|
+
const entries = await this.db.blobs.orderBy('lastAccess').toArray();
|
|
165
|
+
let bytesRemoved = 0;
|
|
166
|
+
let entriesRemoved = 0;
|
|
167
|
+
const targetRemoval = currentBytes - maxBytes;
|
|
168
|
+
for (const entry of entries) {
|
|
169
|
+
if (bytesRemoved >= targetRemoval)
|
|
170
|
+
break;
|
|
171
|
+
await this.db.blobs.delete(entry.hashHex);
|
|
172
|
+
bytesRemoved += entry.data.byteLength;
|
|
173
|
+
entriesRemoved++;
|
|
174
|
+
}
|
|
175
|
+
console.log(`[DexieStore] Evicted ${entriesRemoved} entries (${bytesRemoved} bytes)`);
|
|
176
|
+
return entriesRemoved;
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
console.error('[DexieStore] evict error:', e);
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Close the database connection
|
|
185
|
+
*/
|
|
186
|
+
close() {
|
|
187
|
+
this.db.close();
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Delete the entire database
|
|
191
|
+
*/
|
|
192
|
+
static async deleteDatabase(dbName = 'hashtree') {
|
|
193
|
+
await Dexie.delete(dbName);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=dexie.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dexie.js","sourceRoot":"","sources":["../../src/store/dexie.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FallbackStore - Store with cascading fallback sources
|
|
3
|
+
*
|
|
4
|
+
* Tries stores in order until data is found.
|
|
5
|
+
* Caches successful remote fetches to primary store.
|
|
6
|
+
*
|
|
7
|
+
* Example: local (Dexie) -> WebRTC -> Blossom
|
|
8
|
+
*/
|
|
9
|
+
import type { Store, Hash } from '../types.js';
|
|
10
|
+
/** Minimal interface for read-only fallback sources */
|
|
11
|
+
export interface ReadableStore {
|
|
12
|
+
get(hash: Hash): Promise<Uint8Array | null>;
|
|
13
|
+
}
|
|
14
|
+
/** Minimal interface for writable stores (optional put for fire-and-forget writes) */
|
|
15
|
+
export interface WritableStore extends ReadableStore {
|
|
16
|
+
put?(hash: Hash, data: Uint8Array): Promise<boolean>;
|
|
17
|
+
}
|
|
18
|
+
export interface FallbackStoreConfig {
|
|
19
|
+
/** Primary local store (reads/writes) */
|
|
20
|
+
primary: Store;
|
|
21
|
+
/** Fallback stores to try in order (read-only, writes are fire-and-forget) */
|
|
22
|
+
fallbacks: WritableStore[];
|
|
23
|
+
/** Timeout for fallback stores (ms) */
|
|
24
|
+
timeout?: number;
|
|
25
|
+
}
|
|
26
|
+
export declare class FallbackStore implements Store {
|
|
27
|
+
private primary;
|
|
28
|
+
private fallbacks;
|
|
29
|
+
private timeout;
|
|
30
|
+
constructor(config: FallbackStoreConfig);
|
|
31
|
+
put(hash: Hash, data: Uint8Array): Promise<boolean>;
|
|
32
|
+
get(hash: Hash): Promise<Uint8Array | null>;
|
|
33
|
+
has(hash: Hash): Promise<boolean>;
|
|
34
|
+
delete(hash: Hash): Promise<boolean>;
|
|
35
|
+
/** Add a fallback store dynamically */
|
|
36
|
+
addFallback(store: WritableStore): void;
|
|
37
|
+
/** Remove a fallback store */
|
|
38
|
+
removeFallback(store: WritableStore): void;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=fallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../../src/store/fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAE/C,uDAAuD;AACvD,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;CAC7C;AAED,sFAAsF;AACtF,MAAM,WAAW,aAAc,SAAQ,aAAa;IAClD,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,mBAAmB;IAClC,yCAAyC;IACzC,OAAO,EAAE,KAAK,CAAC;IACf,8EAA8E;IAC9E,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,aAAc,YAAW,KAAK;IACzC,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,mBAAmB;IAMjC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBnD,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA4B3C,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAIjC,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAI1C,uCAAuC;IACvC,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAIvC,8BAA8B;IAC9B,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;CAI3C"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FallbackStore - Store with cascading fallback sources
|
|
3
|
+
*
|
|
4
|
+
* Tries stores in order until data is found.
|
|
5
|
+
* Caches successful remote fetches to primary store.
|
|
6
|
+
*
|
|
7
|
+
* Example: local (Dexie) -> WebRTC -> Blossom
|
|
8
|
+
*/
|
|
9
|
+
export class FallbackStore {
|
|
10
|
+
primary;
|
|
11
|
+
fallbacks;
|
|
12
|
+
timeout;
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.primary = config.primary;
|
|
15
|
+
this.fallbacks = config.fallbacks;
|
|
16
|
+
this.timeout = config.timeout ?? 5000;
|
|
17
|
+
}
|
|
18
|
+
async put(hash, data) {
|
|
19
|
+
// Write to primary
|
|
20
|
+
const success = await this.primary.put(hash, data);
|
|
21
|
+
// Fire-and-forget writes to fallback stores (if they support put)
|
|
22
|
+
for (const store of this.fallbacks) {
|
|
23
|
+
if (store.put) {
|
|
24
|
+
store.put(hash, data).catch(() => {
|
|
25
|
+
// Silently ignore - fallbacks are best-effort
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return success;
|
|
30
|
+
}
|
|
31
|
+
async get(hash) {
|
|
32
|
+
// Try primary first
|
|
33
|
+
let data = await this.primary.get(hash);
|
|
34
|
+
if (data)
|
|
35
|
+
return data;
|
|
36
|
+
// Try fallbacks with timeout
|
|
37
|
+
for (const store of this.fallbacks) {
|
|
38
|
+
try {
|
|
39
|
+
const fetchPromise = store.get(hash);
|
|
40
|
+
const timeoutPromise = new Promise(resolve => setTimeout(() => resolve(null), this.timeout));
|
|
41
|
+
data = await Promise.race([fetchPromise, timeoutPromise]);
|
|
42
|
+
if (data) {
|
|
43
|
+
// Cache to primary
|
|
44
|
+
await this.primary.put(hash, data);
|
|
45
|
+
return data;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Continue to next fallback
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
async has(hash) {
|
|
55
|
+
return this.primary.has(hash);
|
|
56
|
+
}
|
|
57
|
+
async delete(hash) {
|
|
58
|
+
return this.primary.delete(hash);
|
|
59
|
+
}
|
|
60
|
+
/** Add a fallback store dynamically */
|
|
61
|
+
addFallback(store) {
|
|
62
|
+
this.fallbacks.push(store);
|
|
63
|
+
}
|
|
64
|
+
/** Remove a fallback store */
|
|
65
|
+
removeFallback(store) {
|
|
66
|
+
const idx = this.fallbacks.indexOf(store);
|
|
67
|
+
if (idx >= 0)
|
|
68
|
+
this.fallbacks.splice(idx, 1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fallback.js","sourceRoot":"","sources":["../../src/store/fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH,MAAM,OAAO,aAAa;IAChB,OAAO,CAAQ;IACf,SAAS,CAAkB;IAC3B,OAAO,CAAS;IAExB,YAAY,MAA2B;QACrC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAU,EAAE,IAAgB;QACpC,mBAAmB;QACnB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAEnD,kEAAkE;QAClE,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnC,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;gBACd,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;oBAC/B,8CAA8C;gBAChD,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAU;QAClB,oBAAoB;QACpB,IAAI,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QAEtB,6BAA6B;QAC7B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACrC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,CACjD,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAC9C,CAAC;gBAEF,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;gBAE1D,IAAI,IAAI,EAAE,CAAC;oBACT,mBAAmB;oBACnB,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBACnC,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,4BAA4B;YAC9B,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAU;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAU;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,uCAAuC;IACvC,WAAW,CAAC,KAAoB;QAC9B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,8BAA8B;IAC9B,cAAc,CAAC,KAAoB;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,GAAG,IAAI,CAAC;YAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC;CACF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { MemoryStore } from './memory.js';
|
|
2
|
+
export { OpfsStore, type OpfsStoreOptions } from './opfs.js';
|
|
3
|
+
export { BlossomStore, type BlossomStoreConfig, type BlossomServer, type BlossomSigner, type BlossomAuthEvent } from './blossom.js';
|
|
4
|
+
export { DexieStore } from './dexie.js';
|
|
5
|
+
export { FallbackStore, type FallbackStoreConfig, type ReadableStore, type WritableStore } from './fallback.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACpI,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAyB,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,YAAY,EAA0F,MAAM,cAAc,CAAC;AACpI,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,aAAa,EAAoE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory content-addressed store
|
|
3
|
+
* Useful for testing and temporary data
|
|
4
|
+
*/
|
|
5
|
+
import { Store, Hash } from '../types.js';
|
|
6
|
+
export declare class MemoryStore implements Store {
|
|
7
|
+
private data;
|
|
8
|
+
put(hash: Hash, data: Uint8Array): Promise<boolean>;
|
|
9
|
+
get(hash: Hash): Promise<Uint8Array | null>;
|
|
10
|
+
has(hash: Hash): Promise<boolean>;
|
|
11
|
+
delete(hash: Hash): Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* Get number of stored items
|
|
14
|
+
*/
|
|
15
|
+
get size(): number;
|
|
16
|
+
/**
|
|
17
|
+
* Get total bytes stored
|
|
18
|
+
*/
|
|
19
|
+
get totalBytes(): number;
|
|
20
|
+
/**
|
|
21
|
+
* Clear all data
|
|
22
|
+
*/
|
|
23
|
+
clear(): void;
|
|
24
|
+
/**
|
|
25
|
+
* List all hashes
|
|
26
|
+
*/
|
|
27
|
+
keys(): Hash[];
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/store/memory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAS,MAAM,aAAa,CAAC;AAEjD,qBAAa,WAAY,YAAW,KAAK;IACvC,OAAO,CAAC,IAAI,CAAiC;IAEvC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAUnD,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAQ3C,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAIjC,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAI1C;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAMvB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,IAAI,IAAI,EAAE;CASf"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory content-addressed store
|
|
3
|
+
* Useful for testing and temporary data
|
|
4
|
+
*/
|
|
5
|
+
import { toHex } from '../types.js';
|
|
6
|
+
export class MemoryStore {
|
|
7
|
+
data = new Map();
|
|
8
|
+
async put(hash, data) {
|
|
9
|
+
const key = toHex(hash);
|
|
10
|
+
if (this.data.has(key)) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
// Store a copy to prevent external mutation
|
|
14
|
+
this.data.set(key, new Uint8Array(data));
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
async get(hash) {
|
|
18
|
+
const key = toHex(hash);
|
|
19
|
+
const data = this.data.get(key);
|
|
20
|
+
if (!data)
|
|
21
|
+
return null;
|
|
22
|
+
// Return a copy to prevent external mutation
|
|
23
|
+
return new Uint8Array(data);
|
|
24
|
+
}
|
|
25
|
+
async has(hash) {
|
|
26
|
+
return this.data.has(toHex(hash));
|
|
27
|
+
}
|
|
28
|
+
async delete(hash) {
|
|
29
|
+
return this.data.delete(toHex(hash));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get number of stored items
|
|
33
|
+
*/
|
|
34
|
+
get size() {
|
|
35
|
+
return this.data.size;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get total bytes stored
|
|
39
|
+
*/
|
|
40
|
+
get totalBytes() {
|
|
41
|
+
let total = 0;
|
|
42
|
+
for (const data of this.data.values()) {
|
|
43
|
+
total += data.length;
|
|
44
|
+
}
|
|
45
|
+
return total;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Clear all data
|
|
49
|
+
*/
|
|
50
|
+
clear() {
|
|
51
|
+
this.data.clear();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* List all hashes
|
|
55
|
+
*/
|
|
56
|
+
keys() {
|
|
57
|
+
return Array.from(this.data.keys()).map(hex => {
|
|
58
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
59
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
60
|
+
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
|
|
61
|
+
}
|
|
62
|
+
return bytes;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/store/memory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAe,KAAK,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,OAAO,WAAW;IACd,IAAI,GAAG,IAAI,GAAG,EAAsB,CAAC;IAE7C,KAAK,CAAC,GAAG,CAAC,IAAU,EAAE,IAAgB;QACpC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,4CAA4C;QAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAU;QAClB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,6CAA6C;QAC7C,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAU;QAClB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAU;QACrB,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,IAAI,UAAU;QACZ,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACtC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;QACvB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YAC5C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAChD,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OPFS (Origin Private File System) content-addressed store
|
|
3
|
+
* Persistent browser storage using the File System Access API
|
|
4
|
+
*
|
|
5
|
+
* Files are stored as: <dirName>/<first2chars>/<hash>.bin
|
|
6
|
+
* This provides sharding to avoid too many files in one directory.
|
|
7
|
+
*/
|
|
8
|
+
import { Store, Hash } from '../types.js';
|
|
9
|
+
export interface OpfsStoreOptions {
|
|
10
|
+
/** Directory name in OPFS root (default: 'hashtree') */
|
|
11
|
+
dirName?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare class OpfsStore implements Store {
|
|
14
|
+
private dirName;
|
|
15
|
+
private rootDir;
|
|
16
|
+
private storeDir;
|
|
17
|
+
private initPromise;
|
|
18
|
+
constructor(options?: OpfsStoreOptions | string);
|
|
19
|
+
/**
|
|
20
|
+
* Get or create the store directory (with deduplication)
|
|
21
|
+
*/
|
|
22
|
+
private getStoreDir;
|
|
23
|
+
/**
|
|
24
|
+
* Get shard directory for a hash (first 2 hex chars)
|
|
25
|
+
*/
|
|
26
|
+
private getShardDir;
|
|
27
|
+
put(hash: Hash, data: Uint8Array): Promise<boolean>;
|
|
28
|
+
get(hash: Hash): Promise<Uint8Array | null>;
|
|
29
|
+
has(hash: Hash): Promise<boolean>;
|
|
30
|
+
delete(hash: Hash): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Get all stored hashes
|
|
33
|
+
*/
|
|
34
|
+
keys(): Promise<Hash[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Clear all data
|
|
37
|
+
*/
|
|
38
|
+
clear(): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Get count of stored items
|
|
41
|
+
*/
|
|
42
|
+
count(): Promise<number>;
|
|
43
|
+
/**
|
|
44
|
+
* Get total bytes stored
|
|
45
|
+
*/
|
|
46
|
+
totalBytes(): Promise<number>;
|
|
47
|
+
/**
|
|
48
|
+
* Close - cleanup any resources
|
|
49
|
+
*/
|
|
50
|
+
close(): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Delete the entire store directory
|
|
53
|
+
*/
|
|
54
|
+
static deleteStore(dirName?: string): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=opfs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opfs.d.ts","sourceRoot":"","sources":["../../src/store/opfs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAkB,MAAM,aAAa,CAAC;AAI1D,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,SAAU,YAAW,KAAK;IACrC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAA0C;IACzD,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,WAAW,CAAmD;gBAE1D,OAAO,GAAE,gBAAgB,GAAG,MAAyB;IAQjE;;OAEG;YACW,WAAW;IAezB;;OAEG;YACW,WAAW;IAWnB,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BnD,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAiB3C,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAajC,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAa1C;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAoB7B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAK9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAoBnC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B;;OAEG;WACU,WAAW,CAAC,OAAO,GAAE,MAAyB,GAAG,OAAO,CAAC,IAAI,CAAC;CAQ5E"}
|