@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]);
}