-
-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
240 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
const os = require('os') | ||
const path = require('path') | ||
|
||
exports.CACHE_DIR = path.join(os.homedir(), '.import-http') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
const fetch = require('node-fetch') | ||
|
||
module.exports = async (url, opts) => { | ||
console.log(`Downloading ${url}...`) | ||
const res = await fetch(url, opts) | ||
if (!res.ok) { | ||
console.error(`Failed to download ${url}...`) | ||
throw new Error(res.statusText) | ||
} | ||
return res | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,117 +1,8 @@ | ||
const os = require('os') | ||
const path = require('path') | ||
const { parse: parseURL, resolve: resolveURL } = require('url') | ||
const fetch = require('node-fetch') | ||
const builtinModules = require('builtin-modules') | ||
const { pathExists, outputFile } = require('./utils') | ||
const createHttpCache = require('./http-cache') | ||
|
||
const RESOLVER_ID = 'import-http-resolver' | ||
|
||
const HTTP_RE = /^https?:\/\// | ||
|
||
class ImportHttpPlugin { | ||
constructor(options = {}) { | ||
this.reload = options.reload | ||
this.cacheDir = options.cacheDir | ||
? path.resolve(options.cacheDir) | ||
: path.join(os.homedir(), '.import-http') | ||
this.depsDir = path.join(this.cacheDir, 'deps') | ||
this.httpCache = createHttpCache(path.join(this.cacheDir, 'requests.json')) | ||
// Map<file, moduleId> | ||
this.fileModuleCache = new Map() | ||
} | ||
|
||
getFilePathFromURL(url) { | ||
const { host, pathname, protocol } = parseURL(url) | ||
// Where should this url be in the disk | ||
return path.join(this.depsDir, protocol.replace(':', ''), host, pathname) | ||
} | ||
|
||
apply(compiler) { | ||
compiler.resolverFactory.hooks.resolver | ||
.for('normal') | ||
.tap(RESOLVER_ID, resolver => { | ||
const resolvedHook = resolver.ensureHook(`resolve`) | ||
|
||
resolver | ||
.getHook(`described-resolve`) | ||
.tapAsync( | ||
RESOLVER_ID, | ||
async (requestContext, resolveContext, callback) => { | ||
let id = requestContext.request | ||
const { issuer } = requestContext.context | ||
|
||
// if the issuer is a URL (cached in deps dir) | ||
// resolve the url | ||
if ( | ||
!HTTP_RE.test(id) && | ||
issuer && | ||
this.fileModuleCache.has(issuer) && | ||
!this.fileModuleCache.has(id) | ||
) { | ||
if (/^\./.test(id)) { | ||
// Relative file | ||
// Excluded something like ./node_modules/webpack/buildin/global.js | ||
if (!/node_modules/.test(id)) { | ||
id = resolveURL(this.fileModuleCache.get(issuer), id) | ||
} | ||
} else if (!builtinModules.includes(id)) { | ||
// Propably an npm package | ||
id = `https://unpkg.com/${id}` | ||
} | ||
} | ||
|
||
if (!HTTP_RE.test(id)) { | ||
return callback() | ||
} | ||
|
||
const canResolve = (request, url) => { | ||
this.fileModuleCache.set(request, url) | ||
resolver.doResolve( | ||
resolvedHook, | ||
Object.assign({}, requestContext, { | ||
request | ||
}), | ||
null, | ||
resolveContext, | ||
callback | ||
) | ||
} | ||
|
||
try { | ||
// Let's get the actual URL | ||
const url = await this.httpCache.get(id) | ||
let file | ||
|
||
if (url && !this.reload) { | ||
file = this.getFilePathFromURL(url) | ||
if (await pathExists(file)) { | ||
return canResolve(file, url) | ||
} | ||
} | ||
|
||
// We have never requested this before | ||
console.log(`Downloading ${id}...`) | ||
const res = await fetch(id) | ||
if (!res.ok) { | ||
console.error(`Failed to download ${id}...`) | ||
throw new Error(res.statusText) | ||
} | ||
file = this.getFilePathFromURL(res.url) | ||
await this.httpCache.set(id, res.url) | ||
const content = await res | ||
.buffer() | ||
.then(buff => buff.toString('utf8')) | ||
await outputFile(file, content, 'utf8') | ||
canResolve(file, res.url) | ||
} catch (error) { | ||
callback(error) | ||
} | ||
} | ||
) | ||
}) | ||
module.exports = { | ||
get WebpackPlugin() { | ||
return require('./webpack') | ||
}, | ||
get rollupPlugin() { | ||
return require('./rollup') | ||
} | ||
} | ||
|
||
module.exports = ImportHttpPlugin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
const path = require('path') | ||
const { parse: parseURL } = require('url') | ||
const { | ||
outputFile, | ||
pathExists, | ||
readFile, | ||
HTTP_RE, | ||
resolveURL | ||
} = require('./utils') | ||
const createHttpCache = require('./http-cache') | ||
const { CACHE_DIR } = require('./constants') | ||
const fetch = require('./fetch') | ||
|
||
const PREFIX = '\0' | ||
|
||
const removePrefix = id => id && id.replace(/^\0/, '') | ||
|
||
const shouldLoad = id => { | ||
return HTTP_RE.test(removePrefix(id)) | ||
} | ||
|
||
module.exports = ({ reload, cacheDir = CACHE_DIR } = {}) => { | ||
const DEPS_DIR = path.join(cacheDir, 'deps') | ||
const HTTP_CACHE_FILE = path.join(cacheDir, 'requests.json') | ||
|
||
const getFilePathFromURL = url => { | ||
const { host, pathname, protocol } = parseURL(url) | ||
// Where should this url be in the disk | ||
return path.join(DEPS_DIR, protocol.replace(':', ''), host, pathname) | ||
} | ||
|
||
const httpCache = createHttpCache(HTTP_CACHE_FILE) | ||
|
||
return { | ||
name: 'http', | ||
|
||
async resolveId(importee, importer) { | ||
// We're importing from URL | ||
if (HTTP_RE.test(importee)) { | ||
return PREFIX + importee | ||
} | ||
|
||
// We're importing a file but the importer the a URL | ||
// Then we should do | ||
if (importer) { | ||
importer = importer.replace(/^\0/, '') | ||
if (HTTP_RE.test(importer)) { | ||
return resolveURL(importer, importee) | ||
} | ||
} | ||
}, | ||
|
||
async load(id) { | ||
if (!shouldLoad(id)) return | ||
|
||
id = removePrefix(id) | ||
const url = await httpCache.get(id) | ||
let file | ||
|
||
if (url && !reload) { | ||
file = getFilePathFromURL(url) | ||
if (await pathExists(file)) { | ||
return readFile(file, 'utf8') | ||
} | ||
} | ||
|
||
// We have never requested this before | ||
const res = await fetch(url) | ||
file = getFilePathFromURL(res.url) | ||
await httpCache.set(id, res.url) | ||
const content = await res.buffer().then(buff => buff.toString('utf8')) | ||
await outputFile(file, content, 'utf8') | ||
|
||
return content | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.