asset-resolver
Advanced tools
Comparing version 3.0.0 to 3.0.1
39
cli.js
@@ -9,19 +9,24 @@ #!/usr/bin/env node | ||
const cli = meow( | ||
` | ||
Usage | ||
$ asset-resolver <input> | ||
Options | ||
-b --base List of directories/URLs where we should start looking for assets. [Default: process.cwd()] | ||
Examples | ||
asset-resolver 'my.svg' -b 'some/directory' -b 'http://some.domain/assets' | ||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
<svg> | ||
... | ||
</svg> | ||
`, | ||
{ | ||
help: [ | ||
'Usage', | ||
'asset-resolver [input]', | ||
'', | ||
'Options', | ||
' -b --base List of directories/URLs where we should start looking for assets. [Default: process.cwd()]', | ||
'', | ||
'Examples', | ||
"$ asset-resolver 'my.svg' -b 'some/directory' -b 'http://some.domain/assets'", | ||
'<?xml version="1.0" encoding="UTF-8" standalone="no"?>', | ||
'<svg>', | ||
'...', | ||
'</svg>' | ||
] | ||
}, | ||
{alias: {b: 'base'}} | ||
flags: { | ||
base: { | ||
type: 'string', | ||
alias: 'b' | ||
} | ||
} | ||
} | ||
); | ||
@@ -32,3 +37,3 @@ | ||
.then((resource) => { | ||
console.log(resource.contents); | ||
console.log(resource.contents.toString()); | ||
}) | ||
@@ -35,0 +40,0 @@ .catch((error) => { |
48
index.js
'use strict'; | ||
const debug = require('debug')('asset-resolver'); | ||
const resolver = require('./lib/resolver'); | ||
function any(promises) { | ||
return Promise.all( | ||
promises.map((promise) => | ||
promise.then( | ||
(value) => { | ||
throw value; | ||
}, | ||
(error) => error | ||
) | ||
) | ||
).then( | ||
(reasons) => { | ||
throw reasons; | ||
}, | ||
(error) => error | ||
); | ||
} | ||
module.exports.getResource = (file, options = {}) => { | ||
const options_ = { | ||
module.exports.getResource = async (file, options = {}) => { | ||
const _options = { | ||
base: [process.cwd()], | ||
@@ -31,18 +11,14 @@ filter: () => true, | ||
if (!Array.isArray(options_.base)) { | ||
options_.base = [options_.base]; | ||
if (!Array.isArray(_options.base)) { | ||
_options.base = [_options.base]; | ||
} | ||
options_.base = resolver.glob([...options_.base]); | ||
const promises = (options_.base || []).map((base) => { | ||
return resolver.getResource(base, file, options_); | ||
}); | ||
return any(promises).catch((error) => { | ||
const message = [ | ||
`The file "${file}" could not be resolved because of:` | ||
].concat(error.map((err) => err.message)); | ||
debug(message); | ||
return Promise.reject(new Error(message.join('\n'))); | ||
}); | ||
try { | ||
const resource = await resolver.getResource(file, _options); | ||
return resource; | ||
} catch (error) { | ||
throw new Error( | ||
`The file "${file}" could not be resolved because of:\n${error.message}` | ||
); | ||
} | ||
}; |
@@ -13,3 +13,2 @@ 'use strict'; | ||
const cache = {}; | ||
const readFile = util.promisify(fs.readFile); | ||
@@ -21,21 +20,2 @@ | ||
function handle(filter) { | ||
return (resource) => { | ||
debug('handle request', resource.path); | ||
return Promise.resolve(resource) | ||
.then(filter) | ||
.then((result) => { | ||
if (!result) { | ||
debug('FAILED'); | ||
return Promise.reject( | ||
new Error(`${resource.path} rejected by filter`) | ||
); | ||
} | ||
debug('Passed filter:', resource.path); | ||
return resource; | ||
}); | ||
}; | ||
} | ||
/** | ||
@@ -112,3 +92,3 @@ * Token generated by concatenating username and password with `:` character within a base64 encoded string. | ||
contents: body, | ||
path: resource, | ||
path: path.resolve(resource), | ||
mime: mimeType | ||
@@ -163,15 +143,55 @@ }; | ||
function getResource(base, file, options) { | ||
const resource = join(base, file); | ||
if (cache[resource]) { | ||
return cache[resource].then(handle(options.filter)); | ||
async function getResource(file, options) { | ||
const {base, filter = () => true, cwd: _cwd = process.cwd(), glob = {}} = | ||
options || {}; | ||
const cwd = glob.cwd || _cwd; | ||
const searchBase = Array.isArray(base) ? base : [base].filter((r) => r); | ||
const patterns = searchBase.map((base) => join(base, file)); | ||
const errors = []; | ||
// try files first | ||
const globPatterns = patterns | ||
.filter((pattern) => !isUrl(pattern)) | ||
.map((dirPattern) => | ||
// fix for https://github.com/mrmlnc/fast-glob/issues/266 | ||
path.isAbsolute(dirPattern) | ||
? normalize(path.relative(cwd, dirPattern)) | ||
: normalize(dirPattern) | ||
); | ||
const filepaths = (await globby(globPatterns, {cwd, ...glob})) || []; | ||
if (filepaths) { | ||
for (const filepath of filepaths) { | ||
const resource = await readAsync(filepath); | ||
if (await filter(resource)) { | ||
return resource; | ||
} | ||
errors.push(new Error(`${filepath} rejected by filter`)); | ||
} | ||
} | ||
if (isUrl(resource)) { | ||
cache[resource] = requestAsync(resource, options); | ||
} else { | ||
cache[resource] = readAsync(resource); | ||
if (filepaths.length === 0 && globPatterns.length > 0) { | ||
errors.push(new Error(`No such file or directory: ${globPatterns}`)); | ||
} | ||
return cache[resource].then(handle(options.filter)); | ||
const urls = patterns.filter((resource) => isUrl(resource)); | ||
for (const url of urls) { | ||
try { | ||
const resource = await requestAsync(url, options); | ||
if (await filter(resource)) { | ||
return resource; | ||
} | ||
errors.push(new Error(`${url} rejected by filter`)); | ||
} catch (error) { | ||
errors.push(error); | ||
} | ||
} | ||
throw new Error(errors.map((error) => `${error.message}\n`)); | ||
} | ||
@@ -178,0 +198,0 @@ |
{ | ||
"name": "asset-resolver", | ||
"version": "3.0.0", | ||
"version": "3.0.1", | ||
"description": "Find an asset in a set of locations", | ||
@@ -53,2 +53,3 @@ "license": "MIT", | ||
"rules": { | ||
"no-await-in-loop": "off", | ||
"capitalized-comments": "off", | ||
@@ -55,0 +56,0 @@ "promise/prefer-await-to-then": "off" |
12405
217