@leofcoin/peernet 0.16.6 → 0.17.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/README.md +1 -0
- package/exports/browser/browser-2f0b2829.js +190 -0
- package/exports/browser/browser-3c1d0477.js +73 -0
- package/exports/browser/browser-store.js +463 -0
- package/exports/browser/client-29660363.js +690 -0
- package/exports/browser/index-019272d8.js +11486 -0
- package/exports/browser/index-3a25de4d.js +34 -0
- package/exports/browser/messages-4850566c.js +303 -0
- package/exports/browser/pako.esm-aa674ebf.js +6876 -0
- package/exports/browser/peernet-379769d5.js +2896 -0
- package/exports/browser/peernet.js +2 -0
- package/exports/browser/value-40634404.js +64 -0
- package/{dist/module/messages-bce1b91d.js → exports/messages-796c4d5c.js} +0 -0
- package/{dist/module → exports}/peernet.js +85 -166
- package/exports/store.js +225 -0
- package/index.html +2 -2
- package/package.json +19 -4
- package/rollup.config.js +30 -0
- package/src/{peernet.js → peernet.ts} +6 -4
- package/tsconfig.json +19 -0
- package/dist/commonjs/dht-response.js +0 -28
- package/dist/commonjs/dht.js +0 -39
- package/dist/commonjs/messages-f46a3ca1.js +0 -194
- package/dist/commonjs/peernet.js +0 -1126
- package/dist/commonjs/peernet2.js +0 -30
- package/dist/commonjs/request.js +0 -27
- package/dist/commonjs/response.js +0 -27
- package/src/server.js +0 -24
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// import base32 from '@vandeurenglenn/base32'
|
|
2
|
+
// import base58 from '@vandeurenglenn/base58'
|
|
3
|
+
|
|
4
|
+
// export const encodings = {
|
|
5
|
+
// base58,
|
|
6
|
+
// base32
|
|
7
|
+
// }
|
|
8
|
+
|
|
9
|
+
const encode = (string, encoding = 'utf-8') => {
|
|
10
|
+
if (typeof string === 'string') {
|
|
11
|
+
let encoded;
|
|
12
|
+
|
|
13
|
+
// if (encodings[encoding]) encoded = encodings[encoding].encode(encoded)
|
|
14
|
+
encoded = new TextEncoder().encode(string);
|
|
15
|
+
return encoded
|
|
16
|
+
}
|
|
17
|
+
throw Error(`expected typeof String instead got ${string}`)
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const decode = (uint8Array, encoding) => {
|
|
21
|
+
if (uint8Array instanceof Uint8Array) {
|
|
22
|
+
let decoded;
|
|
23
|
+
// if (encodings[encoding]) decoded = encodings[encoding].decode(decoded)
|
|
24
|
+
decoded = new TextDecoder().decode(uint8Array);
|
|
25
|
+
|
|
26
|
+
return decoded
|
|
27
|
+
}
|
|
28
|
+
throw Error(`expected typeof uint8Array instead got ${uint8Array}`)
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
class KeyValue {
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {string | Uint8Array} input
|
|
35
|
+
*/
|
|
36
|
+
constructor(input) {
|
|
37
|
+
if (typeof input === 'string') {
|
|
38
|
+
this.uint8Array = encode(input);
|
|
39
|
+
} else if (input instanceof Uint8Array) {
|
|
40
|
+
this.uint8Array = input;
|
|
41
|
+
} else if (input instanceof KeyValue) {
|
|
42
|
+
this.uint8Array = input.uint8Array;
|
|
43
|
+
} else {
|
|
44
|
+
throw new Error('Invalid KeyValue, should be a String, Uint8Array or KeyValue')
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
isKeyValue() {
|
|
49
|
+
return true
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Convert to the string representation
|
|
54
|
+
*
|
|
55
|
+
* @param {import('uint8arrays/to-string').SupportedEncodings} [encoding='utf8'] - The encoding to use.
|
|
56
|
+
* @returns {string}
|
|
57
|
+
*/
|
|
58
|
+
toString(encoding = 'utf8') {
|
|
59
|
+
return decode(this.uint8Array)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { KeyValue as K };
|
|
File without changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '@vandeurenglenn/debug';
|
|
2
2
|
import PubSub from '@vandeurenglenn/little-pubsub';
|
|
3
|
-
import { Codec } from '@leofcoin/codec-format-interface';
|
|
4
|
-
import LeofcoinStorage from '@leofcoin/storage
|
|
3
|
+
import { Codec, codecs } from '@leofcoin/codec-format-interface';
|
|
4
|
+
import LeofcoinStorage from '@leofcoin/storage';
|
|
5
5
|
|
|
6
6
|
const BufferToUint8Array = data => {
|
|
7
7
|
if (data.type === 'Buffer') {
|
|
@@ -259,94 +259,6 @@ class DhtEarth {
|
|
|
259
259
|
}
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
-
var codecs = {
|
|
263
|
-
// just a hash
|
|
264
|
-
'disco-hash': {
|
|
265
|
-
codec: parseInt('30', 16),
|
|
266
|
-
hashAlg: 'dbl-keccak-256', // ,
|
|
267
|
-
// testnet: 'olivia'
|
|
268
|
-
},
|
|
269
|
-
'peernet-peer-response': {
|
|
270
|
-
codec: parseInt('707072', 16),
|
|
271
|
-
hashAlg: 'keccak-256',
|
|
272
|
-
},
|
|
273
|
-
'peernet-peer': {
|
|
274
|
-
codec: parseInt('7070', 16),
|
|
275
|
-
hashAlg: 'keccak-256',
|
|
276
|
-
},
|
|
277
|
-
'peernet-dht': {
|
|
278
|
-
codec: parseInt('706468', 16),
|
|
279
|
-
hashAlg: 'keccak-256',
|
|
280
|
-
},
|
|
281
|
-
'peernet-dht-response': {
|
|
282
|
-
codec: parseInt('706472', 16),
|
|
283
|
-
hashAlg: 'keccak-256',
|
|
284
|
-
},
|
|
285
|
-
// data
|
|
286
|
-
'peernet-data': {
|
|
287
|
-
codec: parseInt('706461', 16),
|
|
288
|
-
hashAlg: 'keccak-256',
|
|
289
|
-
},
|
|
290
|
-
'peernet-data-response': {
|
|
291
|
-
codec: parseInt('70646172', 16),
|
|
292
|
-
hashAlg: 'keccak-256',
|
|
293
|
-
},
|
|
294
|
-
// message
|
|
295
|
-
'peernet-message': {
|
|
296
|
-
codec: parseInt('706d65', 16),
|
|
297
|
-
hashAlg: 'keccak-256',
|
|
298
|
-
},
|
|
299
|
-
// pubsub
|
|
300
|
-
'peernet-ps': {
|
|
301
|
-
codec: parseInt('707073', 16),
|
|
302
|
-
hashAlg: 'keccak-256',
|
|
303
|
-
},
|
|
304
|
-
'peernet-response': {
|
|
305
|
-
codec: parseInt('7072', 16),
|
|
306
|
-
hashAlg: 'keccak-256',
|
|
307
|
-
},
|
|
308
|
-
'peernet-request': {
|
|
309
|
-
codec: parseInt('707271', 16),
|
|
310
|
-
hashAlg: 'keccak-256',
|
|
311
|
-
},
|
|
312
|
-
// normal block
|
|
313
|
-
'leofcoin-block': {
|
|
314
|
-
codec: parseInt('6c62', 16),
|
|
315
|
-
hashAlg: 'dbl-keccak-512', // ,
|
|
316
|
-
// testnet: 'olivia'
|
|
317
|
-
},
|
|
318
|
-
'leofcoin-tx': {
|
|
319
|
-
codec: parseInt('6c74', 16),
|
|
320
|
-
hashAlg: 'dbl-keccak-512', // ,
|
|
321
|
-
// testnet: 'olivia'
|
|
322
|
-
},
|
|
323
|
-
// itx
|
|
324
|
-
'leofcoin-itx': {
|
|
325
|
-
codec: parseInt('6c69', 16),
|
|
326
|
-
hashAlg: 'keccak-512', // ,
|
|
327
|
-
// testnet: 'olivia'
|
|
328
|
-
},
|
|
329
|
-
// peer reputation
|
|
330
|
-
'leofcoin-pr': {
|
|
331
|
-
codec: parseInt('6c70', 16),
|
|
332
|
-
hashAlg: 'keccak-256', // ,
|
|
333
|
-
// testnet: 'olivia'
|
|
334
|
-
},
|
|
335
|
-
// chat message
|
|
336
|
-
'chat-message': {
|
|
337
|
-
codec: parseInt('70636d', 16),
|
|
338
|
-
hashAlg: 'dbl-keccak-256',
|
|
339
|
-
},
|
|
340
|
-
'peernet-file' : {
|
|
341
|
-
codec: parseInt('7066', 16),
|
|
342
|
-
hashAlg: 'keccak-256',
|
|
343
|
-
},
|
|
344
|
-
'peernet-file-response' : {
|
|
345
|
-
codec: parseInt('706672', 16),
|
|
346
|
-
hashAlg: 'keccak-256',
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
|
|
350
262
|
class MessageHandler {
|
|
351
263
|
constructor(network) {
|
|
352
264
|
this.network = network;
|
|
@@ -381,7 +293,7 @@ class MessageHandler {
|
|
|
381
293
|
* or the messageNode itself
|
|
382
294
|
*/
|
|
383
295
|
async prepareMessage(message) {
|
|
384
|
-
if (message.keys.
|
|
296
|
+
if (message.keys.includes('signature')) {
|
|
385
297
|
message = await this.hashAndSignMessage(message);
|
|
386
298
|
}
|
|
387
299
|
|
|
@@ -440,13 +352,12 @@ class Peernet {
|
|
|
440
352
|
this.network = options.network || 'leofcoin';
|
|
441
353
|
this.stars = options.stars;
|
|
442
354
|
const parts = this.network.split(':');
|
|
443
|
-
this.networkVersion = options.networkVersion
|
|
355
|
+
this.networkVersion = options.networkVersion || parts.length > 1 ? parts[1] : 'mainnet';
|
|
444
356
|
|
|
445
357
|
if (!options.storePrefix) options.storePrefix = 'lfc';
|
|
446
358
|
if (!options.port) options.port = 2000;
|
|
447
359
|
if (!options.root) {
|
|
448
|
-
|
|
449
|
-
else options.root = `.${this.network}`;
|
|
360
|
+
parts[1] ? options.root = `.${parts[0]}/${parts[1]}` : options.root = `.${this.network}`;
|
|
450
361
|
}
|
|
451
362
|
|
|
452
363
|
globalThis.peernet = this;
|
|
@@ -461,10 +372,6 @@ class Peernet {
|
|
|
461
372
|
return ['account', 'wallet', 'block', 'transaction', 'chain', 'data', 'message']
|
|
462
373
|
}
|
|
463
374
|
|
|
464
|
-
get codecs() {
|
|
465
|
-
return codecs
|
|
466
|
-
}
|
|
467
|
-
|
|
468
375
|
addProto(name, proto) {
|
|
469
376
|
if (!globalThis.peernet.protos[name]) globalThis.peernet.protos[name] = proto;
|
|
470
377
|
}
|
|
@@ -478,13 +385,13 @@ class Peernet {
|
|
|
478
385
|
name === 'data' || name === 'message') isPrivate = false;
|
|
479
386
|
|
|
480
387
|
let Storage;
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
388
|
+
|
|
389
|
+
this.hasDaemon ? Storage = LeofcoinStorageClient : Storage = LeofcoinStorage;
|
|
390
|
+
|
|
391
|
+
if (!globalThis[`${name}Store`]) {
|
|
392
|
+
globalThis[`${name}Store`] = new Storage(name, root);
|
|
393
|
+
await globalThis[`${name}Store`].init();
|
|
485
394
|
}
|
|
486
|
-
globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
|
|
487
|
-
await new Storage(name, root);
|
|
488
395
|
|
|
489
396
|
globalThis[`${name}Store`].private = isPrivate;
|
|
490
397
|
if (!isPrivate) this.stores.push(name);
|
|
@@ -542,6 +449,7 @@ class Peernet {
|
|
|
542
449
|
* @property {Object} peer Instance of Peer
|
|
543
450
|
*/
|
|
544
451
|
this.stores = [];
|
|
452
|
+
this.codecs = {...codecs};
|
|
545
453
|
this.requestProtos = {};
|
|
546
454
|
this.storePrefix = options.storePrefix;
|
|
547
455
|
this.root = options.root;
|
|
@@ -560,7 +468,7 @@ class Peernet {
|
|
|
560
468
|
ChatMessage,
|
|
561
469
|
PeernetFile
|
|
562
470
|
// FolderMessageResponse
|
|
563
|
-
} = await import(/* webpackChunkName: "messages" */ './messages-
|
|
471
|
+
} = await import(/* webpackChunkName: "messages" */ './messages-796c4d5c.js');
|
|
564
472
|
|
|
565
473
|
/**
|
|
566
474
|
* proto Object containing protos
|
|
@@ -591,7 +499,7 @@ class Peernet {
|
|
|
591
499
|
|
|
592
500
|
const {daemon, environment} = await target();
|
|
593
501
|
this.hasDaemon = daemon;
|
|
594
|
-
|
|
502
|
+
|
|
595
503
|
for (const store of this.defaultStores) {
|
|
596
504
|
await this.addStore(store, options.storePrefix, options.root);
|
|
597
505
|
}
|
|
@@ -609,7 +517,7 @@ class Peernet {
|
|
|
609
517
|
// TODO: remove when on mainnet
|
|
610
518
|
try {
|
|
611
519
|
this.accounts = JSON.parse(accounts);
|
|
612
|
-
} catch
|
|
520
|
+
} catch {
|
|
613
521
|
this.accounts = [accounts.split(',')];
|
|
614
522
|
}
|
|
615
523
|
} else {
|
|
@@ -648,13 +556,13 @@ class Peernet {
|
|
|
648
556
|
pubsub.subscribe('peer:data', dataHandler);
|
|
649
557
|
|
|
650
558
|
|
|
651
|
-
const importee = await import(/* webpackChunkName: "peernet-swarm" */ '@leofcoin/peernet-swarm');
|
|
559
|
+
const importee = await import(/* webpackChunkName: "peernet-swarm" */ '@leofcoin/peernet-swarm/client');
|
|
652
560
|
/**
|
|
653
561
|
* @access public
|
|
654
562
|
* @type {PeernetClient}
|
|
655
563
|
*/
|
|
656
564
|
this.client = new importee.default(this.id, this.networkVersion, this.stars);
|
|
657
|
-
if (globalThis.
|
|
565
|
+
if (globalThis.navigator) {
|
|
658
566
|
globalThis.addEventListener('beforeunload', async () => this.client.close());
|
|
659
567
|
} else {
|
|
660
568
|
process.on('SIGTERM', async () => {
|
|
@@ -678,6 +586,49 @@ class Peernet {
|
|
|
678
586
|
|
|
679
587
|
}
|
|
680
588
|
|
|
589
|
+
async handleDHT(peer, id, proto) {
|
|
590
|
+
let { hash, store } = proto.decoded;
|
|
591
|
+
let has;
|
|
592
|
+
|
|
593
|
+
if (store) {
|
|
594
|
+
store = globalThis[`${store}Store`];
|
|
595
|
+
has = store.private ? false : await store.has(hash);
|
|
596
|
+
} else {
|
|
597
|
+
has = await this.has(hash);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
const data = await new globalThis.peernet.protos['peernet-dht-response']({hash, has});
|
|
601
|
+
const node = await this.prepareMessage(data);
|
|
602
|
+
|
|
603
|
+
this.sendMessage(peer, id, node.encoded);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
async handleData(peer, id, proto) {
|
|
607
|
+
let { hash, store } = proto.decoded;
|
|
608
|
+
let data;
|
|
609
|
+
store = globalThis[`${store}Store`] || await this.whichStore([...this.stores], hash);
|
|
610
|
+
|
|
611
|
+
if (store && !store.private) {
|
|
612
|
+
data = await store.get(hash);
|
|
613
|
+
|
|
614
|
+
if (data) {
|
|
615
|
+
data = await new globalThis.peernet.protos['peernet-data-response']({hash, data});
|
|
616
|
+
|
|
617
|
+
const node = await this.prepareMessage(data);
|
|
618
|
+
this.sendMessage(peer, id, node.encoded);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
async handleRequest(peer, id, proto) {
|
|
624
|
+
const method = this.requestProtos[proto.decoded.request];
|
|
625
|
+
if (method) {
|
|
626
|
+
const data = await method();
|
|
627
|
+
const node = await this.prepareMessage(data);
|
|
628
|
+
this.sendMessage(peer, id, node.encoded);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
681
632
|
/**
|
|
682
633
|
* @private
|
|
683
634
|
*
|
|
@@ -685,54 +636,25 @@ class Peernet {
|
|
|
685
636
|
* @param {PeernetPeer} peer - peernet peer
|
|
686
637
|
*/
|
|
687
638
|
async _protoHandler(message, peer, from) {
|
|
688
|
-
|
|
689
639
|
const {id, proto} = message;
|
|
690
640
|
this.bw.down += proto.encoded.length;
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
const node = await this.prepareMessage(data);
|
|
704
|
-
|
|
705
|
-
this.sendMessage(peer, id, node.encoded);
|
|
706
|
-
} else if (proto.name === 'peernet-data') {
|
|
707
|
-
let { hash, store } = proto.decoded;
|
|
708
|
-
let data;
|
|
709
|
-
if (!store) {
|
|
710
|
-
store = await this.whichStore([...this.stores], hash);
|
|
711
|
-
} else {
|
|
712
|
-
store = globalThis[`${store}Store`];
|
|
713
|
-
}
|
|
714
|
-
if (store && !store.private) {
|
|
715
|
-
data = await store.get(hash);
|
|
716
|
-
|
|
717
|
-
if (data) {
|
|
718
|
-
data = await new globalThis.peernet.protos['peernet-data-response']({hash, data});
|
|
719
|
-
|
|
720
|
-
const node = await this.prepareMessage(data);
|
|
721
|
-
this.sendMessage(peer, id, node.encoded);
|
|
722
|
-
}
|
|
723
|
-
}
|
|
641
|
+
switch(proto.name) {
|
|
642
|
+
case 'peernet-dht': {
|
|
643
|
+
this.handleDHT(peer, id, proto);
|
|
644
|
+
break
|
|
645
|
+
}
|
|
646
|
+
case 'peenet-data': {
|
|
647
|
+
this.handleData(peer, id, proto);
|
|
648
|
+
break
|
|
649
|
+
}
|
|
650
|
+
case 'peernet-request': {
|
|
651
|
+
this.handleRequest(peer, id, proto);
|
|
652
|
+
}
|
|
724
653
|
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
if (method) {
|
|
728
|
-
const data = await method();
|
|
729
|
-
const node = await this.prepareMessage(data);
|
|
730
|
-
this.sendMessage(peer, id, node.encoded);
|
|
731
|
-
}
|
|
732
|
-
} else if (proto.name === 'peernet-ps' && peer.peerId !== this.id) {
|
|
733
|
-
globalSub.publish(proto.decoded.topic, proto.decoded.data);
|
|
654
|
+
case 'peernet-ps': {
|
|
655
|
+
if (peer.peerId !== this.id) globalSub.publish(proto.decoded.topic, proto.decoded.data);
|
|
734
656
|
}
|
|
735
|
-
|
|
657
|
+
}
|
|
736
658
|
}
|
|
737
659
|
|
|
738
660
|
/**
|
|
@@ -839,7 +761,7 @@ class Peernet {
|
|
|
839
761
|
// get closest peer on earth
|
|
840
762
|
const closestPeer = await this.dht.closestPeer(providers);
|
|
841
763
|
// get peer instance by id
|
|
842
|
-
if (!closestPeer || !closestPeer.id) return this.requestData(hash, store?.name
|
|
764
|
+
if (!closestPeer || !closestPeer.id) return this.requestData(hash, store?.name || store)
|
|
843
765
|
|
|
844
766
|
const id = closestPeer.id;
|
|
845
767
|
if (this.connections) {
|
|
@@ -847,7 +769,7 @@ class Peernet {
|
|
|
847
769
|
if (peer.peerId === id) return peer
|
|
848
770
|
});
|
|
849
771
|
|
|
850
|
-
let data = await new globalThis.peernet.protos['peernet-data']({hash, store: store?.name
|
|
772
|
+
let data = await new globalThis.peernet.protos['peernet-data']({hash, store: store?.name || store});
|
|
851
773
|
|
|
852
774
|
const node = await this.prepareMessage(data);
|
|
853
775
|
if (closest[0]) data = await closest[0].request(node.encoded);
|
|
@@ -864,7 +786,7 @@ class Peernet {
|
|
|
864
786
|
|
|
865
787
|
// this.put(hash, proto.decoded.data)
|
|
866
788
|
}
|
|
867
|
-
return
|
|
789
|
+
return
|
|
868
790
|
}
|
|
869
791
|
|
|
870
792
|
|
|
@@ -970,8 +892,7 @@ class Peernet {
|
|
|
970
892
|
async ls(hash, options) {
|
|
971
893
|
let data;
|
|
972
894
|
const has = await dataStore.has(hash);
|
|
973
|
-
|
|
974
|
-
else data = await this.requestData(hash, 'data');
|
|
895
|
+
data = has ? await dataStore.get(hash) : await this.requestData(hash, 'data');
|
|
975
896
|
|
|
976
897
|
const node = await new peernet.protos['peernet-file'](data);
|
|
977
898
|
await node.decode();
|
|
@@ -988,8 +909,7 @@ class Peernet {
|
|
|
988
909
|
async cat(hash, options) {
|
|
989
910
|
let data;
|
|
990
911
|
const has = await dataStore.has(hash);
|
|
991
|
-
|
|
992
|
-
else data = await this.requestData(hash, 'data');
|
|
912
|
+
data = has ? await dataStore.get(hash) : await this.requestData(hash, 'data');
|
|
993
913
|
const node = await new peernet.protos['peernet-file'](data);
|
|
994
914
|
|
|
995
915
|
if (node.decoded?.links.length > 0) throw new Error(`${hash} is a directory`)
|
|
@@ -1009,7 +929,7 @@ class Peernet {
|
|
|
1009
929
|
const has = await store.has(hash);
|
|
1010
930
|
if (has) return store
|
|
1011
931
|
if (stores.length > 0) return this.whichStore(stores, hash)
|
|
1012
|
-
} else return
|
|
932
|
+
} else return
|
|
1013
933
|
}
|
|
1014
934
|
|
|
1015
935
|
/**
|
|
@@ -1026,7 +946,7 @@ class Peernet {
|
|
|
1026
946
|
if (store && await store.has(hash)) data = await store.get(hash);
|
|
1027
947
|
if (data) return data
|
|
1028
948
|
|
|
1029
|
-
return this.requestData(hash, store?.name
|
|
949
|
+
return this.requestData(hash, store?.name || store)
|
|
1030
950
|
}
|
|
1031
951
|
|
|
1032
952
|
/**
|
|
@@ -1048,8 +968,7 @@ class Peernet {
|
|
|
1048
968
|
async has(hash) {
|
|
1049
969
|
const store = await this.whichStore([...this.stores], hash);
|
|
1050
970
|
if (store) {
|
|
1051
|
-
|
|
1052
|
-
else return true
|
|
971
|
+
return store.private ? false : true
|
|
1053
972
|
}
|
|
1054
973
|
return false
|
|
1055
974
|
}
|
|
@@ -1081,9 +1000,9 @@ class Peernet {
|
|
|
1081
1000
|
* @param {String} topic
|
|
1082
1001
|
* @param {Method} cb
|
|
1083
1002
|
*/
|
|
1084
|
-
async subscribe(topic,
|
|
1003
|
+
async subscribe(topic, callback) {
|
|
1085
1004
|
// TODO: if peer subscribed
|
|
1086
|
-
globalSub.subscribe(topic,
|
|
1005
|
+
globalSub.subscribe(topic, callback);
|
|
1087
1006
|
}
|
|
1088
1007
|
|
|
1089
1008
|
async removePeer(peer) {
|
package/exports/store.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { homedir, platform } from 'os';
|
|
3
|
+
import { readdirSync } from 'fs';
|
|
4
|
+
import { execSync } from 'child_process';
|
|
5
|
+
import { ClassicLevel } from 'classic-level';
|
|
6
|
+
|
|
7
|
+
// import base32 from '@vandeurenglenn/base32'
|
|
8
|
+
// import base58 from '@vandeurenglenn/base58'
|
|
9
|
+
|
|
10
|
+
// export const encodings = {
|
|
11
|
+
// base58,
|
|
12
|
+
// base32
|
|
13
|
+
// }
|
|
14
|
+
|
|
15
|
+
const encode$1 = (string, encoding = 'utf-8') => {
|
|
16
|
+
if (typeof string === 'string') {
|
|
17
|
+
let encoded;
|
|
18
|
+
|
|
19
|
+
// if (encodings[encoding]) encoded = encodings[encoding].encode(encoded)
|
|
20
|
+
encoded = new TextEncoder().encode(string);
|
|
21
|
+
return encoded
|
|
22
|
+
}
|
|
23
|
+
throw Error(`expected typeof String instead got ${string}`)
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const decode$1 = (uint8Array, encoding) => {
|
|
27
|
+
if (uint8Array instanceof Uint8Array) {
|
|
28
|
+
let decoded;
|
|
29
|
+
// if (encodings[encoding]) decoded = encodings[encoding].decode(decoded)
|
|
30
|
+
decoded = new TextDecoder().decode(uint8Array);
|
|
31
|
+
|
|
32
|
+
return decoded
|
|
33
|
+
}
|
|
34
|
+
throw Error(`expected typeof uint8Array instead got ${uint8Array}`)
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
class KeyValue {
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {string | Uint8Array} input
|
|
41
|
+
*/
|
|
42
|
+
constructor(input) {
|
|
43
|
+
if (typeof input === 'string') {
|
|
44
|
+
this.uint8Array = encode$1(input);
|
|
45
|
+
} else if (input instanceof Uint8Array) {
|
|
46
|
+
this.uint8Array = input;
|
|
47
|
+
} else if (input instanceof KeyValue) {
|
|
48
|
+
this.uint8Array = input.uint8Array;
|
|
49
|
+
} else {
|
|
50
|
+
throw new Error('Invalid KeyValue, should be a String, Uint8Array or KeyValue')
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
isKeyValue() {
|
|
55
|
+
return true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Convert to the string representation
|
|
60
|
+
*
|
|
61
|
+
* @param {import('uint8arrays/to-string').SupportedEncodings} [encoding='utf8'] - The encoding to use.
|
|
62
|
+
* @returns {string}
|
|
63
|
+
*/
|
|
64
|
+
toString(encoding = 'utf8') {
|
|
65
|
+
return decode$1(this.uint8Array)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const mkdirp = path => execSync(`mkdir "${platform() === 'win32' ? path.replace(/\//g, '\\') : path}"`);
|
|
71
|
+
|
|
72
|
+
const init = (root, home = true) => {
|
|
73
|
+
let _root;
|
|
74
|
+
if (home) _root = join(homedir(), root);
|
|
75
|
+
if (readdirSync) try {
|
|
76
|
+
readdirSync(_root);
|
|
77
|
+
} catch (e) {
|
|
78
|
+
mkdirp(_root);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return _root
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// import base32 from '@vandeurenglenn/base32'
|
|
85
|
+
// import base58 from '@vandeurenglenn/base58'
|
|
86
|
+
|
|
87
|
+
// export const encodings = {
|
|
88
|
+
// base58,
|
|
89
|
+
// base32
|
|
90
|
+
// }
|
|
91
|
+
|
|
92
|
+
const encode = (string, encoding = 'utf-8') => {
|
|
93
|
+
if (typeof string === 'string') {
|
|
94
|
+
let encoded;
|
|
95
|
+
|
|
96
|
+
// if (encodings[encoding]) encoded = encodings[encoding].encode(encoded)
|
|
97
|
+
encoded = new TextEncoder().encode(string);
|
|
98
|
+
return encoded
|
|
99
|
+
}
|
|
100
|
+
throw Error(`expected typeof String instead got ${string}`)
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const decode = (uint8Array, encoding) => {
|
|
104
|
+
if (uint8Array instanceof Uint8Array) {
|
|
105
|
+
let decoded;
|
|
106
|
+
// if (encodings[encoding]) decoded = encodings[encoding].decode(decoded)
|
|
107
|
+
decoded = new TextDecoder().decode(uint8Array);
|
|
108
|
+
|
|
109
|
+
return decoded
|
|
110
|
+
}
|
|
111
|
+
throw Error(`expected typeof uint8Array instead got ${uint8Array}`)
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const pathSepS = '/';
|
|
115
|
+
class KeyPath {
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @param {string | Uint8Array} input
|
|
119
|
+
*/
|
|
120
|
+
constructor(input) {
|
|
121
|
+
if (typeof input === 'string') {
|
|
122
|
+
this.uint8Array = encode(input);
|
|
123
|
+
} else if (input instanceof Uint8Array) {
|
|
124
|
+
this.uint8Array = input;
|
|
125
|
+
} else if (input instanceof KeyPath) {
|
|
126
|
+
this.uint8Array = input.uint8Array;
|
|
127
|
+
} else {
|
|
128
|
+
throw new Error('Invalid keyPath, should be a String, Uint8Array or KeyPath')
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
isKeyPath() {
|
|
133
|
+
return true
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Convert to the string representation
|
|
138
|
+
*
|
|
139
|
+
* @param {import('uint8arrays/to-string').SupportedEncodings} [encoding='utf8'] - The encoding to use.
|
|
140
|
+
* @returns {string}
|
|
141
|
+
*/
|
|
142
|
+
toString(encoding = 'hex') {
|
|
143
|
+
return decode(this.uint8Array)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Returns the `list` representation of this path.
|
|
148
|
+
*
|
|
149
|
+
* @returns string[]
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```js
|
|
153
|
+
* new Key('/Comedy/MontyPython/Actor:JohnCleese').list()
|
|
154
|
+
* // => ['Comedy', 'MontyPythong', 'Actor:JohnCleese']
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
list() {
|
|
158
|
+
return this.toString().split(pathSepS).slice(1)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
class Store {
|
|
164
|
+
constructor(name = 'storage', root, version = 'v1.0.0') {
|
|
165
|
+
this.name = name;
|
|
166
|
+
this.root = init(root);
|
|
167
|
+
this.version = version;
|
|
168
|
+
|
|
169
|
+
this.db = new ClassicLevel(join(this.root, this.name), { valueEncoding: 'view'});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
toKeyPath(key) {
|
|
173
|
+
if (!key.isKeyPath()) key = new KeyPath(key);
|
|
174
|
+
return key.toString('base32')
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
toKeyValue(value) {
|
|
178
|
+
if (!value.isKeyValue()) value = new KeyValue(value);
|
|
179
|
+
return value.uint8Array
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async get(key) {
|
|
183
|
+
return this.db.get(this.toKeyPath(key))
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async put(key, value) {
|
|
187
|
+
return this.db.put(this.toKeyPath(key), this.toKeyValue(value))
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async delete(key) {
|
|
191
|
+
return this.db.del(this.toKeyPath(key))
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async clear() {
|
|
195
|
+
return this.db.clear()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async values(limit = -1) {
|
|
199
|
+
const values = [];
|
|
200
|
+
for await (const value of this.db.values({limit})) {
|
|
201
|
+
values.push(value);
|
|
202
|
+
}
|
|
203
|
+
return values
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async keys(limit = -1) {
|
|
207
|
+
const keys = [];
|
|
208
|
+
for await (const key of this.db.keys({limit})) {
|
|
209
|
+
keys.push(key);
|
|
210
|
+
}
|
|
211
|
+
return keys
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
*
|
|
216
|
+
* @param {object} options { limit, gt, lt, reverse }
|
|
217
|
+
* @returns
|
|
218
|
+
*/
|
|
219
|
+
iterate(options) {
|
|
220
|
+
return this.db.iterator(options)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export { Store as default };
|