import axios, { AxiosResponse } from 'axios' export interface Imported { content: string; cleanURL: string; type: string; } interface PreviouslyHandledImports { [filePath: string]: Imported } interface Handler { type: string; match(url: string): any; handle(match: any): any; } export class RemixURLResolver { private previouslyHandled: PreviouslyHandledImports constructor() { this.previouslyHandled = {} } /** * Handle an import statement based on github * @params root The root of the github import statement * @params filePath path of the file in github */ async handleGithubCall(root: string, filePath: string) { try { let req: string = 'https://api.github.com/repos/' + root + '/contents/' + filePath const response: AxiosResponse = await axios.get(req) return Buffer.from(response.data.content, 'base64').toString() } catch(e) { throw e } } /** * Handle an import statement based on http * @params url The url of the import statement * @params cleanURL */ async handleHttp(url: string, _: string) { try { const response: AxiosResponse = await axios.get(url) return response.data } catch(e) { throw e } } /** * Handle an import statement based on https * @params url The url of the import statement * @params cleanURL */ async handleHttps(url: string, _: string) { try { const response: AxiosResponse = await axios.get(url) return response.data } catch(e) { throw e } } handleSwarm(url: string, cleanURL: string) { return } /** * Handle an import statement based on IPFS * @params url The url of the IPFS import statement */ async handleIPFS(url: string) { // replace ipfs:// with /ipfs/ url = url.replace(/^ipfs:\/\/?/, 'ipfs/') try { const req = 'https://gateway.ipfs.io/' + url // If you don't find greeter.sol on ipfs gateway use local // const req = 'http://localhost:8080/' + url const response: AxiosResponse = await axios.get(req) return response.data } catch (e) { throw e } } getHandlers(): Handler[] { return [ { type: 'github', match: (url) => { return /^(https?:\/\/)?(www.)?github.com\/([^/]*\/[^/]*)\/(.*)/.exec(url) }, handle: (match) => this.handleGithubCall(match[3], match[4]) }, { type: 'http', match: (url) => { return /^(http?:\/\/?(.*))$/.exec(url) }, handle: (match) => this.handleHttp(match[1], match[2]) }, { type: 'https', match: (url) => { return /^(https?:\/\/?(.*))$/.exec(url) }, handle: (match) => this.handleHttps(match[1], match[2]) }, { type: 'swarm', match: (url) => { return /^(bzz-raw?:\/\/?(.*))$/.exec(url) }, handle: (match) => this.handleSwarm(match[1], match[2]) }, { type: 'ipfs', match: (url) => { return /^(ipfs:\/\/?.+)/.exec(url) }, handle: (match) => this.handleIPFS(match[1]) } ] } public async resolve(filePath: string, customHandlers?: Handler[]): Promise { var imported: Imported = this.previouslyHandled[filePath] if(imported) { return imported } const builtinHandlers: Handler[] = this.getHandlers() const handlers: Handler[] = customHandlers ? [...builtinHandlers, ...customHandlers] : [...builtinHandlers] const matchedHandler = handlers.filter(handler => handler.match(filePath)) const handler: Handler = matchedHandler[0] const match = handler.match(filePath) const content: string = await handler.handle(match) imported = { content, cleanURL: filePath, type: handler.type } this.previouslyHandled[filePath] = imported return imported } }