@pkcprotocol/pkc-js 0.0.22 → 0.0.23

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.
@@ -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
@@ -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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"}