@graphprotocol/graph-cli
Version:
CLI for building for and deploying to The Graph
62 lines (61 loc) • 2.61 kB
JavaScript
import os from 'node:os';
import path from 'node:path';
import fs from 'fs-extra';
import { DEFAULT_IPFS_URL } from './ipfs.js';
export async function resolveFile(source, fileName, timeout = 10_000) {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('File download timed out')), timeout);
});
const resolvePromise = async () => {
// If it's a local file
try {
await fs.access(source, fs.constants.R_OK);
const stats = await fs.stat(source);
if (!stats.isFile()) {
throw new Error('Must be a file');
}
return { path: source };
}
catch (error) {
if (error.code !== 'ENOENT') {
throw new Error(`Local file is not accessible: ${error.message}`);
}
}
// Create temp directory for downloads
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'graph-file-'));
const cleanup = () => fs.removeSync(tempDir);
try {
// If it's an IPFS hash (Qm...)
if (source.startsWith('Qm')) {
const response = await fetch(`${DEFAULT_IPFS_URL}/cat?arg=${source}`);
if (!response.ok) {
throw new Error(`failed to fetch from IPFS: ${response.statusText}`);
}
const filePath = path.join(tempDir, fileName);
const buffer = Buffer.from(await response.arrayBuffer());
await fs.writeFile(filePath, buffer);
return { path: filePath, cleanup };
}
// If it's a URL
if (source.startsWith('http')) {
const response = await fetch(source, { redirect: 'follow' });
if (!response.ok) {
throw new Error(`failed to fetch from URL: ${response.statusText}`);
}
const filePath = path.join(tempDir, fileName);
const buffer = Buffer.from(await response.arrayBuffer());
await fs.writeFile(filePath, buffer);
return { path: filePath, cleanup };
}
throw new Error('Invalid file source. Must be a file path, IPFS hash, or URL');
}
catch (error) {
cleanup();
if (error instanceof Error) {
throw new Error(`Failed to resolve ${source} - ${error.message}`);
}
throw new Error(`Failed to resolve ${source}`);
}
};
return Promise.race([resolvePromise(), timeoutPromise]);
}