Change tag parser for better file support

Should support mp3, ogg, wav, flac and more.
This commit is contained in:
Lynn Smeria 2018-08-17 19:53:14 +03:00
parent 09fa089cfe
commit 15483c0354
7 changed files with 112 additions and 71 deletions

20
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,20 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Organise",
"args": ["${workspaceFolder}/src/cli.js", "organise", "test", "out"],
"console": "integratedTerminal",
"skipFiles": [
"${workspaceRoot}/node_modules/**/*.js",
"<node_internals>/**/*.js"
],
"env": {
"DEBUG": "publikator:*",
"DEBUG_COLORS": "1"
}
}
]
}

View file

@ -1,10 +1,10 @@
{ {
"name": "publikator", "name": "publikator",
"version": "0.1.0", "version": "0.2.0",
"main": "index.js", "main": "index.js",
"repository": "https://github.com/aengl/publikator.git", "repository": "https://github.com/aengl/publikator.git",
"author": "Lynn Smeria <ae@cephea.de>", "author": "Lynn Smeria <ae@cephea.de>",
"license": "MIT", "license": "Unlicense",
"bin": { "bin": {
"publikator": "publikator.js" "publikator": "publikator.js"
}, },
@ -16,8 +16,8 @@
"debug": "3.1.0", "debug": "3.1.0",
"fs-extra": "7.0.0", "fs-extra": "7.0.0",
"js-yaml": "3.12.0", "js-yaml": "3.12.0",
"jsmediatags": "3.8.1",
"lodash": "4.17.10", "lodash": "4.17.10",
"music-metadata": "2.6.0",
"sanitize-filename": "1.6.1", "sanitize-filename": "1.6.1",
"walkdir": "0.0.12" "walkdir": "0.0.12"
}, },

View file

@ -18,17 +18,10 @@ module.exports = {
'track-count': tracks.length, 'track-count': tracks.length,
tracks: tracks.map((track, i) => ({ tracks: tracks.map((track, i) => ({
path: track.path, path: track.path,
size: track.size,
position: i, position: i,
...tags.getTags(track, [ common: track.common,
'title', format: track.format,
'artist', ...tags.getTags(track, ['foo']),
'album',
'year',
'comment',
'track',
'genre',
]),
})), })),
}; };
}) })

View file

@ -5,9 +5,10 @@ const sanitize = require('sanitize-filename');
const debug = require('debug')('publikator:organise'); const debug = require('debug')('publikator:organise');
const tags = require('./tags'); const tags = require('./tags');
const getFolderName = file => `${file.tags.artist} - ${file.tags.album}`; const getArtists = file => file.common.artist || file.common.artists.join(', ');
const getFolderName = file => `${getArtists(file)} - ${file.common.album}`;
const getFileName = file => const getFileName = file =>
`${file.tags.track} - ${file.tags.title}${path.extname(file.path)}`; `${file.common.track.no} - ${file.common.title}${path.extname(file.path)}`;
module.exports = { module.exports = {
/** /**
@ -22,7 +23,12 @@ module.exports = {
*/ */
byAlbum: async (root, taggedFiles) => { byAlbum: async (root, taggedFiles) => {
const files = taggedFiles.filter(file => const files = taggedFiles.filter(file =>
tags.hasTags(file, ['artist', 'album', 'track', 'title']) tags.hasTags(file, [
'common.artists',
'common.album',
'common.track',
'common.title',
])
); );
debug(`grouping tracks by album`); debug(`grouping tracks by album`);

View file

@ -22,7 +22,7 @@ module.exports = {
/** /**
* Reads ID3 tags from all files and returns an array in the form of: * Reads ID3 tags from all files and returns an array in the form of:
* [{ path, size, tags }, ...] * [{ path, common, format, native }, ...]
*/ */
readTags: files => { readTags: files => {
debug(`reading tags from ${files.length} file(s)`); debug(`reading tags from ${files.length} file(s)`);
@ -31,8 +31,7 @@ module.exports = {
const info = await tags.readTags(file); const info = await tags.readTags(file);
return { return {
path: file, path: file,
size: info.size, ...info,
tags: info.tags,
}; };
}) })
); );

View file

@ -1,4 +1,5 @@
const jsmediatags = require('jsmediatags'); const _ = require('lodash');
const mm = require('music-metadata');
const debug = require('debug')('publikator:tags'); const debug = require('debug')('publikator:tags');
module.exports = { module.exports = {
@ -6,24 +7,17 @@ module.exports = {
* Reads tags from a track. * Reads tags from a track.
*/ */
readTags: file => readTags: file =>
new Promise((resolve, reject) => { mm.parseFile(file, {
jsmediatags.read(file, { duration: true,
onSuccess: info => { native: true,
resolve(info); skipCovers: false,
},
onError: error => {
debug(error.type);
debug(error.info);
reject(error);
},
});
}), }),
/** /**
* Returns true if a file has all required tags. * Returns true if a file has all required tags.
*/ */
hasTags: (taggedFile, tags) => { hasTags: (taggedFile, tags) => {
if (tags.some(tag => taggedFile.tags[tag] === undefined)) { if (tags.some(tag => _.get(taggedFile, tag) === undefined)) {
debug(`track'${taggedFile.path}' is missing one or more required tags`); debug(`track'${taggedFile.path}' is missing one or more required tags`);
return false; return false;
} }
@ -35,8 +29,9 @@ module.exports = {
*/ */
getTags: (taggedFile, tags) => getTags: (taggedFile, tags) =>
tags.reduce((all, tag) => { tags.reduce((all, tag) => {
if (taggedFile.tags[tag] !== undefined) { const value = _.get(taggedFile, tag);
all[tag] = taggedFile.tags[tag]; // eslint-disable-line if (value !== undefined) {
all[tag] = value; // eslint-disable-line
} }
return all; return all;
}, {}), }, {}),

102
yarn.lock
View file

@ -21,13 +21,13 @@ ajv-keywords@^3.0.0:
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a"
ajv@^6.0.1, ajv@^6.5.0: ajv@^6.0.1, ajv@^6.5.0:
version "6.5.2" version "6.5.3"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.2.tgz#678495f9b82f7cca6be248dd92f59bff5e1f4360" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.3.tgz#71a569d189ecf4f4f321224fecb166f071dd90f9"
dependencies: dependencies:
fast-deep-equal "^2.0.1" fast-deep-equal "^2.0.1"
fast-json-stable-stringify "^2.0.0" fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1" json-schema-traverse "^0.4.1"
uri-js "^4.2.1" uri-js "^4.2.2"
ansi-align@^2.0.0: ansi-align@^2.0.0:
version "2.0.0" version "2.0.0"
@ -150,8 +150,8 @@ async@~1.0.0:
resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9"
atob@^2.1.1: atob@^2.1.1:
version "2.1.1" version "2.1.2"
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
axobject-query@^2.0.1: axobject-query@^2.0.1:
version "2.0.1" version "2.0.1"
@ -326,9 +326,9 @@ chownr@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181"
ci-info@^1.0.0: ci-info@^1.3.0:
version "1.2.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.2.0.tgz#8d1e9cb4051482ff70cd52a89b4b095a8fb635f6" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.4.0.tgz#4841d53cad49f11b827b648ebde27a6e189b412f"
circular-json@^0.3.1: circular-json@^0.3.1:
version "0.3.3" version "0.3.3"
@ -510,11 +510,10 @@ deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
define-properties@^1.1.2: define-properties@^1.1.2:
version "1.1.2" version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
dependencies: dependencies:
foreach "^2.0.5" object-keys "^1.0.12"
object-keys "^1.0.8"
define-property@^0.2.5: define-property@^0.2.5:
version "0.2.5" version "0.2.5"
@ -610,6 +609,10 @@ es-to-primitive@^1.1.1:
is-date-object "^1.0.1" is-date-object "^1.0.1"
is-symbol "^1.0.1" is-symbol "^1.0.1"
es6-promise@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29"
escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
@ -886,6 +889,10 @@ file-entry-cache@^2.0.0:
flat-cache "^1.2.1" flat-cache "^1.2.1"
object-assign "^4.0.1" object-assign "^4.0.1"
file-type@9:
version "9.0.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-9.0.0.tgz#a68d5ad07f486414dfb2c8866f73161946714a18"
fill-range@^4.0.0: fill-range@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
@ -921,10 +928,6 @@ for-in@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
foreach@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
fragment-cache@^0.2.1: fragment-cache@^0.2.1:
version "0.2.1" version "0.2.1"
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
@ -1234,10 +1237,10 @@ is-callable@^1.1.1, is-callable@^1.1.3:
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
is-ci@^1.0.10: is-ci@^1.0.10:
version "1.1.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.1.0.tgz#247e4162e7860cebbdaf30b774d6b0ac7dcfe7a5" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.0.tgz#3f4a08d6303a09882cef3f0fb97439c5f5ce2d53"
dependencies: dependencies:
ci-info "^1.0.0" ci-info "^1.3.0"
is-data-descriptor@^0.1.4: is-data-descriptor@^0.1.4:
version "0.1.4" version "0.1.4"
@ -1417,12 +1420,6 @@ js-yaml@3.12.0, js-yaml@^3.11.0:
argparse "^1.0.7" argparse "^1.0.7"
esprima "^4.0.0" esprima "^4.0.0"
jsmediatags@3.8.1:
version "3.8.1"
resolved "https://registry.yarnpkg.com/jsmediatags/-/jsmediatags-3.8.1.tgz#e27d26e957b0b330c28f9762c82940c4dcc64720"
dependencies:
xhr2 "^0.1.4"
json-schema-traverse@^0.4.1: json-schema-traverse@^0.4.1:
version "0.4.1" version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
@ -1567,6 +1564,10 @@ map-visit@^1.0.0:
dependencies: dependencies:
object-visit "^1.0.0" object-visit "^1.0.0"
media-typer@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
micromatch@^3.1.4: micromatch@^3.1.4:
version "3.1.10" version "3.1.10"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
@ -1639,6 +1640,18 @@ ms@2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
music-metadata@2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/music-metadata/-/music-metadata-2.6.0.tgz#a913a3a1de73b965158c243a5e188be9ec901ff9"
dependencies:
debug "^3.1.0"
es6-promise "^4.2.4"
file-type "9"
media-typer "^0.3.0"
strtok3 "^1.5.3"
then-read-stream "^1.2.1"
token-types "^0.9.4"
mute-stream@0.0.6: mute-stream@0.0.6:
version "0.0.6" version "0.0.6"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db"
@ -1791,7 +1804,7 @@ object-copy@^0.1.0:
define-property "^0.2.5" define-property "^0.2.5"
kind-of "^3.0.3" kind-of "^3.0.3"
object-keys@^1.0.11, object-keys@^1.0.8: object-keys@^1.0.11, object-keys@^1.0.12:
version "1.0.12" version "1.0.12"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2"
@ -2107,8 +2120,8 @@ remove-trailing-separator@^1.0.1:
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
repeat-element@^1.1.2: repeat-element@^1.1.2:
version "1.1.2" version "1.1.3"
resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
repeat-string@^1.6.1: repeat-string@^1.6.1:
version "1.6.1" version "1.6.1"
@ -2206,8 +2219,8 @@ semver-diff@^2.0.0:
semver "^5.0.3" semver "^5.0.3"
"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0: "semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0:
version "5.5.0" version "5.5.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477"
set-blocking@~2.0.0: set-blocking@~2.0.0:
version "2.0.0" version "2.0.0"
@ -2417,13 +2430,22 @@ strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
strtok3@^1.5.3:
version "1.5.3"
resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-1.5.3.tgz#a788ce5b43cd5365d61ae9c7620113b2c94c068f"
dependencies:
debug "^3.1.0"
es6-promise "^4.2.4"
then-read-stream "^1.2.1"
token-types "^0.9.4"
supports-color@^2.0.0: supports-color@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
supports-color@^5.2.0, supports-color@^5.3.0: supports-color@^5.2.0, supports-color@^5.3.0:
version "5.4.0" version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
dependencies: dependencies:
has-flag "^3.0.0" has-flag "^3.0.0"
@ -2477,6 +2499,12 @@ text-table@^0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
then-read-stream@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/then-read-stream/-/then-read-stream-1.2.1.tgz#9baddcb8a4ebc8a6fb36436985d24c36f7908829"
dependencies:
es6-promise "^4.2.4"
through@2, through@^2.3.6, through@~2.3, through@~2.3.1: through@2, through@^2.3.6, through@~2.3, through@~2.3.1:
version "2.3.8" version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
@ -2519,6 +2547,10 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2" regex-not "^1.0.2"
safe-regex "^1.1.0" safe-regex "^1.1.0"
token-types@^0.9.4:
version "0.9.4"
resolved "https://registry.yarnpkg.com/token-types/-/token-types-0.9.4.tgz#ea24c5c3fc577292a1d362a252e348a0016361ad"
touch@^3.1.0: touch@^3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b"
@ -2596,7 +2628,7 @@ update-notifier@^2.3.0:
semver-diff "^2.0.0" semver-diff "^2.0.0"
xdg-basedir "^3.0.0" xdg-basedir "^3.0.0"
uri-js@^4.2.1: uri-js@^4.2.2:
version "4.2.2" version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
dependencies: dependencies:
@ -2690,10 +2722,6 @@ xdg-basedir@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
xhr2@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f"
yallist@^2.1.2: yallist@^2.1.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"