mirror of
https://github.com/DeBrosOfficial/network-ts-sdk.git
synced 2025-12-12 18:28:50 +00:00
Compare commits
No commits in common. "54c61e6a47a3952f08b79b72fe4213da496a48f6" and "06d58fe85b1be5752e2fd52acff2e9d519c91f4b" have entirely different histories.
54c61e6a47
...
06d58fe85b
@ -35,13 +35,11 @@ export class StorageClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upload content to IPFS and optionally pin it.
|
* Upload content to IPFS and pin it.
|
||||||
* Supports both File objects (browser) and Buffer/ReadableStream (Node.js).
|
* Supports both File objects (browser) and Buffer/ReadableStream (Node.js).
|
||||||
*
|
*
|
||||||
* @param file - File to upload (File, Blob, or Buffer)
|
* @param file - File to upload (File, Blob, or Buffer)
|
||||||
* @param name - Optional filename
|
* @param name - Optional filename
|
||||||
* @param options - Optional upload options
|
|
||||||
* @param options.pin - Whether to pin the content (default: true). Pinning happens asynchronously on the backend.
|
|
||||||
* @returns Upload result with CID
|
* @returns Upload result with CID
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@ -55,15 +53,12 @@ export class StorageClient {
|
|||||||
* // Node.js
|
* // Node.js
|
||||||
* const fs = require('fs');
|
* const fs = require('fs');
|
||||||
* const fileBuffer = fs.readFileSync('image.jpg');
|
* const fileBuffer = fs.readFileSync('image.jpg');
|
||||||
* const result = await client.storage.upload(fileBuffer, 'image.jpg', { pin: true });
|
* const result = await client.storage.upload(fileBuffer, 'image.jpg');
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
async upload(
|
async upload(
|
||||||
file: File | Blob | ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>,
|
file: File | Blob | ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>,
|
||||||
name?: string,
|
name?: string
|
||||||
options?: {
|
|
||||||
pin?: boolean;
|
|
||||||
}
|
|
||||||
): Promise<StorageUploadResponse> {
|
): Promise<StorageUploadResponse> {
|
||||||
// Create FormData for multipart upload
|
// Create FormData for multipart upload
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
@ -106,10 +101,6 @@ export class StorageClient {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add pin flag (default: true)
|
|
||||||
const shouldPin = options?.pin !== false; // Default to true
|
|
||||||
formData.append("pin", shouldPin ? "true" : "false");
|
|
||||||
|
|
||||||
return this.httpClient.uploadFile<StorageUploadResponse>(
|
return this.httpClient.uploadFile<StorageUploadResponse>(
|
||||||
"/v1/storage/upload",
|
"/v1/storage/upload",
|
||||||
formData,
|
formData,
|
||||||
@ -201,64 +192,6 @@ export class StorageClient {
|
|||||||
throw lastError || new Error("Failed to retrieve content");
|
throw lastError || new Error("Failed to retrieve content");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve content from IPFS by CID and return the full Response object
|
|
||||||
* Useful when you need access to response headers (e.g., content-length)
|
|
||||||
*
|
|
||||||
* @param cid - Content ID to retrieve
|
|
||||||
* @returns Response object with body stream and headers
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* const response = await client.storage.getBinary(cid);
|
|
||||||
* const contentLength = response.headers.get('content-length');
|
|
||||||
* const reader = response.body.getReader();
|
|
||||||
* // ... read stream
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
async getBinary(cid: string): Promise<Response> {
|
|
||||||
// Retry logic for content retrieval - content may not be immediately available
|
|
||||||
// after upload due to eventual consistency in IPFS Cluster
|
|
||||||
// IPFS Cluster pins can take 2-3+ seconds to complete across all nodes
|
|
||||||
const maxAttempts = 8;
|
|
||||||
let lastError: Error | null = null;
|
|
||||||
|
|
||||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
||||||
try {
|
|
||||||
const response = await this.httpClient.getBinary(
|
|
||||||
`/v1/storage/get/${cid}`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!response) {
|
|
||||||
throw new Error("Response is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error: any) {
|
|
||||||
lastError = error;
|
|
||||||
|
|
||||||
// Check if this is a 404 error (content not found)
|
|
||||||
const isNotFound =
|
|
||||||
error?.httpStatus === 404 ||
|
|
||||||
error?.message?.includes("not found") ||
|
|
||||||
error?.message?.includes("404");
|
|
||||||
|
|
||||||
// If it's not a 404 error, or this is the last attempt, give up
|
|
||||||
if (!isNotFound || attempt === maxAttempts) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait before retrying (exponential backoff: 400ms, 800ms, 1200ms, etc.)
|
|
||||||
// This gives up to ~12 seconds total wait time, covering typical pin completion
|
|
||||||
const backoffMs = attempt * 2500;
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This should never be reached, but TypeScript needs it
|
|
||||||
throw lastError || new Error("Failed to retrieve content");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unpin a CID
|
* Unpin a CID
|
||||||
*
|
*
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user