Add support for more MusicBrainz features, improve test coverage

This commit is contained in:
Brian Beck 2016-12-09 18:55:41 -08:00
parent b6f2e2d3f7
commit 325c6db0ce
65 changed files with 973 additions and 437 deletions

View file

@ -1,7 +1,7 @@
{ {
"presets": ["es2015", "stage-2"], "presets": ["es2015", "stage-2"],
"plugins": ["transform-runtime"], "plugins": ["transform-runtime"],
"ignore": "test/**", "only": ["scripts/**", "src/**", "test/helpers/**"],
"env": { "env": {
"test": { "test": {
"plugins": ["istanbul"] "plugins": ["istanbul"]

View file

@ -34,8 +34,8 @@
"start:dev": "nodemon --exec babel-node src/index.js", "start:dev": "nodemon --exec babel-node src/index.js",
"test": "npm run lint && npm run test:coverage", "test": "npm run lint && npm run test:coverage",
"test:coverage": "cross-env NODE_ENV=test nyc npm run test:only", "test:coverage": "cross-env NODE_ENV=test nyc npm run test:only",
"test:only": "cross-env VCR_MODE=cache ava", "test:only": "cross-env VCR_MODE=playback ava",
"test:record": "rimraf test/fixtures && npm run test:only -- --serial", "test:record": "cross-env VCR_MODE=record ava",
"test:watch": "npm run test:only -- --watch", "test:watch": "npm run test:only -- --watch",
"update-schema": "npm run -s print-schema:json > schema.json" "update-schema": "npm run -s print-schema:json > schema.json"
}, },
@ -64,7 +64,6 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"babel-runtime": "^6.18.0", "babel-runtime": "^6.18.0",
"chalk": "^1.1.3",
"compression": "^1.6.2", "compression": "^1.6.2",
"dashify": "^0.2.2", "dashify": "^0.2.2",
"dataloader": "^1.2.0", "dataloader": "^1.2.0",

View file

@ -1,14 +1,12 @@
import { graphql, introspectionQuery, printSchema } from 'graphql' import { graphql, introspectionQuery, printSchema } from 'graphql'
import schema from '../src/schema' import schema from '../src/schema'
if (require.main === module) { if (process.argv[2] === '--json') {
if (process.argv[2] === '--json') { graphql(schema, introspectionQuery).then(result => {
graphql(schema, introspectionQuery).then(result => { console.log(JSON.stringify(result, null, 2))
console.log(JSON.stringify(result, null, 2)) }).catch(err => {
}).catch(err => { console.error(err)
console.error(err) })
}) } else {
} else { console.log(printSchema(schema))
console.log(printSchema(schema))
}
} }

View file

@ -1,7 +1,6 @@
import request from 'request' import request from 'request'
import retry from 'retry' import retry from 'retry'
import qs from 'qs' import qs from 'qs'
import chalk from 'chalk'
import ExtendableError from 'es6-error' import ExtendableError from 'es6-error'
import RateLimit from './rate-limit' import RateLimit from './rate-limit'
import pkg from '../package.json' import pkg from '../package.json'
@ -164,6 +163,9 @@ export default class MusicBrainz {
} }
getLookupURL (entity, id, params) { getLookupURL (entity, id, params) {
if (id == null) {
return this.getBrowseURL(entity, params)
}
return this.getURL(`${entity}/${id}`, params) return this.getURL(`${entity}/${id}`, params)
} }
@ -190,19 +192,3 @@ export default class MusicBrainz {
return this.get(url) return this.get(url)
} }
} }
if (require.main === module) {
const client = new MusicBrainz()
const fn = (id) => {
return client.lookup('artist', id).then(artist => {
console.log(chalk.green(`Done: ${id}${artist.name}`))
}).catch(err => {
console.log(chalk.red(`Error: ${id}${err}`))
})
}
fn('f1106b17-dcbb-45f6-b938-199ccfab50cc')
fn('a74b1b7f-71a5-4011-9441-d0b5e4122711')
fn('9b5ae4cc-15ae-4f0b-8a4e-8c44e42ba52a')
fn('26f77379-968b-4435-b486-fc9acb4590d3')
fn('8538e728-ca0b-4321-b7e5-cff6565dd4c0')
}

View file

@ -3,7 +3,6 @@ import { forwardConnectionArgs } from 'graphql-relay'
import { resolveBrowse } from '../resolvers' import { resolveBrowse } from '../resolvers'
import { import {
MBID, MBID,
URLString,
AreaConnection, AreaConnection,
ArtistConnection, ArtistConnection,
EventConnection, EventConnection,
@ -12,10 +11,9 @@ import {
RecordingConnection, RecordingConnection,
ReleaseConnection, ReleaseConnection,
ReleaseGroupConnection, ReleaseGroupConnection,
URLConnection,
WorkConnection WorkConnection
} from '../types' } from '../types'
import { toWords } from '../types/helpers' import { toWords, releaseGroupType, releaseStatus } from '../types/helpers'
const area = { const area = {
type: MBID, type: MBID,
@ -115,22 +113,19 @@ entity.`,
release, but is not included in the credits for the release itself.` release, but is not included in the credits for the release itself.`
}, },
recording, recording,
releaseGroup releaseGroup,
type: releaseGroupType,
status: releaseStatus
}), }),
releaseGroups: createBrowseField(ReleaseGroupConnection, { releaseGroups: createBrowseField(ReleaseGroupConnection, {
artist, artist,
collection, collection,
release release,
type: releaseGroupType
}), }),
works: createBrowseField(WorkConnection, { works: createBrowseField(WorkConnection, {
artist, artist,
collection collection
}),
urls: createBrowseField(URLConnection, {
resource: {
type: URLString,
description: 'The web address for which to browse URL entities.'
}
}) })
} }
}) })

View file

@ -7,21 +7,23 @@ import {
Event, Event,
Instrument, Instrument,
Label, Label,
MBID,
Place, Place,
Recording, Recording,
Release, Release,
ReleaseGroup, ReleaseGroup,
Series, Series,
URL, URL,
URLString,
Work Work
} from '../types' } from '../types'
function createLookupField (entity) { function createLookupField (entity, args) {
const typeName = toWords(entity.name) const typeName = toWords(entity.name)
return { return {
type: entity, type: entity,
description: `Look up a specific ${typeName} by its MBID.`, description: `Look up a specific ${typeName} by its MBID.`,
args: { mbid }, args: { mbid, ...args },
resolve: resolveLookup resolve: resolveLookup
} }
} }
@ -40,7 +42,18 @@ export const LookupQuery = new GraphQLObjectType({
release: createLookupField(Release), release: createLookupField(Release),
releaseGroup: createLookupField(ReleaseGroup), releaseGroup: createLookupField(ReleaseGroup),
series: createLookupField(Series), series: createLookupField(Series),
url: createLookupField(URL), url: createLookupField(URL, {
mbid: {
...mbid,
// Remove the non-null requirement that is usually on the `mbid` field
// so that URLs can be looked up by `resource`.
type: MBID
},
resource: {
type: URLString,
description: 'The web address of the URL entity to look up.'
}
}),
work: createLookupField(Work) work: createLookupField(Work)
} }
}) })

View file

@ -17,7 +17,6 @@ export default class RateLimit {
this.periodCapacity = this.limit this.periodCapacity = this.limit
this.timer = null this.timer = null
this.pendingFlush = false this.pendingFlush = false
this.paused = false
this.prevTaskID = null this.prevTaskID = null
} }
@ -27,20 +26,6 @@ export default class RateLimit {
return id return id
} }
pause () {
clearTimeout(this.timer)
this.paused = true
}
unpause () {
this.paused = false
this.flush()
}
clear () {
this.queues.length = 0
}
enqueue (fn, args, priority = this.defaultPriority) { enqueue (fn, args, priority = this.defaultPriority) {
priority = Math.max(0, priority) priority = Math.max(0, priority)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -76,9 +61,6 @@ export default class RateLimit {
} }
flush () { flush () {
if (this.paused) {
return
}
if (this.numPending < this.concurrency && this.periodCapacity > 0) { if (this.numPending < this.concurrency && this.periodCapacity > 0) {
const task = this.dequeue() const task = this.dequeue()
if (task) { if (task) {
@ -118,37 +100,3 @@ export default class RateLimit {
} }
} }
} }
if (require.main === module) {
const t0 = Date.now()
const logTime = (...args) => {
const t = Date.now()
console.log(`[t=${t - t0}]`, ...args)
}
const limiter = new RateLimit({
limit: 3,
period: 3000,
concurrency: 5
})
const fn = (i) => {
return new Promise((resolve) => {
setTimeout(() => {
logTime(`Finished task ${i}`)
resolve(i)
}, 7000)
})
}
limiter.enqueue(fn, [1])
limiter.enqueue(fn, [2])
limiter.enqueue(fn, [3])
limiter.enqueue(fn, [4], 2)
limiter.enqueue(fn, [5], 10)
limiter.enqueue(fn, [6])
limiter.enqueue(fn, [7])
limiter.enqueue(fn, [8])
limiter.enqueue(fn, [9])
limiter.enqueue(fn, [10])
}

View file

@ -63,9 +63,12 @@ export function includeSubqueries (params, info, fragments = info.fragments) {
return params return params
} }
export function resolveLookup (root, { mbid }, { loaders }, info) { export function resolveLookup (root, { mbid, ...params }, { loaders }, info) {
if (!mbid && !params.resource) {
throw new Error('Lookups by a field other than MBID must provide: resource')
}
const entityType = toDashed(info.fieldName) const entityType = toDashed(info.fieldName)
let params = includeSubqueries({}, info) params = includeSubqueries(params, info)
params = includeRelationships(params, info) params = includeRelationships(params, info)
return loaders.lookup.load([entityType, mbid, params]) return loaders.lookup.load([entityType, mbid, params])
} }

View file

@ -1,8 +1,8 @@
import { import {
GraphQLObjectType, GraphQLObjectType,
GraphQLString,
GraphQLBoolean GraphQLBoolean
} from 'graphql/type' } from 'graphql/type'
import { Locale } from './scalars'
import { name, sortName, fieldWithID } from './helpers' import { name, sortName, fieldWithID } from './helpers'
export default new GraphQLObjectType({ export default new GraphQLObjectType({
@ -17,7 +17,7 @@ entity will be given as a result even if the actual name wouldnt be.`,
}, },
sortName, sortName,
locale: { locale: {
type: GraphQLString, type: Locale,
description: `The locale (language and/or country) in which the alias is description: `The locale (language and/or country) in which the alias is
used.` used.`
}, },

View file

@ -202,6 +202,16 @@ export const artistCredit = {
resolve: createSubqueryResolver() resolve: createSubqueryResolver()
} }
export const releaseGroupType = {
type: new GraphQLList(ReleaseGroupType),
description: 'Filter by one or more release group types.'
}
export const releaseStatus = {
type: new GraphQLList(ReleaseStatus),
description: 'Filter by one or more release statuses.'
}
export const artists = linkedQuery(ArtistConnection) export const artists = linkedQuery(ArtistConnection)
export const events = linkedQuery(EventConnection) export const events = linkedQuery(EventConnection)
export const labels = linkedQuery(LabelConnection) export const labels = linkedQuery(LabelConnection)
@ -209,22 +219,13 @@ export const places = linkedQuery(PlaceConnection)
export const recordings = linkedQuery(RecordingConnection) export const recordings = linkedQuery(RecordingConnection)
export const releases = linkedQuery(ReleaseConnection, { export const releases = linkedQuery(ReleaseConnection, {
args: { args: {
type: { type: releaseGroupType,
type: new GraphQLList(ReleaseGroupType), status: releaseStatus
description: 'Filter by one or more release group types.'
},
status: {
type: new GraphQLList(ReleaseStatus),
description: 'Filter by one or more release statuses.'
}
} }
}) })
export const releaseGroups = linkedQuery(ReleaseGroupConnection, { export const releaseGroups = linkedQuery(ReleaseGroupConnection, {
args: { args: {
type: { type: releaseGroupType
type: new GraphQLList(ReleaseGroupType),
description: 'Filter by one or more release group types.'
}
} }
}) })
export const tags = linkedQuery(TagConnection, { export const tags = linkedQuery(TagConnection, {

View file

@ -1,7 +1,7 @@
import { GraphQLObjectType, GraphQLString, GraphQLList } from 'graphql/type' import { GraphQLObjectType, GraphQLString, GraphQLList } from 'graphql/type'
import Node from './node' import Node from './node'
import Entity from './entity' import Entity from './entity'
import { DateType } from './scalars' import { ASIN, DateType } from './scalars'
import { ReleaseStatus } from './enums' import { ReleaseStatus } from './enums'
import ReleaseEvent from './release-event' import ReleaseEvent from './release-event'
import { import {
@ -52,6 +52,11 @@ distribution mechanism.`
type: GraphQLString, type: GraphQLString,
description: 'The country in which the release was issued.' description: 'The country in which the release was issued.'
}, },
asin: {
type: ASIN,
description: `The [Amazon Standard Identification Number](https://musicbrainz.org/doc/ASIN)
of the release.`
},
barcode: { barcode: {
type: GraphQLString, type: GraphQLString,
description: `The [barcode](https://en.wikipedia.org/wiki/Barcode), if the description: `The [barcode](https://en.wikipedia.org/wiki/Barcode), if the

View file

@ -1,7 +1,24 @@
import { Kind } from 'graphql/language' import { Kind } from 'graphql/language'
import { GraphQLScalarType } from 'graphql/type' import { GraphQLScalarType } from 'graphql/type'
function createScalar (config) {
return new GraphQLScalarType({
serialize: value => value,
parseValue: value => value,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return ast.value
}
return null
},
...config
})
}
const uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ const uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
const locale = /^([a-z]{2})(_[A-Z]{2})?(\.[A-Z0-9-]+)?$/
// Be extremely lenient; just prevent major input errors.
const url = /^\w+:\/\/[\w-]+\.\w+/
function validateMBID (value) { function validateMBID (value) {
if (typeof value === 'string' && uuid.test(value)) { if (typeof value === 'string' && uuid.test(value)) {
@ -17,34 +34,38 @@ function validatePositive (value) {
throw new TypeError(`Expected positive value: ${value}`) throw new TypeError(`Expected positive value: ${value}`)
} }
export const DateType = new GraphQLScalarType({ function validateLocale (value) {
if (typeof value === 'string' && locale.test(value)) {
return value
}
throw new TypeError(`Malformed locale: ${value}`)
}
function validateURL (value) {
if (typeof value === 'string' && url.test(value)) {
return value
}
throw new TypeError(`Malformed URL: ${value}`)
}
export const ASIN = createScalar({
name: 'ASIN',
description: `An [Amazon Standard Identification Number](https://musicbrainz.org/doc/ASIN)
(ASIN) is a 10-character alphanumeric unique identifier assigned by Amazon.com
and its partners for product identification within the Amazon organization.`
})
export const DateType = createScalar({
name: 'Date', name: 'Date',
description: description: 'Year, month (optional), and day (optional) in YYYY-MM-DD format.'
'Year, month (optional), and day (optional) in YYYY-MM-DD format.',
serialize: value => value,
parseValue: value => value,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return ast.value
}
return null
}
}) })
export const Degrees = new GraphQLScalarType({ export const Degrees = createScalar({
name: 'Degrees', name: 'Degrees',
description: 'Decimal degrees, used for latitude and longitude.', description: 'Decimal degrees, used for latitude and longitude.'
serialize: value => value,
parseValue: value => value,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return ast.value
}
return null
}
}) })
export const Duration = new GraphQLScalarType({ export const Duration = createScalar({
name: 'Duration', name: 'Duration',
description: 'A length of time, in milliseconds.', description: 'A length of time, in milliseconds.',
serialize: validatePositive, serialize: validatePositive,
@ -57,91 +78,41 @@ export const Duration = new GraphQLScalarType({
} }
}) })
export const IPI = new GraphQLScalarType({ export const IPI = createScalar({
name: 'IPI', name: 'IPI',
description: `An [IPI](https://musicbrainz.org/doc/IPI) (interested party description: `An [IPI](https://musicbrainz.org/doc/IPI) (interested party
information) code is an identifying number assigned by the CISAC database for information) code is an identifying number assigned by the CISAC database for
musical rights management.`, musical rights management.`
serialize: value => value,
parseValue: value => value,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return ast.value
}
return null
}
}) })
export const ISNI = new GraphQLScalarType({ export const ISNI = createScalar({
name: 'ISNI', name: 'ISNI',
description: `The [International Standard Name Identifier](https://musicbrainz.org/doc/ISNI) description: `The [International Standard Name Identifier](https://musicbrainz.org/doc/ISNI)
(ISNI) is an ISO standard for uniquely identifying the public identities of (ISNI) is an ISO standard for uniquely identifying the public identities of
contributors to media content.`, contributors to media content.`
serialize: value => value,
parseValue: value => value,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return ast.value
}
return null
}
}) })
export const ISWC = new GraphQLScalarType({ export const ISWC = createScalar({
name: 'ISWC', name: 'ISWC',
description: `The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC) description: `The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC)
(ISWC) is an ISO standard similar to ISBNs for identifying musical works / (ISWC) is an ISO standard similar to ISBNs for identifying musical works /
compositions.`, compositions.`
serialize: value => value,
parseValue: value => value,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return ast.value
}
return null
}
}) })
export const Locale = new GraphQLScalarType({ export const Locale = createScalar({
name: 'Locale', name: 'Locale',
description: 'Language code, optionally with country and encoding.', description: 'Language code, optionally with country and encoding.',
serialize: value => value, serialize: validateLocale,
parseValue: value => value, parseValue: validateLocale,
parseLiteral (ast) { parseLiteral (ast) {
if (ast.kind === Kind.STRING) { if (ast.kind === Kind.STRING) {
return ast.value return validateLocale(ast.value)
} }
return null return null
} }
}) })
export const Time = new GraphQLScalarType({ export const MBID = createScalar({
name: 'Time',
description: 'A time of day, in 24-hour hh:mm notation.',
serialize: value => value,
parseValue: value => value,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return ast.value
}
return null
}
})
export const URLString = new GraphQLScalarType({
name: 'URLString',
description: 'A web address.',
serialize: value => value,
parseValue: value => value,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return ast.value
}
return null
}
})
export const MBID = new GraphQLScalarType({
name: 'MBID', name: 'MBID',
description: `The MBID scalar represents MusicBrainz identifiers, which are description: `The MBID scalar represents MusicBrainz identifiers, which are
36-character UUIDs.`, 36-character UUIDs.`,
@ -154,3 +125,21 @@ export const MBID = new GraphQLScalarType({
return null return null
} }
}) })
export const Time = createScalar({
name: 'Time',
description: 'A time of day, in 24-hour hh:mm notation.'
})
export const URLString = createScalar({
name: 'URLString',
description: 'A web address.',
serialize: validateURL,
parseValue: validateURL,
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return validateURL(ast.value)
}
return null
}
})

View file

@ -1,15 +1,6 @@
import path from 'path'
import test from 'ava' import test from 'ava'
import sepia from 'sepia' import { MusicBrainzError } from '../src/api'
import MusicBrainz, { MusicBrainzError } from '../src/api' import client from './helpers/client'
sepia.fixtureDir(path.join(__dirname, 'fixtures'))
let client
test.before(t => {
client = new MusicBrainz()
})
test('getLookupURL() generates a lookup URL', t => { test('getLookupURL() generates a lookup URL', t => {
t.is(client.getLookupURL('artist', 'c8da2e40-bd28-4d4e-813a-bd2f51958ba8', { t.is(client.getLookupURL('artist', 'c8da2e40-bd28-4d4e-813a-bd2f51958ba8', {
@ -37,9 +28,8 @@ test('lookup() sends a lookup query', t => {
}) })
test('rejects the promise when the API returns an error', t => { test('rejects the promise when the API returns an error', t => {
t.throws( const req = client.lookup('artist', '5b11f4ce-a62d-471e-81fc-a69a8278c7da', {
client.lookup('artist', '5b11f4ce-a62d-471e-81fc-a69a8278c7da', { inc: ['foobar']
inc: ['foobar'] })
}), MusicBrainzError return t.throws(req, MusicBrainzError)
)
}) })

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:00 GMT", "date": "Fri, 09 Dec 2016 21:53:05 GMT",
"content-type": "application/json; charset=UTF-8", "content-type": "application/json; charset=UTF-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "303", "x-ratelimit-remaining": "365",
"x-ratelimit-reset": "1481236321", "x-ratelimit-reset": "1481320386",
"last-modified": "Wed, 09 Nov 2016 23:43:24 GMT", "last-modified": "Wed, 09 Nov 2016 23:43:24 GMT",
"server": "Jetty(9.3.10.v20160621)", "server": "Jetty(9.3.10.v20160621)",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/recording?query=Burn%20the%20Witch&fmt=json", "url": "http://musicbrainz.org:80/ws/2/recording?query=Burn%20the%20Witch&fmt=json",
"time": 596, "time": 508,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

Binary file not shown.

View file

@ -0,0 +1,29 @@
{
"statusCode": 200,
"headers": {
"date": "Sat, 10 Dec 2016 02:52:35 GMT",
"content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked",
"connection": "keep-alive",
"keep-alive": "timeout=15",
"vary": "Accept-Encoding",
"x-ratelimit-limit": "700",
"x-ratelimit-remaining": "352",
"x-ratelimit-reset": "1481338356",
"server": "Plack::Handler::Starlet",
"etag": "W/\"6e4fd0ce8e71cdb68d2f23d878327605\"",
"access-control-allow-origin": "*",
"content-encoding": "gzip"
},
"url": "http://musicbrainz.org:80/ws/2/release/d5cdb7fd-c7e9-460a-9549-8a369655cc52?fmt=json",
"time": 486,
"request": {
"method": "GET",
"headers": {
"User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org",
"accept-encoding": "gzip, deflate",
"accept": "application/json"
}
}
}

Binary file not shown.

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:02 GMT", "date": "Fri, 09 Dec 2016 21:53:05 GMT",
"content-type": "application/json; charset=UTF-8", "content-type": "application/json; charset=UTF-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "334", "x-ratelimit-remaining": "363",
"x-ratelimit-reset": "1481236323", "x-ratelimit-reset": "1481320386",
"last-modified": "Thu, 08 Dec 2016 22:03:30 GMT", "last-modified": "Fri, 09 Dec 2016 21:37:57 GMT",
"server": "Jetty(9.3.10.v20160621)", "server": "Jetty(9.3.10.v20160621)",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/label?limit=1&query=Apple%20Records&fmt=json", "url": "http://musicbrainz.org:80/ws/2/label?limit=1&query=Apple%20Records&fmt=json",
"time": 1539, "time": 582,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

View file

@ -1,20 +1,20 @@
{ {
"statusCode": 400, "statusCode": 400,
"headers": { "headers": {
"date": "Fri, 09 Dec 2016 00:06:41 GMT", "date": "Fri, 09 Dec 2016 21:53:05 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"content-length": "72", "content-length": "72",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "575", "x-ratelimit-remaining": "429",
"x-ratelimit-reset": "1481242002", "x-ratelimit-reset": "1481320386",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "\"d54d2bc5c412c1bb3c02bfc91d13a900\"", "etag": "\"d54d2bc5c412c1bb3c02bfc91d13a900\"",
"access-control-allow-origin": "*" "access-control-allow-origin": "*"
}, },
"url": "http://musicbrainz.org:80/ws/2/artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da?inc=foobar&fmt=json", "url": "http://musicbrainz.org:80/ws/2/artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da?inc=foobar&fmt=json",
"time": 613, "time": 396,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {

View file

@ -0,0 +1 @@
{"resource":"http://www.nirvana.com/","id":"4347ffe2-82ec-4059-9520-6a1a3f73a304"}

View file

@ -0,0 +1,27 @@
{
"statusCode": 200,
"headers": {
"date": "Sat, 10 Dec 2016 00:43:25 GMT",
"content-type": "application/json; charset=utf-8",
"content-length": "82",
"connection": "keep-alive",
"keep-alive": "timeout=15",
"x-ratelimit-limit": "700",
"x-ratelimit-remaining": "542",
"x-ratelimit-reset": "1481330606",
"server": "Plack::Handler::Starlet",
"etag": "\"d2b2ef09f302f15cd08587ad1e02d9ef\"",
"access-control-allow-origin": "*"
},
"url": "http://musicbrainz.org:80/ws/2/url?resource=http%3A%2F%2Fwww.nirvana.com%2F&fmt=json",
"time": 486,
"request": {
"method": "GET",
"headers": {
"User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org",
"accept-encoding": "gzip, deflate",
"accept": "application/json"
}
}
}

Binary file not shown.

View file

@ -0,0 +1,29 @@
{
"statusCode": 200,
"headers": {
"date": "Sat, 10 Dec 2016 02:31:10 GMT",
"content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked",
"connection": "keep-alive",
"keep-alive": "timeout=15",
"vary": "Accept-Encoding",
"x-ratelimit-limit": "700",
"x-ratelimit-remaining": "381",
"x-ratelimit-reset": "1481337071",
"server": "Plack::Handler::Starlet",
"etag": "W/\"76d4b01f2f2f2713907e9d82646b801a\"",
"access-control-allow-origin": "*",
"content-encoding": "gzip"
},
"url": "http://musicbrainz.org:80/ws/2/release?artist=5b11f4ce-a62d-471e-81fc-a69a8278c7da&type=ep&status=bootleg&fmt=json",
"time": 590,
"request": {
"method": "GET",
"headers": {
"User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org",
"accept-encoding": "gzip, deflate",
"accept": "application/json"
}
}
}

Binary file not shown.

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:31:58 GMT", "date": "Fri, 09 Dec 2016 21:53:05 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "180", "x-ratelimit-remaining": "368",
"x-ratelimit-reset": "1481236319", "x-ratelimit-reset": "1481320386",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "W/\"15092bd7b55df20c4f8fd072b82a0f1f\"", "etag": "W/\"05d3a423b0b8ea0f99c184f8131c7cac\"",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/artist/c8da2e40-bd28-4d4e-813a-bd2f51958ba8?fmt=json", "url": "http://musicbrainz.org:80/ws/2/artist/c8da2e40-bd28-4d4e-813a-bd2f51958ba8?fmt=json",
"time": 426, "time": 419,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

Binary file not shown.

View file

@ -0,0 +1,29 @@
{
"statusCode": 200,
"headers": {
"date": "Fri, 09 Dec 2016 21:53:05 GMT",
"content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked",
"connection": "keep-alive",
"keep-alive": "timeout=15",
"vary": "Accept-Encoding",
"x-ratelimit-limit": "700",
"x-ratelimit-remaining": "369",
"x-ratelimit-reset": "1481320386",
"server": "Plack::Handler::Starlet",
"etag": "W/\"617be9e745c8ab9b5097353b14655232\"",
"access-control-allow-origin": "*",
"content-encoding": "gzip"
},
"url": "http://musicbrainz.org:80/ws/2/artist/65314b12-0e08-43fa-ba33-baaa7b874c15?fmt=json",
"time": 416,
"request": {
"method": "GET",
"headers": {
"User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org",
"accept-encoding": "gzip, deflate",
"accept": "application/json"
}
}
}

Binary file not shown.

View file

@ -0,0 +1,29 @@
{
"statusCode": 200,
"headers": {
"date": "Fri, 09 Dec 2016 23:32:25 GMT",
"content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked",
"connection": "keep-alive",
"keep-alive": "timeout=15",
"vary": "Accept-Encoding",
"x-ratelimit-limit": "700",
"x-ratelimit-remaining": "352",
"x-ratelimit-reset": "1481326345",
"server": "Plack::Handler::Starlet",
"etag": "W/\"cd4a6370a1597ab7cb7ed51617049d2f\"",
"access-control-allow-origin": "*",
"content-encoding": "gzip"
},
"url": "http://musicbrainz.org:80/ws/2/area/489ce91b-6658-3307-9877-795b68554c98?fmt=json",
"time": 416,
"request": {
"method": "GET",
"headers": {
"User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org",
"accept-encoding": "gzip, deflate",
"accept": "application/json"
}
}
}

Binary file not shown.

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:06 GMT", "date": "Fri, 09 Dec 2016 21:53:18 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "289", "x-ratelimit-remaining": "225",
"x-ratelimit-reset": "1481236327", "x-ratelimit-reset": "1481320398",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "W/\"6a12c1ded7c7c8d9315107669601ed70\"", "etag": "W/\"5626413881801f644e96284425f962ef\"",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/artist/300c4c73-33ac-4255-9d57-4e32627f5e13?inc=artist-rels&fmt=json", "url": "http://musicbrainz.org:80/ws/2/artist/300c4c73-33ac-4255-9d57-4e32627f5e13?inc=artist-rels&fmt=json",
"time": 556, "time": 496,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

Binary file not shown.

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:06 GMT", "date": "Fri, 09 Dec 2016 21:53:18 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "287", "x-ratelimit-remaining": "228",
"x-ratelimit-reset": "1481236327", "x-ratelimit-reset": "1481320398",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "W/\"cfec247269cfa3680afeab36d412221c\"", "etag": "W/\"079599c4dc85b7d5376d1ff936519512\"",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/artist/0d4ab0f9-bbda-4ab1-ae2c-f772ffcfbea9?inc=artist-rels&fmt=json", "url": "http://musicbrainz.org:80/ws/2/artist/0d4ab0f9-bbda-4ab1-ae2c-f772ffcfbea9?inc=artist-rels&fmt=json",
"time": 517, "time": 430,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

Binary file not shown.

View file

@ -0,0 +1,29 @@
{
"statusCode": 200,
"headers": {
"date": "Fri, 09 Dec 2016 23:50:40 GMT",
"content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked",
"connection": "keep-alive",
"keep-alive": "timeout=15",
"vary": "Accept-Encoding",
"x-ratelimit-limit": "700",
"x-ratelimit-remaining": "543",
"x-ratelimit-reset": "1481327442",
"server": "Plack::Handler::Starlet",
"etag": "W/\"80d5da0c3f297592e23e0bc3f0beea82\"",
"access-control-allow-origin": "*",
"content-encoding": "gzip"
},
"url": "http://musicbrainz.org:80/ws/2/artist/f99b7d67-4e63-4678-aa66-4c6ac0f7d24a?inc=aliases&fmt=json",
"time": 539,
"request": {
"method": "GET",
"headers": {
"User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org",
"accept-encoding": "gzip, deflate",
"accept": "application/json"
}
}
}

View file

@ -1 +1 @@
{"primary-type":"Album","disambiguation":"","title":"Lures","secondary-types":[],"id":"e37d2740-4503-4e3f-ab6d-e622a25e964d","secondary-type-ids":[],"first-release-date":"2014-10-07","primary-type-id":"f529b476-6e62-324f-b0aa-1f3e33d313fc"} {"primary-type":"Album","primary-type-id":"f529b476-6e62-324f-b0aa-1f3e33d313fc","title":"Lures","first-release-date":"2014-10-07","secondary-type-ids":[],"disambiguation":"","id":"e37d2740-4503-4e3f-ab6d-e622a25e964d","secondary-types":[]}

View file

@ -1,24 +1,24 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:00 GMT", "date": "Fri, 09 Dec 2016 21:53:05 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"content-length": "240", "content-length": "240",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "504", "x-ratelimit-remaining": "372",
"x-ratelimit-reset": "1481236321", "x-ratelimit-reset": "1481320386",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "\"89bacb0f43473ab326be8f6ba1f42afd\"", "etag": "\"3dba57e694e0ee8ca9730d90a1601bfb\"",
"access-control-allow-origin": "*" "access-control-allow-origin": "*"
}, },
"url": "http://musicbrainz.org:80/ws/2/release-group/e37d2740-4503-4e3f-ab6d-e622a25e964d?fmt=json", "url": "http://musicbrainz.org:80/ws/2/release-group/e37d2740-4503-4e3f-ab6d-e622a25e964d?fmt=json",
"time": 588, "time": 424,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

View file

@ -0,0 +1 @@
{"id":"ef7d0814-da6a-32f5-a600-ff81cffd1aed","language":"mul","type":"Song","title":"Song of the French Partisan","attributes":[],"disambiguation":"","iswcs":["T-900.755.682-3"],"type-id":"f061270a-2fd6-32f1-a641-f0f8676d14e6"}

View file

@ -0,0 +1,27 @@
{
"statusCode": 200,
"headers": {
"date": "Fri, 09 Dec 2016 23:59:46 GMT",
"content-type": "application/json; charset=utf-8",
"content-length": "227",
"connection": "keep-alive",
"keep-alive": "timeout=15",
"x-ratelimit-limit": "700",
"x-ratelimit-remaining": "399",
"x-ratelimit-reset": "1481327987",
"server": "Plack::Handler::Starlet",
"etag": "\"8cfcefbad616638c208f7d6f28321cac\"",
"access-control-allow-origin": "*"
},
"url": "http://musicbrainz.org:80/ws/2/work/ef7d0814-da6a-32f5-a600-ff81cffd1aed?fmt=json",
"time": 416,
"request": {
"method": "GET",
"headers": {
"User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org",
"accept-encoding": "gzip, deflate",
"accept": "application/json"
}
}
}

Binary file not shown.

View file

@ -0,0 +1,29 @@
{
"statusCode": 200,
"headers": {
"date": "Fri, 09 Dec 2016 21:53:11 GMT",
"content-type": "application/json; charset=UTF-8",
"transfer-encoding": "chunked",
"connection": "keep-alive",
"keep-alive": "timeout=15",
"vary": "Accept-Encoding",
"x-ratelimit-limit": "700",
"x-ratelimit-remaining": "560",
"x-ratelimit-reset": "1481320392",
"last-modified": "Fri, 09 Dec 2016 21:01:38 GMT",
"server": "Jetty(9.3.10.v20160621)",
"access-control-allow-origin": "*",
"content-encoding": "gzip"
},
"url": "http://musicbrainz.org:80/ws/2/artist?limit=1&query=Leonard%20Cohen&fmt=json",
"time": 419,
"request": {
"method": "GET",
"headers": {
"User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org",
"accept-encoding": "gzip, deflate",
"accept": "application/json"
}
}
}

Binary file not shown.

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:05 GMT", "date": "Fri, 09 Dec 2016 21:53:16 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "697", "x-ratelimit-remaining": "104",
"x-ratelimit-reset": "1481236327", "x-ratelimit-reset": "1481320396",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "W/\"9020613941ca4d7631fab0e7d51d077f\"", "etag": "W/\"17516f4a3648cd4259751af5341b0d1b\"",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/release?label=cf7fc5cf-e011-4ef4-b511-cd0188537910&limit=1&fmt=json", "url": "http://musicbrainz.org:80/ws/2/release?label=cf7fc5cf-e011-4ef4-b511-cd0188537910&limit=1&fmt=json",
"time": 390, "time": 420,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

Binary file not shown.

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:11 GMT", "date": "Fri, 09 Dec 2016 21:53:22 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "254", "x-ratelimit-remaining": "260",
"x-ratelimit-reset": "1481236331", "x-ratelimit-reset": "1481320402",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "W/\"285b663debaf6f383194dcb82b6655e1\"", "etag": "W/\"a2a6b542d767ee02cb3e2a0ec5f79525\"",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/artist/ba550d0e-adac-4864-b88b-407cab5e76af?inc=artist-rels&fmt=json", "url": "http://musicbrainz.org:80/ws/2/artist/ba550d0e-adac-4864-b88b-407cab5e76af?inc=artist-rels&fmt=json",
"time": 677, "time": 548,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

Binary file not shown.

View file

@ -0,0 +1,29 @@
{
"statusCode": 200,
"headers": {
"date": "Fri, 09 Dec 2016 21:53:11 GMT",
"content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked",
"connection": "keep-alive",
"keep-alive": "timeout=15",
"vary": "Accept-Encoding",
"x-ratelimit-limit": "700",
"x-ratelimit-remaining": "555",
"x-ratelimit-reset": "1481320392",
"server": "Plack::Handler::Starlet",
"etag": "W/\"9a9c2cdbc92df7efa25d42bd9169b9a8\"",
"access-control-allow-origin": "*",
"content-encoding": "gzip"
},
"url": "http://musicbrainz.org:80/ws/2/artist?area=3f504d54-c40c-487d-bc16-c1990eac887f&fmt=json",
"time": 1072,
"request": {
"method": "GET",
"headers": {
"User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org",
"accept-encoding": "gzip, deflate",
"accept": "application/json"
}
}
}

Binary file not shown.

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:01 GMT", "date": "Fri, 09 Dec 2016 21:53:11 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "147", "x-ratelimit-remaining": "559",
"x-ratelimit-reset": "1481236321", "x-ratelimit-reset": "1481320392",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "W/\"2dd0bb83c0e5e4f352ffbf3a1272050d\"", "etag": "W/\"d4f25526cc965da41321e414529517ef\"",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/release-group?artist=c8da2e40-bd28-4d4e-813a-bd2f51958ba8&inc=artist-credits&fmt=json", "url": "http://musicbrainz.org:80/ws/2/release-group?artist=c8da2e40-bd28-4d4e-813a-bd2f51958ba8&inc=artist-credits&fmt=json",
"time": 439, "time": 416,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

Binary file not shown.

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:10 GMT", "date": "Fri, 09 Dec 2016 21:53:22 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "255", "x-ratelimit-remaining": "263",
"x-ratelimit-reset": "1481236331", "x-ratelimit-reset": "1481320402",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "W/\"dbec5286f8302667b6edff5be3352490\"", "etag": "W/\"6594e99cea0327cd0491b879ebeb6baf\"",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/artist/49a51491-650e-44b3-8085-2f07ac2986dd?inc=artist-rels&fmt=json", "url": "http://musicbrainz.org:80/ws/2/artist/49a51491-650e-44b3-8085-2f07ac2986dd?inc=artist-rels&fmt=json",
"time": 672, "time": 419,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

Binary file not shown.

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:06 GMT", "date": "Fri, 09 Dec 2016 21:53:17 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "570", "x-ratelimit-remaining": "607",
"x-ratelimit-reset": "1481236327", "x-ratelimit-reset": "1481320398",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "W/\"00e70096bc0434f732f47e3050094637\"", "etag": "W/\"86e889bbf99d0bd3b567fa8888299b53\"",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/artist?release=2ac3cbf2-f0d0-3678-af5f-b62dcb051bc0&inc=artist-rels&fmt=json", "url": "http://musicbrainz.org:80/ws/2/artist?release=2ac3cbf2-f0d0-3678-af5f-b62dcb051bc0&inc=artist-rels&fmt=json",
"time": 841, "time": 1132,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

Binary file not shown.

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:11 GMT", "date": "Fri, 09 Dec 2016 21:53:22 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "253", "x-ratelimit-remaining": "258",
"x-ratelimit-reset": "1481236331", "x-ratelimit-reset": "1481320402",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "W/\"262816d2e746629059388bf96eb1241d\"", "etag": "W/\"8b0d167a80f1f60f6b0ccdb1254ea172\"",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/artist/4d5447d7-c61c-4120-ba1b-d7f471d385b9?inc=artist-rels&fmt=json", "url": "http://musicbrainz.org:80/ws/2/artist/4d5447d7-c61c-4120-ba1b-d7f471d385b9?inc=artist-rels&fmt=json",
"time": 676, "time": 508,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

Binary file not shown.

View file

@ -1,26 +1,26 @@
{ {
"statusCode": 200, "statusCode": 200,
"headers": { "headers": {
"date": "Thu, 08 Dec 2016 22:32:06 GMT", "date": "Fri, 09 Dec 2016 21:53:18 GMT",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked", "transfer-encoding": "chunked",
"connection": "keep-alive", "connection": "keep-alive",
"keep-alive": "timeout=15", "keep-alive": "timeout=15",
"vary": "Accept-Encoding", "vary": "Accept-Encoding",
"x-ratelimit-limit": "700", "x-ratelimit-limit": "700",
"x-ratelimit-remaining": "288", "x-ratelimit-remaining": "220",
"x-ratelimit-reset": "1481236327", "x-ratelimit-reset": "1481320398",
"server": "Plack::Handler::Starlet", "server": "Plack::Handler::Starlet",
"etag": "W/\"7c937ac3dcff44777fa9d4c32d65b803\"", "etag": "W/\"5da167e635ba53580f8c82e6958f2ec9\"",
"access-control-allow-origin": "*", "access-control-allow-origin": "*",
"content-encoding": "gzip" "content-encoding": "gzip"
}, },
"url": "http://musicbrainz.org:80/ws/2/artist/42a8f507-8412-4611-854f-926571049fa0?inc=artist-rels&fmt=json", "url": "http://musicbrainz.org:80/ws/2/artist/42a8f507-8412-4611-854f-926571049fa0?inc=artist-rels&fmt=json",
"time": 558, "time": 488,
"request": { "request": {
"method": "GET", "method": "GET",
"headers": { "headers": {
"User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org", "host": "musicbrainz.org",
"accept-encoding": "gzip, deflate", "accept-encoding": "gzip, deflate",
"accept": "application/json" "accept": "application/json"

Binary file not shown.

View file

@ -0,0 +1,29 @@
{
"statusCode": 200,
"headers": {
"date": "Fri, 09 Dec 2016 22:08:27 GMT",
"content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked",
"connection": "keep-alive",
"keep-alive": "timeout=15",
"vary": "Accept-Encoding",
"x-ratelimit-limit": "700",
"x-ratelimit-remaining": "287",
"x-ratelimit-reset": "1481321304",
"server": "Plack::Handler::Starlet",
"etag": "W/\"4466cd809101f3b9c834437d95f317ba\"",
"access-control-allow-origin": "*",
"content-encoding": "gzip"
},
"url": "http://musicbrainz.org:80/ws/2/artist/65314b12-0e08-43fa-ba33-baaa7b874c15?inc=artist-rels%2Brecording-rels%2Brelease-rels&fmt=json",
"time": 3639,
"request": {
"method": "GET",
"headers": {
"User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org",
"accept-encoding": "gzip, deflate",
"accept": "application/json"
}
}
}

Binary file not shown.

View file

@ -0,0 +1,29 @@
{
"statusCode": 200,
"headers": {
"date": "Sat, 10 Dec 2016 02:24:17 GMT",
"content-type": "application/json; charset=utf-8",
"transfer-encoding": "chunked",
"connection": "keep-alive",
"keep-alive": "timeout=15",
"vary": "Accept-Encoding",
"x-ratelimit-limit": "700",
"x-ratelimit-remaining": "472",
"x-ratelimit-reset": "1481336658",
"server": "Plack::Handler::Starlet",
"etag": "W/\"b99b4284b3ed400d70ad6d104e56cbb2\"",
"access-control-allow-origin": "*",
"content-encoding": "gzip"
},
"url": "http://musicbrainz.org:80/ws/2/release-group?artist=5b11f4ce-a62d-471e-81fc-a69a8278c7da&type=ep&fmt=json",
"time": 463,
"request": {
"method": "GET",
"headers": {
"User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )",
"host": "musicbrainz.org",
"accept-encoding": "gzip, deflate",
"accept": "application/json"
}
}
}

11
test/helpers/client.js Normal file
View file

@ -0,0 +1,11 @@
import path from 'path'
import sepia from 'sepia'
import MusicBrainz from '../../src/api'
sepia.fixtureDir(path.join(__dirname, '..', 'fixtures'))
const options = /^(playback|cache)$/.test(process.env.VCR_MODE)
? { limit: Infinity, period: 0 }
: {}
export default new MusicBrainz(options)

7
test/helpers/context.js Normal file
View file

@ -0,0 +1,7 @@
import createLoaders from '../../src/loaders'
import client from './client'
export default {
client,
loaders: createLoaders(client)
}

View file

@ -1,25 +1,25 @@
import path from 'path'
import test from 'ava' import test from 'ava'
import sepia from 'sepia'
import { graphql } from 'graphql' import { graphql } from 'graphql'
import MusicBrainz from '../src/api'
import schema from '../src/schema' import schema from '../src/schema'
import createLoaders from '../src/loaders' import context from './helpers/context'
sepia.fixtureDir(path.join(__dirname, 'fixtures')) function testData (t, query, handler) {
return graphql(schema, query, null, context).then(result => {
t.is(result.errors, undefined)
return handler(t, result.data)
})
}
let client function testError (t, query, handler) {
let loaders return graphql(schema, query, null, context).then(result => {
let context t.truthy(result.errors)
t.true(result.errors.length > 0)
return handler(t, result.errors)
})
}
test.before(t => { test('schema has a node field', testData,
client = new MusicBrainz() `
loaders = createLoaders(client)
context = { client, loaders }
})
test('schema has a node field', t => {
const query = `
{ {
node(id: "UmVsZWFzZUdyb3VwOmUzN2QyNzQwLTQ1MDMtNGUzZi1hYjZkLWU2MjJhMjVlOTY0ZA==") { node(id: "UmVsZWFzZUdyb3VwOmUzN2QyNzQwLTQ1MDMtNGUzZi1hYjZkLWU2MjJhMjVlOTY0ZA==") {
__typename __typename
@ -28,21 +28,18 @@ test('schema has a node field', t => {
} }
} }
} }
` `, (t, data) => {
return graphql(schema, query, null, context).then(result => { t.deepEqual(data, {
t.deepEqual(result, { node: {
data: { __typename: 'ReleaseGroup',
node: { mbid: 'e37d2740-4503-4e3f-ab6d-e622a25e964d'
__typename: 'ReleaseGroup',
mbid: 'e37d2740-4503-4e3f-ab6d-e622a25e964d'
}
} }
}) })
}) }
}) )
test('schema has a lookup query', t => { test('schema has a lookup query', testData,
const query = ` `
{ {
lookup { lookup {
artist (mbid: "c8da2e40-bd28-4d4e-813a-bd2f51958ba8") { artist (mbid: "c8da2e40-bd28-4d4e-813a-bd2f51958ba8") {
@ -52,24 +49,20 @@ test('schema has a lookup query', t => {
} }
} }
} }
` `, (t, data) => {
return graphql(schema, query, null, context).then(result => { t.deepEqual(data, {
t.deepEqual(result, { lookup: {
data: { artist: {
lookup: { mbid: 'c8da2e40-bd28-4d4e-813a-bd2f51958ba8',
artist: { name: 'Lures',
mbid: 'c8da2e40-bd28-4d4e-813a-bd2f51958ba8', type: 'Group'
name: 'Lures',
type: 'Group'
}
} }
} }
}) })
}) })
})
test('schema has a search query', t => { test('schema has a search query', testData,
const query = ` `
{ {
search { search {
recordings (query: "Burn the Witch") { recordings (query: "Burn the Witch") {
@ -84,17 +77,15 @@ test('schema has a search query', t => {
} }
} }
} }
` `, (t, data) => {
return graphql(schema, query, null, context).then(result => { const { recordings } = data.search
const { recordings } = result.data.search
t.true(recordings.totalCount > 0) t.true(recordings.totalCount > 0)
t.true(recordings.edges.length === 25) t.true(recordings.edges.length === 25)
recordings.edges.forEach(edge => t.true(edge.score > 0)) recordings.edges.forEach(edge => t.true(edge.score > 0))
}) })
})
test('schema has a browse query', t => { test('schema has a browse query', testData,
const query = ` `
{ {
browse { browse {
releaseGroups (artist: "c8da2e40-bd28-4d4e-813a-bd2f51958ba8") { releaseGroups (artist: "c8da2e40-bd28-4d4e-813a-bd2f51958ba8") {
@ -115,17 +106,15 @@ test('schema has a browse query', t => {
} }
} }
} }
` `, (t, data) => {
return graphql(schema, query, null, context).then(result => { const { releaseGroups } = data.browse
const { releaseGroups } = result.data.browse
t.true(releaseGroups.totalCount > 0) t.true(releaseGroups.totalCount > 0)
t.true(releaseGroups.edges.length > 0) t.true(releaseGroups.edges.length > 0)
releaseGroups.edges.forEach(edge => t.truthy(edge.node.title)) releaseGroups.edges.forEach(edge => t.truthy(edge.node.title))
}) })
})
test('supports deeply nested queries', t => { test('supports deeply nested queries', testData,
const query = ` `
query AppleRecordsMarriages { query AppleRecordsMarriages {
search { search {
labels(query: "Apple Records", first: 1) { labels(query: "Apple Records", first: 1) {
@ -193,10 +182,284 @@ test('supports deeply nested queries', t => {
} }
} }
} }
` `, (t, data) => {
return graphql(schema, query, null, context).then(result => { const { labels } = data.search
const { labels } = result.data.search
t.true(labels.edges.length > 0) t.true(labels.edges.length > 0)
t.is(labels.edges[0].node.releases.edges.length, 1) t.is(labels.edges[0].node.releases.edges.length, 1)
}) })
})
test('throws an error if given a malformed MBID', testError,
`
{
lookup {
artist(mbid: "ABC123") {
name
}
}
}
`, (t, errors) => {
const err = errors[0]
t.true(err instanceof TypeError)
t.is(err.message, 'Malformed MBID: ABC123')
})
test('Artist beginArea/endArea pulls from begin_area/end_area for lookup queries', testData,
`
{
lookup {
artist(mbid: "65314b12-0e08-43fa-ba33-baaa7b874c15") {
beginArea {
name
}
endArea {
name
}
}
}
}
`, (t, data) => {
const { artist } = data.lookup
t.is(artist.beginArea.name, 'Westmount')
t.is(artist.endArea.name, 'Los Angeles')
})
test('Artist beginArea/endArea pull from begin_area/end_area for browse queries', testData,
`
{
browse {
artists(area: "3f504d54-c40c-487d-bc16-c1990eac887f") {
edges {
node {
beginArea {
name
}
endArea {
name
}
}
}
}
}
}
`, (t, data) => {
const artists = data.browse.artists.edges.map(edge => edge.node)
t.true(artists.length > 1)
t.true(artists.some(artist => artist.beginArea))
t.true(artists.some(artist => artist.endArea))
})
test('Artist beginArea/endArea pulls from begin-area/end-area for search queries', testData,
`
{
search {
artists(query: "Leonard Cohen", first: 1) {
edges {
node {
beginArea {
name
}
endArea {
name
}
}
}
}
}
}
`, (t, data) => {
const artists = data.search.artists.edges.map(edge => edge.node)
t.true(artists.length === 1)
t.is(artists[0].beginArea.name, 'Westmount')
t.is(artists[0].endArea.name, 'Los Angeles')
})
test('relationships filter by type', testData,
`
{
lookup {
artist(mbid: "65314b12-0e08-43fa-ba33-baaa7b874c15") {
relationships {
artists(first: 5) {
edges {
node {
target {
__typename
}
targetType
}
}
}
recordings(first: 5) {
edges {
node {
target {
__typename
}
targetType
}
}
}
releases(first: 5) {
edges {
node {
target {
__typename
}
targetType
}
}
}
}
}
}
}
`, (t, data) => {
const { relationships } = data.lookup.artist
t.is(relationships.artists.edges.length, 5)
relationships.artists.edges.forEach(edge => {
t.is(edge.node.targetType, 'artist')
t.is(edge.node.target.__typename, 'Artist')
})
t.is(relationships.recordings.edges.length, 5)
relationships.recordings.edges.forEach(edge => {
t.is(edge.node.targetType, 'recording')
t.is(edge.node.target.__typename, 'Recording')
})
t.is(relationships.releases.edges.length, 5)
relationships.releases.edges.forEach(edge => {
t.is(edge.node.targetType, 'release')
t.is(edge.node.target.__typename, 'Release')
})
})
test('Area maps iso-3166-1-codes to isoCodes', testData,
`
{
lookup {
area(mbid: "489ce91b-6658-3307-9877-795b68554c98") {
name
isoCodes
}
}
}
`, (t, data) => {
t.deepEqual(data.lookup.area.isoCodes, ['US'])
})
test('Alias locales use the Locale scalar', testData,
`
{
lookup {
artist(mbid: "f99b7d67-4e63-4678-aa66-4c6ac0f7d24a") {
aliases {
name
locale
}
}
}
}
`, (t, data) => {
const { aliases } = data.lookup.artist
t.is(aliases.find(alias => alias.locale === 'en').name, 'PSY')
t.is(aliases.find(alias => alias.locale === 'ko').name, '싸이')
})
test('Work ISWCs use the ISWC scalar', testData,
`
{
lookup {
work(mbid: "ef7d0814-da6a-32f5-a600-ff81cffd1aed") {
title
iswcs
}
}
}
`, (t, data) => {
const { work } = data.lookup
t.is(work.title, 'Song of the French Partisan')
t.deepEqual(work.iswcs, ['T-900.755.682-3'])
})
test('URLs may be looked up by resource', testData,
`
{
lookup {
url(resource: "http://www.nirvana.com/") {
mbid
resource
}
}
}
`, (t, data) => {
const { url } = data.lookup
t.is(url.mbid, '4347ffe2-82ec-4059-9520-6a1a3f73a304')
t.is(url.resource, 'http://www.nirvana.com/')
})
test('throws an error if given a malformed URLString', testError,
`
{
lookup {
url(resource: "http:foo") {
mbid
resource
}
}
}
`, (t, errors) => {
const err = errors[0]
t.true(err instanceof TypeError)
t.is(err.message, 'Malformed URL: http:foo')
})
test('Release groups can be browsed by type', testData,
`
{
browse {
releaseGroups(artist: "5b11f4ce-a62d-471e-81fc-a69a8278c7da", type: EP) {
edges {
node {
primaryType
}
}
}
}
}
`, (t, data) => {
const releaseGroups = data.browse.releaseGroups.edges.map(edge => edge.node)
t.is(releaseGroups.length, 8)
releaseGroups.forEach(releaseGroup => t.is(releaseGroup.primaryType, 'EP'))
})
test('Releases can be browsed by type and status', testData,
`
{
browse {
releases(artist: "5b11f4ce-a62d-471e-81fc-a69a8278c7da", type: EP, status: BOOTLEG) {
edges {
node {
status
}
}
}
}
}
`, (t, data) => {
const releases = data.browse.releases.edges.map(edge => edge.node)
t.is(releases.length, 6)
releases.forEach(release => t.is(release.status, 'BOOTLEG'))
})
test('Releases have an ASIN field', testData,
`
{
lookup {
release(mbid: "d5cdb7fd-c7e9-460a-9549-8a369655cc52") {
asin
}
}
}
`, (t, data) => {
const { release } = data.lookup
t.is(release.asin, 'B01KN6XDS6')
})

181
yarn.lock
View file

@ -32,8 +32,8 @@ ajv-keywords@^1.0.0:
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.2.0.tgz#676c4f087bfe1e8b12dca6fda2f3c74f417b099c" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.2.0.tgz#676c4f087bfe1e8b12dca6fda2f3c74f417b099c"
ajv@^4.7.0: ajv@^4.7.0:
version "4.9.1" version "4.9.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.9.1.tgz#08e1b0a5fddc8b844d28ca7b03510e78812ee3a0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.9.2.tgz#3f7dcda95b0c34bceb2d69945117d146219f1a2c"
dependencies: dependencies:
co "^4.6.0" co "^4.6.0"
json-stable-stringify "^1.0.1" json-stable-stringify "^1.0.1"
@ -322,27 +322,27 @@ babel-cli@^6.18.0:
optionalDependencies: optionalDependencies:
chokidar "^1.0.0" chokidar "^1.0.0"
babel-code-frame@^6.16.0: babel-code-frame@^6.16.0, babel-code-frame@^6.20.0:
version "6.16.0" version "6.20.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.16.0.tgz#f90e60da0862909d3ce098733b5d3987c97cb8de" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.20.0.tgz#b968f839090f9a8bc6d41938fb96cb84f7387b26"
dependencies: dependencies:
chalk "^1.1.0" chalk "^1.1.0"
esutils "^2.0.2" esutils "^2.0.2"
js-tokens "^2.0.0" js-tokens "^2.0.0"
babel-core@^6.17.0, babel-core@^6.18.0: babel-core@^6.17.0, babel-core@^6.18.0:
version "6.18.2" version "6.20.0"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.18.2.tgz#d8bb14dd6986fa4f3566a26ceda3964fa0e04e5b" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.20.0.tgz#ab0d7176d9dea434e66badadaf92237865eab1ec"
dependencies: dependencies:
babel-code-frame "^6.16.0" babel-code-frame "^6.20.0"
babel-generator "^6.18.0" babel-generator "^6.20.0"
babel-helpers "^6.16.0" babel-helpers "^6.16.0"
babel-messages "^6.8.0" babel-messages "^6.8.0"
babel-register "^6.18.0" babel-register "^6.18.0"
babel-runtime "^6.9.1" babel-runtime "^6.20.0"
babel-template "^6.16.0" babel-template "^6.16.0"
babel-traverse "^6.18.0" babel-traverse "^6.20.0"
babel-types "^6.18.0" babel-types "^6.20.0"
babylon "^6.11.0" babylon "^6.11.0"
convert-source-map "^1.1.0" convert-source-map "^1.1.0"
debug "^2.1.1" debug "^2.1.1"
@ -364,13 +364,13 @@ babel-eslint@^7.1.1:
babylon "^6.13.0" babylon "^6.13.0"
lodash.pickby "^4.6.0" lodash.pickby "^4.6.0"
babel-generator@^6.1.0, babel-generator@^6.18.0: babel-generator@^6.1.0, babel-generator@^6.18.0, babel-generator@^6.20.0:
version "6.19.0" version "6.20.0"
resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.19.0.tgz#9b2f244204777a3d6810ec127c673c87b349fac5" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.20.0.tgz#fee63614e0449390103b3097f3f6a118016c6766"
dependencies: dependencies:
babel-messages "^6.8.0" babel-messages "^6.8.0"
babel-runtime "^6.9.0" babel-runtime "^6.20.0"
babel-types "^6.19.0" babel-types "^6.20.0"
detect-indent "^4.0.0" detect-indent "^4.0.0"
jsesc "^1.3.0" jsesc "^1.3.0"
lodash "^4.2.0" lodash "^4.2.0"
@ -467,14 +467,14 @@ babel-helper-regex@^6.8.0:
lodash "^4.2.0" lodash "^4.2.0"
babel-helper-remap-async-to-generator@^6.16.0, babel-helper-remap-async-to-generator@^6.16.2: babel-helper-remap-async-to-generator@^6.16.0, babel-helper-remap-async-to-generator@^6.16.2:
version "6.18.0" version "6.20.3"
resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.18.0.tgz#336cdf3cab650bb191b02fc16a3708e7be7f9ce5" resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.20.3.tgz#9dd3b396f13e35ef63e538098500adc24c63c4e7"
dependencies: dependencies:
babel-helper-function-name "^6.18.0" babel-helper-function-name "^6.18.0"
babel-runtime "^6.0.0" babel-runtime "^6.20.0"
babel-template "^6.16.0" babel-template "^6.16.0"
babel-traverse "^6.18.0" babel-traverse "^6.20.0"
babel-types "^6.18.0" babel-types "^6.20.0"
babel-helper-replace-supers@^6.18.0, babel-helper-replace-supers@^6.8.0: babel-helper-replace-supers@^6.18.0, babel-helper-replace-supers@^6.8.0:
version "6.18.0" version "6.18.0"
@ -567,8 +567,8 @@ babel-plugin-syntax-object-rest-spread@^6.8.0:
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
babel-plugin-syntax-trailing-function-commas@^6.3.13: babel-plugin-syntax-trailing-function-commas@^6.3.13:
version "6.13.0" version "6.20.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.13.0.tgz#2b84b7d53dd744f94ff1fad7669406274b23f541" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.20.0.tgz#442835e19179f45b87e92d477d70b9f1f18b5c4f"
babel-plugin-transform-async-generator-functions@^6.17.0: babel-plugin-transform-async-generator-functions@^6.17.0:
version "6.17.0" version "6.17.0"
@ -619,13 +619,13 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.3.13:
babel-runtime "^6.0.0" babel-runtime "^6.0.0"
babel-plugin-transform-es2015-block-scoping@^6.18.0: babel-plugin-transform-es2015-block-scoping@^6.18.0:
version "6.18.0" version "6.20.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.18.0.tgz#3bfdcfec318d46df22525cdea88f1978813653af" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.20.0.tgz#5d8f3e83b1a1ae1064e64a9e5bb83108d8e73be3"
dependencies: dependencies:
babel-runtime "^6.9.0" babel-runtime "^6.20.0"
babel-template "^6.15.0" babel-template "^6.15.0"
babel-traverse "^6.18.0" babel-traverse "^6.20.0"
babel-types "^6.18.0" babel-types "^6.20.0"
lodash "^4.2.0" lodash "^4.2.0"
babel-plugin-transform-es2015-classes@^6.18.0: babel-plugin-transform-es2015-classes@^6.18.0:
@ -784,19 +784,17 @@ babel-plugin-transform-exponentiation-operator@^6.3.13:
babel-runtime "^6.0.0" babel-runtime "^6.0.0"
babel-plugin-transform-object-rest-spread@^6.16.0: babel-plugin-transform-object-rest-spread@^6.16.0:
version "6.19.0" version "6.20.2"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.19.0.tgz#f6ac428ee3cb4c6aa00943ed1422ce813603b34c" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.20.2.tgz#e816c55bba77b14c16365d87e2ae48c8fd18fc2e"
dependencies: dependencies:
babel-plugin-syntax-object-rest-spread "^6.8.0" babel-plugin-syntax-object-rest-spread "^6.8.0"
babel-runtime "^6.0.0" babel-runtime "^6.20.0"
babel-plugin-transform-regenerator@^6.16.0: babel-plugin-transform-regenerator@^6.16.0:
version "6.16.1" version "6.20.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.16.1.tgz#a75de6b048a14154aae14b0122756c5bed392f59" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.20.0.tgz#a546cd2aa1c9889929d5c427a31303847847ab75"
dependencies: dependencies:
babel-runtime "^6.9.0" regenerator-transform "0.9.8"
babel-types "^6.16.0"
private "~0.1.5"
babel-plugin-transform-runtime@^6.15.0: babel-plugin-transform-runtime@^6.15.0:
version "6.15.0" version "6.15.0"
@ -812,12 +810,12 @@ babel-plugin-transform-strict-mode@^6.18.0:
babel-types "^6.18.0" babel-types "^6.18.0"
babel-polyfill@^6.16.0: babel-polyfill@^6.16.0:
version "6.16.0" version "6.20.0"
resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.16.0.tgz#2d45021df87e26a374b6d4d1a9c65964d17f2422" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.20.0.tgz#de4a371006139e20990aac0be367d398331204e7"
dependencies: dependencies:
babel-runtime "^6.9.1" babel-runtime "^6.20.0"
core-js "^2.4.0" core-js "^2.4.0"
regenerator-runtime "^0.9.5" regenerator-runtime "^0.10.0"
babel-preset-es2015-node4@^2.1.0: babel-preset-es2015-node4@^2.1.0:
version "2.1.0" version "2.1.0"
@ -892,12 +890,12 @@ babel-register@^6.18.0:
mkdirp "^0.5.1" mkdirp "^0.5.1"
source-map-support "^0.4.2" source-map-support "^0.4.2"
babel-runtime@^6.0.0, babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.9.0, babel-runtime@^6.9.1: babel-runtime@^6.0.0, babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.20.0, babel-runtime@^6.9.0, babel-runtime@^6.9.1:
version "6.18.0" version "6.20.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.18.0.tgz#0f4177ffd98492ef13b9f823e9994a02584c9078" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.20.0.tgz#87300bdcf4cd770f09bf0048c64204e17806d16f"
dependencies: dependencies:
core-js "^2.4.0" core-js "^2.4.0"
regenerator-runtime "^0.9.5" regenerator-runtime "^0.10.0"
babel-template@^6.14.0, babel-template@^6.15.0, babel-template@^6.16.0, babel-template@^6.7.0, babel-template@^6.8.0: babel-template@^6.14.0, babel-template@^6.15.0, babel-template@^6.16.0, babel-template@^6.7.0, babel-template@^6.8.0:
version "6.16.0" version "6.16.0"
@ -909,25 +907,25 @@ babel-template@^6.14.0, babel-template@^6.15.0, babel-template@^6.16.0, babel-te
babylon "^6.11.0" babylon "^6.11.0"
lodash "^4.2.0" lodash "^4.2.0"
babel-traverse@^6.15.0, babel-traverse@^6.16.0, babel-traverse@^6.18.0: babel-traverse@^6.15.0, babel-traverse@^6.16.0, babel-traverse@^6.18.0, babel-traverse@^6.20.0:
version "6.19.0" version "6.20.0"
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.19.0.tgz#68363fb821e26247d52a519a84b2ceab8df4f55a" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.20.0.tgz#5378d1a743e3d856e6a52289994100bbdfd9872a"
dependencies: dependencies:
babel-code-frame "^6.16.0" babel-code-frame "^6.20.0"
babel-messages "^6.8.0" babel-messages "^6.8.0"
babel-runtime "^6.9.0" babel-runtime "^6.20.0"
babel-types "^6.19.0" babel-types "^6.20.0"
babylon "^6.11.0" babylon "^6.11.0"
debug "^2.2.0" debug "^2.2.0"
globals "^9.0.0" globals "^9.0.0"
invariant "^2.2.0" invariant "^2.2.0"
lodash "^4.2.0" lodash "^4.2.0"
babel-types@^6.13.0, babel-types@^6.15.0, babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.7.2, babel-types@^6.8.0, babel-types@^6.9.0: babel-types@^6.13.0, babel-types@^6.15.0, babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.20.0, babel-types@^6.7.2, babel-types@^6.8.0, babel-types@^6.9.0:
version "6.19.0" version "6.20.0"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.19.0.tgz#8db2972dbed01f1192a8b602ba1e1e4c516240b9" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.20.0.tgz#3869ecb98459533b37df809886b3f7f3b08d2baa"
dependencies: dependencies:
babel-runtime "^6.9.1" babel-runtime "^6.20.0"
esutils "^2.0.2" esutils "^2.0.2"
lodash "^4.2.0" lodash "^4.2.0"
to-fast-properties "^1.0.1" to-fast-properties "^1.0.1"
@ -1359,20 +1357,6 @@ cross-env@^3.1.3:
dependencies: dependencies:
cross-spawn "^3.0.1" cross-spawn "^3.0.1"
cross-spawn-async@^2.0.0:
version "2.2.5"
resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc"
dependencies:
lru-cache "^4.0.0"
which "^1.2.8"
cross-spawn@2.0.x:
version "2.0.1"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-2.0.1.tgz#ab6fd893a099759d9b85220e3a64397de946b0f6"
dependencies:
cross-spawn-async "^2.0.0"
spawn-sync "1.0.13"
cross-spawn@^3.0.1: cross-spawn@^3.0.1:
version "3.0.1" version "3.0.1"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
@ -1387,6 +1371,14 @@ cross-spawn@^4, cross-spawn@^4.0.0:
lru-cache "^4.0.1" lru-cache "^4.0.1"
which "^1.2.9" which "^1.2.9"
cross-spawn@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.0.1.tgz#a3bbb302db2297cbea3c04edf36941f4613aa399"
dependencies:
lru-cache "^4.0.1"
shebang-command "^1.2.0"
which "^1.2.9"
cryptiles@2.x.x: cryptiles@2.x.x:
version "2.0.5" version "2.0.5"
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
@ -1955,7 +1947,7 @@ finalhandler@0.5.0:
find-cache-dir@^0.1.1: find-cache-dir@^0.1.1:
version "0.1.1" version "0.1.1"
resolved "http://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9"
dependencies: dependencies:
commondir "^1.0.1" commondir "^1.0.1"
mkdirp "^0.5.1" mkdirp "^0.5.1"
@ -2762,8 +2754,8 @@ jsx-ast-utils@^1.3.3:
object-assign "^4.1.0" object-assign "^4.1.0"
kind-of@^3.0.2: kind-of@^3.0.2:
version "3.0.4" version "3.1.0"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.0.4.tgz#7b8ecf18a4e17f8269d73b501c9f232c96887a74" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47"
dependencies: dependencies:
is-buffer "^1.0.2" is-buffer "^1.0.2"
@ -2956,7 +2948,7 @@ lowercase-keys@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306"
lru-cache@^4.0.0, lru-cache@^4.0.1: lru-cache@^4.0.1:
version "4.0.2" version "4.0.2"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e"
dependencies: dependencies:
@ -3570,10 +3562,11 @@ power-assert-util-string-width@^1.1.1:
eastasianwidth "^0.1.1" eastasianwidth "^0.1.1"
pre-commit@^1.1.3: pre-commit@^1.1.3:
version "1.1.3" version "1.2.0"
resolved "https://registry.yarnpkg.com/pre-commit/-/pre-commit-1.1.3.tgz#6d5ed90740472072958c711a15f676aa2c231377" resolved "https://registry.yarnpkg.com/pre-commit/-/pre-commit-1.2.0.tgz#16a1a218861c778d1a1498719c9763717913d5b8"
dependencies: dependencies:
cross-spawn "2.0.x" cross-spawn "^5.0.1"
spawn-sync "^1.0.15"
which "1.2.x" which "1.2.x"
prelude-ls@~1.1.2: prelude-ls@~1.1.2:
@ -3602,7 +3595,7 @@ pretty-ms@^2.0.0:
parse-ms "^1.0.0" parse-ms "^1.0.0"
plur "^1.0.0" plur "^1.0.0"
private@^0.1.6, private@~0.1.5: private@^0.1.6:
version "0.1.6" version "0.1.6"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.6.tgz#55c6a976d0f9bafb9924851350fe47b9b5fbb7c1" resolved "https://registry.yarnpkg.com/private/-/private-0.1.6.tgz#55c6a976d0f9bafb9924851350fe47b9b5fbb7c1"
@ -3771,13 +3764,21 @@ regenerate@^1.2.1:
version "1.3.2" version "1.3.2"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
regenerator-runtime@^0.9.5: regenerator-runtime@^0.10.0:
version "0.9.6" version "0.10.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz#d33eb95d0d2001a4be39659707c51b0cb71ce029" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.1.tgz#257f41961ce44558b18f7814af48c17559f9faeb"
regenerator-transform@0.9.8:
version "0.9.8"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.8.tgz#0f88bb2bc03932ddb7b6b7312e68078f01026d6c"
dependencies:
babel-runtime "^6.18.0"
babel-types "^6.19.0"
private "^0.1.6"
regex-cache@^0.4.2: regex-cache@^0.4.2:
version "0.4.3" version "0.4.3"
resolved "http://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145"
dependencies: dependencies:
is-equal-shallow "^0.1.3" is-equal-shallow "^0.1.3"
is-primitive "^2.0.0" is-primitive "^2.0.0"
@ -4049,6 +4050,16 @@ setprototypeof@1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08"
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
dependencies:
shebang-regex "^1.0.0"
shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
shelljs@^0.7.5: shelljs@^0.7.5:
version "0.7.5" version "0.7.5"
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.5.tgz#2eef7a50a21e1ccf37da00df767ec69e30ad0675" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.5.tgz#2eef7a50a21e1ccf37da00df767ec69e30ad0675"
@ -4121,9 +4132,9 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@~0.5.1:
version "0.5.6" version "0.5.6"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
spawn-sync@1.0.13: spawn-sync@^1.0.15:
version "1.0.13" version "1.0.15"
resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.13.tgz#904091b9ad48a0f3afb0e84752154c01e82fd8d8" resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476"
dependencies: dependencies:
concat-stream "^1.4.7" concat-stream "^1.4.7"
os-shim "^0.1.2" os-shim "^0.1.2"
@ -4692,7 +4703,7 @@ which-module@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
which@1.2.x, which@^1.2.4, which@^1.2.8, which@^1.2.9: which@1.2.x, which@^1.2.4, which@^1.2.9:
version "1.2.12" version "1.2.12"
resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192" resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192"
dependencies: dependencies: