ipfs-storage
Version:
IPFS storage API providers.
88 lines (75 loc) • 2.78 kB
JavaScript
import { Blob } from "buffer";
import { CID } from "multiformats";
import { PinataSDK } from "pinata";
const uploadFile = async function (
connect = { jwt: "" },
file = { hash: "", ext: "", stream: "", buffer: "" }
) {
if (!connect.jwt) {
throw new Error("Pinata JWT is required.");
}
const pinata = new PinataSDK({ pinataJwt: connect.jwt });
const fileName = `${file.hash}${file.ext}`;
let fileContent = file.buffer;
// The SDK expects a File object, created from Blob/Buffer.
// Stream handling might be complex, relying on buffer for now.
if (!fileContent) {
if (file.stream) {
console.warn(
"Pinata provider currently prefers buffer input over streams. Attempting to read stream..."
);
// Consuming stream to buffer here can be memory intensive for large files.
// Consider alternatives if large stream uploads are common.
const chunks = [];
for await (const chunk of file.stream) {
chunks.push(chunk);
}
fileContent = Buffer.concat(chunks);
} else {
throw new Error("Pinata upload requires file buffer or stream.");
}
}
const blob = new Blob([fileContent]);
const fileObject = new File([blob], fileName); // Requires Node >= 18 (experimental) or >= 20
try {
const result = await pinata.upload.public.file(fileObject);
if (!result || !result.cid || !result.id) {
throw new Error(
"Pinata upload failed: Invalid response format or missing CID/ID."
);
}
const cid = CID.parse(result.cid);
const ipfsUrl = `https://${cid.toV1().toString()}.ipfs.dweb.link`;
// Return URL and Pinata ID (needed for deletion)
return { url: ipfsUrl, providerId: result.id };
} catch (err) {
console.error(`Pinata upload failed for ${fileName}:`, err);
// Attempt to parse Pinata API error response
const errorMessage =
err.response?.data?.error || err.message || "Unknown error";
throw new Error(`Pinata upload failed: ${errorMessage}`);
}
};
const deleteFile = async function (
connect = { jwt: "" },
file = { providerId: "" }
) {
if (!connect.jwt) {
throw new Error("Pinata JWT is required.");
}
if (!file.providerId) {
throw new Error("Pinata delete requires the Pinata file ID (providerId).");
}
const pinata = new PinataSDK({ pinataJwt: connect.jwt });
try {
// Delete expects an array of Pinata IDs
await pinata.files.public.delete([file.providerId]);
return true;
} catch (err) {
console.error(`Pinata delete failed for ID ${file.providerId}:`, err);
const errorMessage =
err.response?.data?.error || err.message || "Unknown error";
throw new Error(`Pinata delete failed: ${errorMessage}`);
}
};
export { deleteFile, uploadFile };