|
|
|
@ -23,13 +23,17 @@ interface HandlerResponse { |
|
|
|
|
cleanUrl: string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export type getPackages = () => Promise<{ [name: string]: string }> |
|
|
|
|
|
|
|
|
|
export class RemixURLResolver { |
|
|
|
|
private previouslyHandled: PreviouslyHandledImports |
|
|
|
|
gistAccessToken: string |
|
|
|
|
protocol: string |
|
|
|
|
getDependencies: getPackages |
|
|
|
|
|
|
|
|
|
constructor (gistToken?: string, protocol = 'http:') { |
|
|
|
|
constructor (getDependencies?: getPackages, gistToken?: string, protocol = 'http:') { |
|
|
|
|
this.previouslyHandled = {} |
|
|
|
|
this.getDependencies = getDependencies |
|
|
|
|
this.setGistToken(gistToken, protocol) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -38,12 +42,16 @@ export class RemixURLResolver { |
|
|
|
|
this.protocol = protocol |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
clearCache () { |
|
|
|
|
this.previouslyHandled = {} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Handle an import statement based on github |
|
|
|
|
* @param root The root of the github import statement |
|
|
|
|
* @param filePath path of the file in github |
|
|
|
|
*/ |
|
|
|
|
async handleGithubCall (root: string, filePath: string): Promise<HandlerResponse> { |
|
|
|
|
async handleGithubCall(root: string, filePath: string): Promise<HandlerResponse> { |
|
|
|
|
const regex = filePath.match(/blob\/([^/]+)\/(.*)/) |
|
|
|
|
let reference = 'master' |
|
|
|
|
if (regex) { |
|
|
|
@ -67,7 +75,7 @@ export class RemixURLResolver { |
|
|
|
|
* @param url The url of the import statement |
|
|
|
|
* @param cleanUrl |
|
|
|
|
*/ |
|
|
|
|
async handleHttp (url: string, cleanUrl: string): Promise<HandlerResponse> { |
|
|
|
|
async handleHttp(url: string, cleanUrl: string): Promise<HandlerResponse> { |
|
|
|
|
// eslint-disable-next-line no-useless-catch
|
|
|
|
|
try { |
|
|
|
|
const response: AxiosResponse = await axios.get(url, { transformResponse: [] }) |
|
|
|
@ -82,7 +90,7 @@ export class RemixURLResolver { |
|
|
|
|
* @param url The url of the import statement |
|
|
|
|
* @param cleanUrl |
|
|
|
|
*/ |
|
|
|
|
async handleHttps (url: string, cleanUrl: string): Promise<HandlerResponse> { |
|
|
|
|
async handleHttps(url: string, cleanUrl: string): Promise<HandlerResponse> { |
|
|
|
|
// eslint-disable-next-line no-useless-catch
|
|
|
|
|
try { |
|
|
|
|
const response: AxiosResponse = await axios.get(url, { transformResponse: [] }) |
|
|
|
@ -92,7 +100,7 @@ export class RemixURLResolver { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async handleSwarm (url: string, cleanUrl: string): Promise<HandlerResponse> { |
|
|
|
|
async handleSwarm(url: string, cleanUrl: string): Promise<HandlerResponse> { |
|
|
|
|
// eslint-disable-next-line no-useless-catch
|
|
|
|
|
try { |
|
|
|
|
const bzz = new Bzz({ url: this.protocol + '//swarm-gateways.net' }) |
|
|
|
@ -108,7 +116,7 @@ export class RemixURLResolver { |
|
|
|
|
* Handle an import statement based on IPFS |
|
|
|
|
* @param url The url of the IPFS import statement |
|
|
|
|
*/ |
|
|
|
|
async handleIPFS (url: string): Promise<HandlerResponse> { |
|
|
|
|
async handleIPFS(url: string): Promise<HandlerResponse> { |
|
|
|
|
// replace ipfs:// with /ipfs/
|
|
|
|
|
url = url.replace(/^ipfs:\/\/?/, 'ipfs/') |
|
|
|
|
// eslint-disable-next-line no-useless-catch
|
|
|
|
@ -127,25 +135,68 @@ export class RemixURLResolver { |
|
|
|
|
* Handle an import statement based on NPM |
|
|
|
|
* @param url The url of the NPM import statement |
|
|
|
|
*/ |
|
|
|
|
async handleNpmImport (url: string): Promise<HandlerResponse> { |
|
|
|
|
const urls = ["https://cdn.jsdelivr.net/npm/", "https://unpkg.com/"] |
|
|
|
|
process && process.env && process.env['NPM_URL'] && urls.unshift(process.env['NPM_URL']) |
|
|
|
|
let content = null |
|
|
|
|
// get response from all urls
|
|
|
|
|
for (let i = 0; i < urls.length; i++) { |
|
|
|
|
try { |
|
|
|
|
const req = urls[i] + url |
|
|
|
|
const response: AxiosResponse = await axios.get(req, { transformResponse: [] }) |
|
|
|
|
content = response.data |
|
|
|
|
break |
|
|
|
|
} catch (e) { |
|
|
|
|
// try next url
|
|
|
|
|
|
|
|
|
|
async handleNpmImport(url: string): Promise<HandlerResponse> { |
|
|
|
|
if (this.getDependencies) { |
|
|
|
|
try { |
|
|
|
|
const { deps, yarnLock, packageLock } = await this.getDependencies() |
|
|
|
|
let matchLength = 0 |
|
|
|
|
let pkg |
|
|
|
|
if (deps) { |
|
|
|
|
Object.keys(deps).map((dep) => { |
|
|
|
|
const reg = new RegExp(dep, 'g') |
|
|
|
|
const match = url.match(reg) |
|
|
|
|
if (match && match.length > 0 && matchLength < match[0].length) { |
|
|
|
|
matchLength = match[0].length |
|
|
|
|
pkg = dep |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
if (pkg) { |
|
|
|
|
let version |
|
|
|
|
if (yarnLock) { |
|
|
|
|
// yarn.lock
|
|
|
|
|
const regex = new RegExp(`"${pkg}@(.*)"`, 'g') |
|
|
|
|
const yarnVersion = regex.exec(yarnLock) |
|
|
|
|
if (yarnVersion && yarnVersion.length > 1) { |
|
|
|
|
version = yarnVersion[1] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!version && packageLock && packageLock['dependencies'] && packageLock['dependencies'][pkg] && packageLock['dependencies'][pkg]['version']) { |
|
|
|
|
// package-lock.json
|
|
|
|
|
version = packageLock['dependencies'][pkg]['version'] |
|
|
|
|
} |
|
|
|
|
if (!version) { |
|
|
|
|
// package.json
|
|
|
|
|
version = deps[pkg] |
|
|
|
|
} |
|
|
|
|
if (version) url = url.replace(pkg, `${pkg}@${version}`) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} catch (e) { |
|
|
|
|
console.log(e) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!content) throw new Error('Unable to load ' + url) |
|
|
|
|
return { content, cleanUrl: url } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const npm_urls = ["https://cdn.jsdelivr.net/npm/", "https://unpkg.com/"] |
|
|
|
|
process && process.env && process.env['NPM_URL'] && npm_urls.unshift(process.env['NPM_URL']) |
|
|
|
|
let content = null |
|
|
|
|
// get response from all urls
|
|
|
|
|
for (let i = 0; i < npm_urls.length; i++) { |
|
|
|
|
try { |
|
|
|
|
const req = npm_urls[i] + url |
|
|
|
|
const response: AxiosResponse = await axios.get(req, { transformResponse: [] }) |
|
|
|
|
content = response.data |
|
|
|
|
break |
|
|
|
|
} catch (e) { |
|
|
|
|
// try next url
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
if (!content) throw new Error('Unable to load ' + url) |
|
|
|
|
return { content, cleanUrl: url } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getHandlers (): Handler[] { |
|
|
|
|
return [ |
|
|
|
@ -182,9 +233,9 @@ export class RemixURLResolver { |
|
|
|
|
] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async resolve (filePath: string, customHandlers?: Handler[]): Promise<Imported> { |
|
|
|
|
public async resolve (filePath: string, customHandlers?: Handler[], force?: boolean): Promise<Imported> { |
|
|
|
|
let imported: Imported = this.previouslyHandled[filePath] |
|
|
|
|
if (imported) { |
|
|
|
|
if (!force && imported) { |
|
|
|
|
return imported |
|
|
|
|
} |
|
|
|
|
const builtinHandlers: Handler[] = this.getHandlers() |
|
|
|
|