@pkcprotocol/pkc-js 0.0.22 → 0.0.24
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 -1
- package/dist/browser/generated-version.d.ts +1 -1
- package/dist/browser/generated-version.js +1 -1
- package/dist/browser/helia/helia-for-pkc.js +24 -8
- package/dist/browser/helia/helia-for-pkc.js.map +1 -1
- package/dist/browser/test/test-util.js +4 -5
- package/dist/browser/test/test-util.js.map +1 -1
- package/dist/node/generated-version.d.ts +1 -1
- package/dist/node/generated-version.js +1 -1
- package/dist/node/helia/helia-for-pkc.js +24 -8
- package/dist/node/helia/helia-for-pkc.js.map +1 -1
- package/dist/node/test/test-util.js +4 -5
- package/dist/node/test/test-util.js.map +1 -1
- package/package.json +22 -21
- package/dist/browser/helia/ipns-over-pubsub-with-fetch.d.ts +0 -36
- package/dist/browser/helia/ipns-over-pubsub-with-fetch.js +0 -229
- package/dist/browser/helia/ipns-over-pubsub-with-fetch.js.map +0 -1
- package/dist/node/helia/ipns-over-pubsub-with-fetch.d.ts +0 -36
- package/dist/node/helia/ipns-over-pubsub-with-fetch.js +0 -229
- package/dist/node/helia/ipns-over-pubsub-with-fetch.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pkcprotocol/pkc-js",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"prebuild": "node config/generate-version.js",
|
|
@@ -18,15 +18,16 @@
|
|
|
18
18
|
"test:node:parallel:all": "node test/run-test-config.js --environment node --parallel --per-test-logs .tmp/per-test-logs-node-parallel-all test/node test/node-and-browser src/rpc/test/node src/rpc/test/node-and-browser",
|
|
19
19
|
"test:node:parallel:local": "cross-env PKC_CONFIGS=local-kubo-rpc node test/run-test-config.js --environment node --parallel --per-test-logs .tmp/per-test-logs-node-parallel-local test/node src/rpc/test/node",
|
|
20
20
|
"test:node:local": "node test/run-test-config.js --environment node --per-test-logs .tmp/per-test-logs-node-local test/node src/rpc/test/node --run-timeout-ms 1740000 --log-prefix test_node_local",
|
|
21
|
-
"test:node:parallel:remote": "node test/run-test-config.js --pkc-config remote-kubo-rpc,remote-ipfs-gateway --environment node --parallel --per-test-logs .tmp/per-test-logs-node-parallel-remote test/node-and-browser",
|
|
22
|
-
"test:node:remote": "node test/run-test-config.js --pkc-config remote-kubo-rpc,remote-ipfs-gateway --environment node --per-test-logs .tmp/per-test-logs-node-remote",
|
|
23
|
-
"test:browser:chrome": "node test/run-test-config.js --pkc-config ${PKC_CONFIGS:-remote-kubo-rpc,remote-ipfs-gateway} --environment chrome --per-test-logs .tmp/per-test-logs-browser-chrome",
|
|
24
|
-
"test:browser:firefox": "node test/run-test-config.js --pkc-config ${PKC_CONFIGS:-remote-kubo-rpc,remote-ipfs-gateway} --environment firefox --per-test-logs .tmp/per-test-logs-browser-firefox",
|
|
25
|
-
"test:browser:chrome:parallel": "node test/run-test-config.js --pkc-config ${PKC_CONFIGS:-remote-kubo-rpc,remote-ipfs-gateway} --environment chrome --parallel --per-test-logs .tmp/per-test-logs-browser-chrome-parallel",
|
|
26
|
-
"test:browser:firefox:parallel": "node test/run-test-config.js --pkc-config ${PKC_CONFIGS:-remote-kubo-rpc,remote-ipfs-gateway} --environment firefox --parallel --per-test-logs .tmp/per-test-logs-browser-firefox-parallel",
|
|
21
|
+
"test:node:parallel:remote": "node test/run-test-config.js --pkc-config remote-kubo-rpc,remote-ipfs-gateway,remote-libp2pjs --environment node --parallel --per-test-logs .tmp/per-test-logs-node-parallel-remote test/node-and-browser",
|
|
22
|
+
"test:node:remote": "node test/run-test-config.js --pkc-config remote-kubo-rpc,remote-ipfs-gateway,remote-libp2pjs --environment node --per-test-logs .tmp/per-test-logs-node-remote",
|
|
23
|
+
"test:browser:chrome": "node test/run-test-config.js --pkc-config ${PKC_CONFIGS:-remote-kubo-rpc,remote-ipfs-gateway,remote-libp2pjs} --environment chrome --per-test-logs .tmp/per-test-logs-browser-chrome",
|
|
24
|
+
"test:browser:firefox": "node test/run-test-config.js --pkc-config ${PKC_CONFIGS:-remote-kubo-rpc,remote-ipfs-gateway,remote-libp2pjs} --environment firefox --per-test-logs .tmp/per-test-logs-browser-firefox",
|
|
25
|
+
"test:browser:chrome:parallel": "node test/run-test-config.js --pkc-config ${PKC_CONFIGS:-remote-kubo-rpc,remote-ipfs-gateway,remote-libp2pjs} --environment chrome --parallel --per-test-logs .tmp/per-test-logs-browser-chrome-parallel",
|
|
26
|
+
"test:browser:firefox:parallel": "node test/run-test-config.js --pkc-config ${PKC_CONFIGS:-remote-kubo-rpc,remote-ipfs-gateway,remote-libp2pjs} --environment firefox --parallel --per-test-logs .tmp/per-test-logs-browser-firefox-parallel",
|
|
27
27
|
"test:server:node": "node test/server/test-server.js",
|
|
28
28
|
"test:server:node:rpc": "cross-env START_RPC_SERVER=1 PKC_CONFIGS=remote-kubo-rpc node --es-module-specifier-resolution=node test/server/test-server.js",
|
|
29
29
|
"test:server:wait-on": "wait-on http://localhost:14952 --timeout 300000",
|
|
30
|
+
"prepublishOnly": "npm run build",
|
|
30
31
|
"clean": "rimraf dist",
|
|
31
32
|
"prettier": "prettier {src,test,config}/**/*.{js,ts} --write --config config/prettier.config.js",
|
|
32
33
|
"test:prettier": "prettier --check {src,test,config}/**/*.{js,ts} --config config/prettier.config.js",
|
|
@@ -63,17 +64,17 @@
|
|
|
63
64
|
},
|
|
64
65
|
"dependencies": {
|
|
65
66
|
"@enhances/with-resolvers": "0.0.5",
|
|
66
|
-
"@helia/block-brokers": "5.
|
|
67
|
+
"@helia/block-brokers": "5.2.4",
|
|
67
68
|
"@helia/delegated-routing-v1-http-api-client": "6.0.1",
|
|
68
|
-
"@helia/ipns": "9.1
|
|
69
|
-
"@helia/unixfs": "7.
|
|
70
|
-
"@libp2p/crypto": "5.1.
|
|
71
|
-
"@libp2p/fetch": "4.
|
|
72
|
-
"@libp2p/gossipsub": "15.0.
|
|
73
|
-
"@libp2p/identify": "4.
|
|
69
|
+
"@helia/ipns": "9.2.1",
|
|
70
|
+
"@helia/unixfs": "7.2.1",
|
|
71
|
+
"@libp2p/crypto": "5.1.17",
|
|
72
|
+
"@libp2p/fetch": "4.1.3",
|
|
73
|
+
"@libp2p/gossipsub": "15.0.21",
|
|
74
|
+
"@libp2p/identify": "4.1.3",
|
|
74
75
|
"@libp2p/interfaces": "3.3.2",
|
|
75
|
-
"@libp2p/peer-id": "6.0.
|
|
76
|
-
"@libp2p/websockets": "10.1.
|
|
76
|
+
"@libp2p/peer-id": "6.0.8",
|
|
77
|
+
"@libp2p/websockets": "10.1.11",
|
|
77
78
|
"@noble/curves": "2.2.0",
|
|
78
79
|
"@pkcprotocol/pkc-logger": "0.1.0",
|
|
79
80
|
"@pkcprotocol/proper-lock-file": "4.2.1",
|
|
@@ -87,7 +88,7 @@
|
|
|
87
88
|
"debounce": "1.2.1",
|
|
88
89
|
"err-code": "3.0.1",
|
|
89
90
|
"ext-name": "5.0.0",
|
|
90
|
-
"helia": "6.
|
|
91
|
+
"helia": "6.1.4",
|
|
91
92
|
"hpagent": "1.2.0",
|
|
92
93
|
"it-all": "3.0.6",
|
|
93
94
|
"js-sha256": "0.11.1",
|
|
@@ -99,7 +100,7 @@
|
|
|
99
100
|
"lru-cache": "10.1.0",
|
|
100
101
|
"open-graph-scraper": "6.11.0",
|
|
101
102
|
"p-limit": "7.3.0",
|
|
102
|
-
"p-retry": "
|
|
103
|
+
"p-retry": "8.0.0",
|
|
103
104
|
"p-timeout": "7.0.1",
|
|
104
105
|
"probe-image-size": "7.2.3",
|
|
105
106
|
"remeda": "1.57.0",
|
|
@@ -123,7 +124,7 @@
|
|
|
123
124
|
"@types/debounce": "1.2.1",
|
|
124
125
|
"@types/lodash": "4.17.13",
|
|
125
126
|
"@types/lodash.merge": "4.6.9",
|
|
126
|
-
"@types/node": "
|
|
127
|
+
"@types/node": "22.19.17",
|
|
127
128
|
"@types/node-forge": "1.3.11",
|
|
128
129
|
"@types/probe-image-size": "7.2.4",
|
|
129
130
|
"@types/retry": "0.12.5",
|
|
@@ -158,7 +159,7 @@
|
|
|
158
159
|
"vitest": "4.0.15",
|
|
159
160
|
"wait-on": "9.0.5"
|
|
160
161
|
},
|
|
161
|
-
"description": "
|
|
162
|
+
"description": "TypeScript SDK for PKC (Public Key Communities), a serverless, decentralized social protocol built on IPFS, IPNS, and libp2p pubsub. Powers all PKC clients: CLI, Electron desktop, and web.",
|
|
162
163
|
"publishConfig": {
|
|
163
164
|
"access": "public"
|
|
164
165
|
},
|
|
@@ -195,7 +196,7 @@
|
|
|
195
196
|
},
|
|
196
197
|
"homepage": "https://github.com/pkcprotocol/pkc-js#readme",
|
|
197
198
|
"engines": {
|
|
198
|
-
"node": ">=
|
|
199
|
+
"node": ">=22"
|
|
199
200
|
},
|
|
200
201
|
"config": {
|
|
201
202
|
"commitizen": {
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { GetOptions as ipnsGetOptions, IPNSRouting, PutOptions } from "@helia/ipns/routing";
|
|
2
|
-
import type { Fetch } from "@libp2p/fetch";
|
|
3
|
-
import { peerIdFromString } from "@libp2p/peer-id";
|
|
4
|
-
import type { HeliaWithLibp2pPubsub } from "./types.js";
|
|
5
|
-
export type PKCIpnsGetOptions = ipnsGetOptions & {
|
|
6
|
-
ipnsName: string;
|
|
7
|
-
};
|
|
8
|
-
type PeerId = ReturnType<typeof peerIdFromString>;
|
|
9
|
-
export declare class IpnsFetchRouter implements IPNSRouting {
|
|
10
|
-
fetchedIpnsRecordBefore: Record<string, boolean>;
|
|
11
|
-
_helia: HeliaWithLibp2pPubsub;
|
|
12
|
-
_fetchService: Fetch;
|
|
13
|
-
constructor(helia: HeliaWithLibp2pPubsub);
|
|
14
|
-
put(routingKey: Uint8Array, marshaledRecord: Uint8Array, options?: PutOptions): Promise<void>;
|
|
15
|
-
private _fetchFromPeer;
|
|
16
|
-
_handleFetchingFromSubscribedPubsubPeers({ routingKey, topic, pubsubSubscribers, options }: {
|
|
17
|
-
routingKey: Uint8Array;
|
|
18
|
-
topic: string;
|
|
19
|
-
pubsubSubscribers: PeerId[];
|
|
20
|
-
options: PKCIpnsGetOptions & {
|
|
21
|
-
signal: AbortSignal;
|
|
22
|
-
abortController: AbortController;
|
|
23
|
-
};
|
|
24
|
-
}): Promise<Uint8Array>;
|
|
25
|
-
_handleFetchingFromProviders({ routingKey, topic, options }: {
|
|
26
|
-
routingKey: Uint8Array;
|
|
27
|
-
topic: string;
|
|
28
|
-
options: PKCIpnsGetOptions & {
|
|
29
|
-
signal: AbortSignal;
|
|
30
|
-
abortController: AbortController;
|
|
31
|
-
};
|
|
32
|
-
}): Promise<Uint8Array>;
|
|
33
|
-
get(routingKey: Uint8Array, options: PKCIpnsGetOptions): Promise<Uint8Array>;
|
|
34
|
-
}
|
|
35
|
-
export declare function createIpnsFetchRouter(helia: HeliaWithLibp2pPubsub): IPNSRouting;
|
|
36
|
-
export {};
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import Logger from "../logger.js";
|
|
2
|
-
import pLimit from "p-limit";
|
|
3
|
-
import pTimeout from "p-timeout";
|
|
4
|
-
import { binaryKeyToPubsubTopic, pubsubTopicToDhtKey, pubsubTopicToDhtKeyCid } from "../util.js";
|
|
5
|
-
import { PKCError } from "../pkc-error.js";
|
|
6
|
-
import { CID } from "kubo-rpc-client";
|
|
7
|
-
const log = Logger("pkc-js:helia:ipns:routing:pubsub-with-fetch");
|
|
8
|
-
const LIMIT_PARALLEL_FETCH_IPNS_FROM_PEERS = 3;
|
|
9
|
-
const IPNS_FETCH_FROM_PEER_TIMEOUT_MS = 10000;
|
|
10
|
-
export class IpnsFetchRouter {
|
|
11
|
-
constructor(helia) {
|
|
12
|
-
this.fetchedIpnsRecordBefore = {}; // key is the "topic", value is true if it was fetched before using libp2p/fetch
|
|
13
|
-
this._helia = helia;
|
|
14
|
-
this._fetchService = helia.libp2p.services.fetch;
|
|
15
|
-
}
|
|
16
|
-
put(routingKey, marshaledRecord, options) {
|
|
17
|
-
throw new Error("Method not implemented.");
|
|
18
|
-
}
|
|
19
|
-
async _fetchFromPeer({ peer, routingKey, topic, options }) {
|
|
20
|
-
const contentCidString = pubsubTopicToDhtKeyCid(topic);
|
|
21
|
-
const record = await pTimeout(this._fetchService.fetch(peer, routingKey), {
|
|
22
|
-
milliseconds: IPNS_FETCH_FROM_PEER_TIMEOUT_MS,
|
|
23
|
-
signal: options?.signal,
|
|
24
|
-
message: new PKCError("ERR_LIBP2P_FETCH_IPNS_FROM_PEER_TIMEDOUT", {
|
|
25
|
-
peerId: peer,
|
|
26
|
-
routingKey,
|
|
27
|
-
topic,
|
|
28
|
-
timeoutMs: IPNS_FETCH_FROM_PEER_TIMEOUT_MS,
|
|
29
|
-
contentCidString,
|
|
30
|
-
options
|
|
31
|
-
})
|
|
32
|
-
});
|
|
33
|
-
if (!record) {
|
|
34
|
-
throw new PKCError("ERR_FETCH_OVER_IPNS_OVER_PUBSUB_RETURNED_UNDEFINED", {
|
|
35
|
-
peerId: peer,
|
|
36
|
-
routingKey,
|
|
37
|
-
topic,
|
|
38
|
-
contentCidString,
|
|
39
|
-
options
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
return record;
|
|
43
|
-
}
|
|
44
|
-
async _handleFetchingFromSubscribedPubsubPeers({ routingKey, topic, pubsubSubscribers, options }) {
|
|
45
|
-
const limit = pLimit(LIMIT_PARALLEL_FETCH_IPNS_FROM_PEERS);
|
|
46
|
-
// We already have subscribers, no need to find providers
|
|
47
|
-
log("Using", pubsubSubscribers.length, "existing pubsub subscribers for topic", topic);
|
|
48
|
-
// Create individual abort controllers for each fetch
|
|
49
|
-
const fetchAbortControllers = [];
|
|
50
|
-
const peerIdToError = {};
|
|
51
|
-
const cleanUp = () => {
|
|
52
|
-
fetchAbortControllers.forEach((controller) => controller.abort());
|
|
53
|
-
if (options.abortController)
|
|
54
|
-
options.abortController.abort();
|
|
55
|
-
};
|
|
56
|
-
// Create fetch promises for all subscribers in parallel
|
|
57
|
-
const fetchPromises = pubsubSubscribers.map((peer) => {
|
|
58
|
-
const peerAbortController = new AbortController();
|
|
59
|
-
fetchAbortControllers.push(peerAbortController);
|
|
60
|
-
const combinedSignal = AbortSignal.any([options.signal, peerAbortController.signal]);
|
|
61
|
-
return limit(() => this._fetchFromPeer({
|
|
62
|
-
peer,
|
|
63
|
-
routingKey,
|
|
64
|
-
topic,
|
|
65
|
-
options: { ...options, signal: combinedSignal }
|
|
66
|
-
})).catch((error) => {
|
|
67
|
-
peerIdToError[peer.toString()] = error;
|
|
68
|
-
throw error;
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
// Use Promise.allSettled to wait for all promises and find the first successful one
|
|
72
|
-
const results = await Promise.allSettled(fetchPromises);
|
|
73
|
-
// Find the first fulfilled (successful) result
|
|
74
|
-
const successfulResult = results.find((result) => result.status === "fulfilled");
|
|
75
|
-
if (successfulResult) {
|
|
76
|
-
log("Fetched IPNS", options?.ipnsName, "record for topic", topic, "using pubsub subscribers");
|
|
77
|
-
cleanUp();
|
|
78
|
-
this.fetchedIpnsRecordBefore[topic] = true;
|
|
79
|
-
return successfulResult.value;
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
// All promises failed
|
|
83
|
-
cleanUp();
|
|
84
|
-
throw new PKCError("ERR_FETCH_OVER_IPNS_OVER_PUBSUB_FAILED", {
|
|
85
|
-
peerIdToError,
|
|
86
|
-
topic,
|
|
87
|
-
routingKey,
|
|
88
|
-
options,
|
|
89
|
-
fetchingFromGossipsubTopicSubscribers: true
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
async _handleFetchingFromProviders({ routingKey, topic, options }) {
|
|
94
|
-
const limit = pLimit(LIMIT_PARALLEL_FETCH_IPNS_FROM_PEERS);
|
|
95
|
-
// No subscribers, need to find providers using content routing and process them as they come
|
|
96
|
-
const pubsubTopicCidString = pubsubTopicToDhtKey(topic);
|
|
97
|
-
const pubsubTopicCid = CID.parse(pubsubTopicToDhtKey(topic));
|
|
98
|
-
const peerIdToError = {};
|
|
99
|
-
const fetchAbortControllers = [];
|
|
100
|
-
const activeFetchPromises = [];
|
|
101
|
-
const findProvidersAbortController = new AbortController();
|
|
102
|
-
const cleanUp = () => {
|
|
103
|
-
findProvidersAbortController.abort();
|
|
104
|
-
fetchAbortControllers.forEach((controller) => controller.abort());
|
|
105
|
-
options.abortController.abort();
|
|
106
|
-
};
|
|
107
|
-
// Helper function to check if any promise has succeeded
|
|
108
|
-
const checkForSuccess = async (promises) => {
|
|
109
|
-
if (promises.length === 0)
|
|
110
|
-
return null;
|
|
111
|
-
const results = await Promise.allSettled(promises);
|
|
112
|
-
const successfulResult = results.find((result) => result.status === "fulfilled");
|
|
113
|
-
return successfulResult ? successfulResult.value : null;
|
|
114
|
-
};
|
|
115
|
-
try {
|
|
116
|
-
// Process providers as they're discovered, but in parallel up to the limit
|
|
117
|
-
for await (const peer of this._helia.libp2p.contentRouting.findProviders(pubsubTopicCid, {
|
|
118
|
-
signal: findProvidersAbortController.signal
|
|
119
|
-
})) {
|
|
120
|
-
const peerAbortController = new AbortController();
|
|
121
|
-
fetchAbortControllers.push(peerAbortController);
|
|
122
|
-
const combinedSignal = AbortSignal.any([options.signal, peerAbortController.signal]);
|
|
123
|
-
const fetchPromise = limit(() => this._fetchFromPeer({
|
|
124
|
-
peer: peer.id,
|
|
125
|
-
routingKey,
|
|
126
|
-
topic,
|
|
127
|
-
options: { ...options, signal: combinedSignal }
|
|
128
|
-
})).catch((error) => {
|
|
129
|
-
peerIdToError[peer.id.toString()] = error;
|
|
130
|
-
throw error;
|
|
131
|
-
});
|
|
132
|
-
activeFetchPromises.push(fetchPromise);
|
|
133
|
-
// Check if any active promises have succeeded
|
|
134
|
-
const result = await checkForSuccess(activeFetchPromises);
|
|
135
|
-
if (result) {
|
|
136
|
-
cleanUp();
|
|
137
|
-
log("Fetched IPNS", options?.ipnsName, "record for topic", topic, "using provider discovery");
|
|
138
|
-
return result;
|
|
139
|
-
}
|
|
140
|
-
// If we have reached the limit, wait for some to complete before adding more
|
|
141
|
-
if (activeFetchPromises.length >= LIMIT_PARALLEL_FETCH_IPNS_FROM_PEERS) {
|
|
142
|
-
// Remove completed promises
|
|
143
|
-
const results = await Promise.allSettled(activeFetchPromises);
|
|
144
|
-
const successfulResult = results.find((result) => result.status === "fulfilled");
|
|
145
|
-
if (successfulResult) {
|
|
146
|
-
cleanUp();
|
|
147
|
-
log("Fetched IPNS", options?.ipnsName, "record for topic", topic, "using provider discovery");
|
|
148
|
-
return successfulResult.value;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// Final check on any remaining promises
|
|
153
|
-
const result = await checkForSuccess(activeFetchPromises);
|
|
154
|
-
if (result) {
|
|
155
|
-
log("Fetched IPNS", options?.ipnsName, "record for topic", topic, "using provider discovery");
|
|
156
|
-
this.fetchedIpnsRecordBefore[topic] = true;
|
|
157
|
-
return result;
|
|
158
|
-
}
|
|
159
|
-
cleanUp();
|
|
160
|
-
// If we get here, all providers have been tried and failed
|
|
161
|
-
throw new PKCError("ERR_FETCH_OVER_IPNS_OVER_PUBSUB_FAILED", {
|
|
162
|
-
peerIdToError,
|
|
163
|
-
fetchingFromProviders: true,
|
|
164
|
-
topic,
|
|
165
|
-
routingKey,
|
|
166
|
-
options
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
catch (e) {
|
|
170
|
-
//@ts-expect-error
|
|
171
|
-
e.details = {
|
|
172
|
-
//@ts-expect-error
|
|
173
|
-
...e.details,
|
|
174
|
-
topic,
|
|
175
|
-
routingKey,
|
|
176
|
-
peerIdToError,
|
|
177
|
-
pubsubTopicCid,
|
|
178
|
-
pubsubTopicCidString,
|
|
179
|
-
options
|
|
180
|
-
};
|
|
181
|
-
throw e;
|
|
182
|
-
}
|
|
183
|
-
finally {
|
|
184
|
-
cleanUp();
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
async get(routingKey, options) {
|
|
188
|
-
const topic = binaryKeyToPubsubTopic(routingKey);
|
|
189
|
-
// Check if we should use libp2p/fetch based on cooloff period
|
|
190
|
-
const cooloffKey = `${topic}`;
|
|
191
|
-
const shouldUseFetch = !this.fetchedIpnsRecordBefore[cooloffKey];
|
|
192
|
-
if (!shouldUseFetch) {
|
|
193
|
-
log.trace("Skipping libp2p/fetch for topic", topic, "and IPNS", options?.ipnsName, "since we already fetched it before using libp2p/fetch");
|
|
194
|
-
throw new Error("Already loaded via libp2p/fetch, should await for updates in gossipsub topic");
|
|
195
|
-
}
|
|
196
|
-
// First check if we already have pubsub subscribers
|
|
197
|
-
const pubsubSubscribers = this._helia.libp2p.services.pubsub.getSubscribers(topic);
|
|
198
|
-
const abortController = new AbortController();
|
|
199
|
-
const combinedSignal = options?.signal ? AbortSignal.any([options.signal, abortController.signal]) : abortController.signal;
|
|
200
|
-
try {
|
|
201
|
-
if (pubsubSubscribers.length > 0)
|
|
202
|
-
return await this._handleFetchingFromSubscribedPubsubPeers({
|
|
203
|
-
routingKey,
|
|
204
|
-
topic,
|
|
205
|
-
pubsubSubscribers,
|
|
206
|
-
options: { ...options, signal: combinedSignal, abortController }
|
|
207
|
-
});
|
|
208
|
-
else
|
|
209
|
-
return await this._handleFetchingFromProviders({
|
|
210
|
-
routingKey,
|
|
211
|
-
topic,
|
|
212
|
-
options: { ...options, signal: combinedSignal, abortController }
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
catch (error) {
|
|
216
|
-
//@ts-expect-error
|
|
217
|
-
error.details = { ...error.details, topic, routingKey, options };
|
|
218
|
-
log.trace("Error in get method:", error);
|
|
219
|
-
throw error;
|
|
220
|
-
}
|
|
221
|
-
finally {
|
|
222
|
-
abortController.abort(); // make sure to abort
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
export function createIpnsFetchRouter(helia) {
|
|
227
|
-
return new IpnsFetchRouter(helia);
|
|
228
|
-
}
|
|
229
|
-
//# sourceMappingURL=ipns-over-pubsub-with-fetch.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ipns-over-pubsub-with-fetch.js","sourceRoot":"","sources":["../../../src/helia/ipns-over-pubsub-with-fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { GetOptions as ipnsGetOptions, IPNSRouting, PutOptions } from "@helia/ipns/routing";
|
|
2
|
-
import type { Fetch } from "@libp2p/fetch";
|
|
3
|
-
import { peerIdFromString } from "@libp2p/peer-id";
|
|
4
|
-
import type { HeliaWithLibp2pPubsub } from "./types.js";
|
|
5
|
-
export type PKCIpnsGetOptions = ipnsGetOptions & {
|
|
6
|
-
ipnsName: string;
|
|
7
|
-
};
|
|
8
|
-
type PeerId = ReturnType<typeof peerIdFromString>;
|
|
9
|
-
export declare class IpnsFetchRouter implements IPNSRouting {
|
|
10
|
-
fetchedIpnsRecordBefore: Record<string, boolean>;
|
|
11
|
-
_helia: HeliaWithLibp2pPubsub;
|
|
12
|
-
_fetchService: Fetch;
|
|
13
|
-
constructor(helia: HeliaWithLibp2pPubsub);
|
|
14
|
-
put(routingKey: Uint8Array, marshaledRecord: Uint8Array, options?: PutOptions): Promise<void>;
|
|
15
|
-
private _fetchFromPeer;
|
|
16
|
-
_handleFetchingFromSubscribedPubsubPeers({ routingKey, topic, pubsubSubscribers, options }: {
|
|
17
|
-
routingKey: Uint8Array;
|
|
18
|
-
topic: string;
|
|
19
|
-
pubsubSubscribers: PeerId[];
|
|
20
|
-
options: PKCIpnsGetOptions & {
|
|
21
|
-
signal: AbortSignal;
|
|
22
|
-
abortController: AbortController;
|
|
23
|
-
};
|
|
24
|
-
}): Promise<Uint8Array>;
|
|
25
|
-
_handleFetchingFromProviders({ routingKey, topic, options }: {
|
|
26
|
-
routingKey: Uint8Array;
|
|
27
|
-
topic: string;
|
|
28
|
-
options: PKCIpnsGetOptions & {
|
|
29
|
-
signal: AbortSignal;
|
|
30
|
-
abortController: AbortController;
|
|
31
|
-
};
|
|
32
|
-
}): Promise<Uint8Array>;
|
|
33
|
-
get(routingKey: Uint8Array, options: PKCIpnsGetOptions): Promise<Uint8Array>;
|
|
34
|
-
}
|
|
35
|
-
export declare function createIpnsFetchRouter(helia: HeliaWithLibp2pPubsub): IPNSRouting;
|
|
36
|
-
export {};
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import Logger from "../logger.js";
|
|
2
|
-
import pLimit from "p-limit";
|
|
3
|
-
import pTimeout from "p-timeout";
|
|
4
|
-
import { binaryKeyToPubsubTopic, pubsubTopicToDhtKey, pubsubTopicToDhtKeyCid } from "../util.js";
|
|
5
|
-
import { PKCError } from "../pkc-error.js";
|
|
6
|
-
import { CID } from "kubo-rpc-client";
|
|
7
|
-
const log = Logger("pkc-js:helia:ipns:routing:pubsub-with-fetch");
|
|
8
|
-
const LIMIT_PARALLEL_FETCH_IPNS_FROM_PEERS = 3;
|
|
9
|
-
const IPNS_FETCH_FROM_PEER_TIMEOUT_MS = 10000;
|
|
10
|
-
export class IpnsFetchRouter {
|
|
11
|
-
constructor(helia) {
|
|
12
|
-
this.fetchedIpnsRecordBefore = {}; // key is the "topic", value is true if it was fetched before using libp2p/fetch
|
|
13
|
-
this._helia = helia;
|
|
14
|
-
this._fetchService = helia.libp2p.services.fetch;
|
|
15
|
-
}
|
|
16
|
-
put(routingKey, marshaledRecord, options) {
|
|
17
|
-
throw new Error("Method not implemented.");
|
|
18
|
-
}
|
|
19
|
-
async _fetchFromPeer({ peer, routingKey, topic, options }) {
|
|
20
|
-
const contentCidString = pubsubTopicToDhtKeyCid(topic);
|
|
21
|
-
const record = await pTimeout(this._fetchService.fetch(peer, routingKey), {
|
|
22
|
-
milliseconds: IPNS_FETCH_FROM_PEER_TIMEOUT_MS,
|
|
23
|
-
signal: options?.signal,
|
|
24
|
-
message: new PKCError("ERR_LIBP2P_FETCH_IPNS_FROM_PEER_TIMEDOUT", {
|
|
25
|
-
peerId: peer,
|
|
26
|
-
routingKey,
|
|
27
|
-
topic,
|
|
28
|
-
timeoutMs: IPNS_FETCH_FROM_PEER_TIMEOUT_MS,
|
|
29
|
-
contentCidString,
|
|
30
|
-
options
|
|
31
|
-
})
|
|
32
|
-
});
|
|
33
|
-
if (!record) {
|
|
34
|
-
throw new PKCError("ERR_FETCH_OVER_IPNS_OVER_PUBSUB_RETURNED_UNDEFINED", {
|
|
35
|
-
peerId: peer,
|
|
36
|
-
routingKey,
|
|
37
|
-
topic,
|
|
38
|
-
contentCidString,
|
|
39
|
-
options
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
return record;
|
|
43
|
-
}
|
|
44
|
-
async _handleFetchingFromSubscribedPubsubPeers({ routingKey, topic, pubsubSubscribers, options }) {
|
|
45
|
-
const limit = pLimit(LIMIT_PARALLEL_FETCH_IPNS_FROM_PEERS);
|
|
46
|
-
// We already have subscribers, no need to find providers
|
|
47
|
-
log("Using", pubsubSubscribers.length, "existing pubsub subscribers for topic", topic);
|
|
48
|
-
// Create individual abort controllers for each fetch
|
|
49
|
-
const fetchAbortControllers = [];
|
|
50
|
-
const peerIdToError = {};
|
|
51
|
-
const cleanUp = () => {
|
|
52
|
-
fetchAbortControllers.forEach((controller) => controller.abort());
|
|
53
|
-
if (options.abortController)
|
|
54
|
-
options.abortController.abort();
|
|
55
|
-
};
|
|
56
|
-
// Create fetch promises for all subscribers in parallel
|
|
57
|
-
const fetchPromises = pubsubSubscribers.map((peer) => {
|
|
58
|
-
const peerAbortController = new AbortController();
|
|
59
|
-
fetchAbortControllers.push(peerAbortController);
|
|
60
|
-
const combinedSignal = AbortSignal.any([options.signal, peerAbortController.signal]);
|
|
61
|
-
return limit(() => this._fetchFromPeer({
|
|
62
|
-
peer,
|
|
63
|
-
routingKey,
|
|
64
|
-
topic,
|
|
65
|
-
options: { ...options, signal: combinedSignal }
|
|
66
|
-
})).catch((error) => {
|
|
67
|
-
peerIdToError[peer.toString()] = error;
|
|
68
|
-
throw error;
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
// Use Promise.allSettled to wait for all promises and find the first successful one
|
|
72
|
-
const results = await Promise.allSettled(fetchPromises);
|
|
73
|
-
// Find the first fulfilled (successful) result
|
|
74
|
-
const successfulResult = results.find((result) => result.status === "fulfilled");
|
|
75
|
-
if (successfulResult) {
|
|
76
|
-
log("Fetched IPNS", options?.ipnsName, "record for topic", topic, "using pubsub subscribers");
|
|
77
|
-
cleanUp();
|
|
78
|
-
this.fetchedIpnsRecordBefore[topic] = true;
|
|
79
|
-
return successfulResult.value;
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
// All promises failed
|
|
83
|
-
cleanUp();
|
|
84
|
-
throw new PKCError("ERR_FETCH_OVER_IPNS_OVER_PUBSUB_FAILED", {
|
|
85
|
-
peerIdToError,
|
|
86
|
-
topic,
|
|
87
|
-
routingKey,
|
|
88
|
-
options,
|
|
89
|
-
fetchingFromGossipsubTopicSubscribers: true
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
async _handleFetchingFromProviders({ routingKey, topic, options }) {
|
|
94
|
-
const limit = pLimit(LIMIT_PARALLEL_FETCH_IPNS_FROM_PEERS);
|
|
95
|
-
// No subscribers, need to find providers using content routing and process them as they come
|
|
96
|
-
const pubsubTopicCidString = pubsubTopicToDhtKey(topic);
|
|
97
|
-
const pubsubTopicCid = CID.parse(pubsubTopicToDhtKey(topic));
|
|
98
|
-
const peerIdToError = {};
|
|
99
|
-
const fetchAbortControllers = [];
|
|
100
|
-
const activeFetchPromises = [];
|
|
101
|
-
const findProvidersAbortController = new AbortController();
|
|
102
|
-
const cleanUp = () => {
|
|
103
|
-
findProvidersAbortController.abort();
|
|
104
|
-
fetchAbortControllers.forEach((controller) => controller.abort());
|
|
105
|
-
options.abortController.abort();
|
|
106
|
-
};
|
|
107
|
-
// Helper function to check if any promise has succeeded
|
|
108
|
-
const checkForSuccess = async (promises) => {
|
|
109
|
-
if (promises.length === 0)
|
|
110
|
-
return null;
|
|
111
|
-
const results = await Promise.allSettled(promises);
|
|
112
|
-
const successfulResult = results.find((result) => result.status === "fulfilled");
|
|
113
|
-
return successfulResult ? successfulResult.value : null;
|
|
114
|
-
};
|
|
115
|
-
try {
|
|
116
|
-
// Process providers as they're discovered, but in parallel up to the limit
|
|
117
|
-
for await (const peer of this._helia.libp2p.contentRouting.findProviders(pubsubTopicCid, {
|
|
118
|
-
signal: findProvidersAbortController.signal
|
|
119
|
-
})) {
|
|
120
|
-
const peerAbortController = new AbortController();
|
|
121
|
-
fetchAbortControllers.push(peerAbortController);
|
|
122
|
-
const combinedSignal = AbortSignal.any([options.signal, peerAbortController.signal]);
|
|
123
|
-
const fetchPromise = limit(() => this._fetchFromPeer({
|
|
124
|
-
peer: peer.id,
|
|
125
|
-
routingKey,
|
|
126
|
-
topic,
|
|
127
|
-
options: { ...options, signal: combinedSignal }
|
|
128
|
-
})).catch((error) => {
|
|
129
|
-
peerIdToError[peer.id.toString()] = error;
|
|
130
|
-
throw error;
|
|
131
|
-
});
|
|
132
|
-
activeFetchPromises.push(fetchPromise);
|
|
133
|
-
// Check if any active promises have succeeded
|
|
134
|
-
const result = await checkForSuccess(activeFetchPromises);
|
|
135
|
-
if (result) {
|
|
136
|
-
cleanUp();
|
|
137
|
-
log("Fetched IPNS", options?.ipnsName, "record for topic", topic, "using provider discovery");
|
|
138
|
-
return result;
|
|
139
|
-
}
|
|
140
|
-
// If we have reached the limit, wait for some to complete before adding more
|
|
141
|
-
if (activeFetchPromises.length >= LIMIT_PARALLEL_FETCH_IPNS_FROM_PEERS) {
|
|
142
|
-
// Remove completed promises
|
|
143
|
-
const results = await Promise.allSettled(activeFetchPromises);
|
|
144
|
-
const successfulResult = results.find((result) => result.status === "fulfilled");
|
|
145
|
-
if (successfulResult) {
|
|
146
|
-
cleanUp();
|
|
147
|
-
log("Fetched IPNS", options?.ipnsName, "record for topic", topic, "using provider discovery");
|
|
148
|
-
return successfulResult.value;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// Final check on any remaining promises
|
|
153
|
-
const result = await checkForSuccess(activeFetchPromises);
|
|
154
|
-
if (result) {
|
|
155
|
-
log("Fetched IPNS", options?.ipnsName, "record for topic", topic, "using provider discovery");
|
|
156
|
-
this.fetchedIpnsRecordBefore[topic] = true;
|
|
157
|
-
return result;
|
|
158
|
-
}
|
|
159
|
-
cleanUp();
|
|
160
|
-
// If we get here, all providers have been tried and failed
|
|
161
|
-
throw new PKCError("ERR_FETCH_OVER_IPNS_OVER_PUBSUB_FAILED", {
|
|
162
|
-
peerIdToError,
|
|
163
|
-
fetchingFromProviders: true,
|
|
164
|
-
topic,
|
|
165
|
-
routingKey,
|
|
166
|
-
options
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
catch (e) {
|
|
170
|
-
//@ts-expect-error
|
|
171
|
-
e.details = {
|
|
172
|
-
//@ts-expect-error
|
|
173
|
-
...e.details,
|
|
174
|
-
topic,
|
|
175
|
-
routingKey,
|
|
176
|
-
peerIdToError,
|
|
177
|
-
pubsubTopicCid,
|
|
178
|
-
pubsubTopicCidString,
|
|
179
|
-
options
|
|
180
|
-
};
|
|
181
|
-
throw e;
|
|
182
|
-
}
|
|
183
|
-
finally {
|
|
184
|
-
cleanUp();
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
async get(routingKey, options) {
|
|
188
|
-
const topic = binaryKeyToPubsubTopic(routingKey);
|
|
189
|
-
// Check if we should use libp2p/fetch based on cooloff period
|
|
190
|
-
const cooloffKey = `${topic}`;
|
|
191
|
-
const shouldUseFetch = !this.fetchedIpnsRecordBefore[cooloffKey];
|
|
192
|
-
if (!shouldUseFetch) {
|
|
193
|
-
log.trace("Skipping libp2p/fetch for topic", topic, "and IPNS", options?.ipnsName, "since we already fetched it before using libp2p/fetch");
|
|
194
|
-
throw new Error("Already loaded via libp2p/fetch, should await for updates in gossipsub topic");
|
|
195
|
-
}
|
|
196
|
-
// First check if we already have pubsub subscribers
|
|
197
|
-
const pubsubSubscribers = this._helia.libp2p.services.pubsub.getSubscribers(topic);
|
|
198
|
-
const abortController = new AbortController();
|
|
199
|
-
const combinedSignal = options?.signal ? AbortSignal.any([options.signal, abortController.signal]) : abortController.signal;
|
|
200
|
-
try {
|
|
201
|
-
if (pubsubSubscribers.length > 0)
|
|
202
|
-
return await this._handleFetchingFromSubscribedPubsubPeers({
|
|
203
|
-
routingKey,
|
|
204
|
-
topic,
|
|
205
|
-
pubsubSubscribers,
|
|
206
|
-
options: { ...options, signal: combinedSignal, abortController }
|
|
207
|
-
});
|
|
208
|
-
else
|
|
209
|
-
return await this._handleFetchingFromProviders({
|
|
210
|
-
routingKey,
|
|
211
|
-
topic,
|
|
212
|
-
options: { ...options, signal: combinedSignal, abortController }
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
catch (error) {
|
|
216
|
-
//@ts-expect-error
|
|
217
|
-
error.details = { ...error.details, topic, routingKey, options };
|
|
218
|
-
log.trace("Error in get method:", error);
|
|
219
|
-
throw error;
|
|
220
|
-
}
|
|
221
|
-
finally {
|
|
222
|
-
abortController.abort(); // make sure to abort
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
export function createIpnsFetchRouter(helia) {
|
|
227
|
-
return new IpnsFetchRouter(helia);
|
|
228
|
-
}
|
|
229
|
-
//# sourceMappingURL=ipns-over-pubsub-with-fetch.js.map
|