Internal renames, update dependencies, add Travis config

This commit is contained in:
Brian Beck 2016-12-02 00:21:10 -08:00
parent 3dbbf54161
commit 6cb41e1ce0
15 changed files with 240 additions and 217 deletions

16
.travis.yml Normal file
View file

@ -0,0 +1,16 @@
language: node_js
node_js:
- "4"
- "5"
- "6"
# Use container-based Travis infrastructure.
sudo: false
branches:
only:
- master
script:
- yarn run check

View file

@ -1,6 +1,6 @@
import { GraphQLObjectType } from 'graphql'
import { forwardConnectionArgs } from 'graphql-relay'
import { browseResolver } from '../resolvers'
import { resolveBrowse } from '../resolvers'
import {
MBID,
URLString,
@ -42,7 +42,7 @@ const releaseGroup = {
description: 'The MBID of a release group to which the entity is linked.'
}
function browseQuery (connectionType, args) {
function createBrowseField (connectionType, args) {
const typeName = toWords(connectionType.name.slice(0, -10))
return {
type: connectionType,
@ -51,7 +51,7 @@ function browseQuery (connectionType, args) {
...forwardConnectionArgs,
...args
},
resolve: browseResolver()
resolve: resolveBrowse
}
}
@ -60,10 +60,10 @@ export const BrowseQuery = new GraphQLObjectType({
description: `A query for all MusicBrainz entities directly linked to another
entity.`,
fields: {
areas: browseQuery(AreaConnection, {
areas: createBrowseField(AreaConnection, {
collection
}),
artists: browseQuery(ArtistConnection, {
artists: createBrowseField(ArtistConnection, {
area,
collection,
recording,
@ -74,7 +74,7 @@ entity.`,
description: 'The MBID of a work to which the artist is linked.'
}
}),
events: browseQuery(EventConnection, {
events: createBrowseField(EventConnection, {
area,
artist,
collection,
@ -83,21 +83,21 @@ entity.`,
description: 'The MBID of a place to which the event is linked.'
}
}),
labels: browseQuery(LabelConnection, {
labels: createBrowseField(LabelConnection, {
area,
collection,
release
}),
places: browseQuery(PlaceConnection, {
places: createBrowseField(PlaceConnection, {
area,
collection
}),
recordings: browseQuery(RecordingConnection, {
recordings: createBrowseField(RecordingConnection, {
artist,
collection,
release
}),
releases: browseQuery(ReleaseConnection, {
releases: createBrowseField(ReleaseConnection, {
area,
artist,
collection,
@ -117,16 +117,16 @@ release, but is not included in the credits for the release itself.`
recording,
releaseGroup
}),
releaseGroups: browseQuery(ReleaseGroupConnection, {
releaseGroups: createBrowseField(ReleaseGroupConnection, {
artist,
collection,
release
}),
works: browseQuery(WorkConnection, {
works: createBrowseField(WorkConnection, {
artist,
collection
}),
urls: browseQuery(URLConnection, {
urls: createBrowseField(URLConnection, {
resource: {
type: URLString,
description: 'The web address for which to browse URL entities.'
@ -135,7 +135,7 @@ release, but is not included in the credits for the release itself.`
}
})
export const browseField = {
export const browse = {
type: BrowseQuery,
description: 'Browse all MusicBrainz entities directly linked to another entity.',
// We only have work to do once we know what entity types are being requested,

View file

@ -1,3 +1,3 @@
export { LookupQuery, lookupField } from './lookup'
export { BrowseQuery, browseField } from './browse'
export { SearchQuery, searchField } from './search'
export { LookupQuery, lookup } from './lookup'
export { BrowseQuery, browse } from './browse'
export { SearchQuery, search } from './search'

View file

@ -1,5 +1,5 @@
import { GraphQLObjectType } from 'graphql'
import { lookupResolver } from '../resolvers'
import { resolveLookup } from '../resolvers'
import { mbid, toWords } from '../types/helpers'
import {
Area,
@ -16,13 +16,13 @@ import {
Work
} from '../types'
function lookupQuery (entity) {
function createLookupField (entity) {
const typeName = toWords(entity.name)
return {
type: entity,
description: `Look up a specific ${typeName} by its MBID.`,
args: { mbid },
resolve: lookupResolver()
resolve: resolveLookup
}
}
@ -30,22 +30,22 @@ export const LookupQuery = new GraphQLObjectType({
name: 'LookupQuery',
description: 'A lookup of an individual MusicBrainz entity by its MBID.',
fields: {
area: lookupQuery(Area),
artist: lookupQuery(Artist),
event: lookupQuery(Event),
instrument: lookupQuery(Instrument),
label: lookupQuery(Label),
place: lookupQuery(Place),
recording: lookupQuery(Recording),
release: lookupQuery(Release),
releaseGroup: lookupQuery(ReleaseGroup),
series: lookupQuery(Series),
url: lookupQuery(URL),
work: lookupQuery(Work)
area: createLookupField(Area),
artist: createLookupField(Artist),
event: createLookupField(Event),
instrument: createLookupField(Instrument),
label: createLookupField(Label),
place: createLookupField(Place),
recording: createLookupField(Recording),
release: createLookupField(Release),
releaseGroup: createLookupField(ReleaseGroup),
series: createLookupField(Series),
url: createLookupField(URL),
work: createLookupField(Work)
}
})
export const lookupField = {
export const lookup = {
type: LookupQuery,
description: 'Perform a lookup of a MusicBrainz entity by its MBID.',
// We only have work to do once we know what entity types are being requested,

View file

@ -1,6 +1,6 @@
import { GraphQLObjectType, GraphQLNonNull, GraphQLString } from 'graphql'
import { forwardConnectionArgs } from 'graphql-relay'
import { searchResolver } from '../resolvers'
import { resolveSearch } from '../resolvers'
import {
AreaConnection,
ArtistConnection,
@ -16,7 +16,7 @@ import {
} from '../types'
import { toWords } from '../types/helpers'
function searchQuery (connectionType) {
function createSearchField (connectionType) {
const typeName = toWords(connectionType.name.slice(0, -10))
return {
type: connectionType,
@ -29,7 +29,7 @@ and search fields](https://musicbrainz.org/doc/Development/XML_Web_Service/Versi
},
...forwardConnectionArgs
},
resolve: searchResolver()
resolve: resolveSearch
}
}
@ -37,21 +37,21 @@ export const SearchQuery = new GraphQLObjectType({
name: 'SearchQuery',
description: 'A search for MusicBrainz entities using Lucene query syntax.',
fields: {
areas: searchQuery(AreaConnection),
artists: searchQuery(ArtistConnection),
events: searchQuery(EventConnection),
instruments: searchQuery(InstrumentConnection),
labels: searchQuery(LabelConnection),
places: searchQuery(PlaceConnection),
recordings: searchQuery(RecordingConnection),
releases: searchQuery(ReleaseConnection),
releaseGroups: searchQuery(ReleaseGroupConnection),
series: searchQuery(SeriesConnection),
works: searchQuery(WorkConnection)
areas: createSearchField(AreaConnection),
artists: createSearchField(ArtistConnection),
events: createSearchField(EventConnection),
instruments: createSearchField(InstrumentConnection),
labels: createSearchField(LabelConnection),
places: createSearchField(PlaceConnection),
recordings: createSearchField(RecordingConnection),
releases: createSearchField(ReleaseConnection),
releaseGroups: createSearchField(ReleaseGroupConnection),
series: createSearchField(SeriesConnection),
works: createSearchField(WorkConnection)
}
})
export const searchField = {
export const search = {
type: SearchQuery,
description: 'Search for MusicBrainz entities using Lucene query syntax.',
// We only have work to do once we know what entity types are being requested,

View file

@ -63,111 +63,110 @@ export function includeSubqueries (params, info, fragments = info.fragments) {
return params
}
export function lookupResolver () {
return (root, { mbid }, { loaders }, info) => {
const entityType = toDashed(info.fieldName)
let params = includeSubqueries({}, info)
params = includeRelationships(params, info)
return loaders.lookup.load([entityType, mbid, params])
}
export function resolveLookup (root, { mbid }, { loaders }, info) {
const entityType = toDashed(info.fieldName)
let params = includeSubqueries({}, info)
params = includeRelationships(params, info)
return loaders.lookup.load([entityType, mbid, params])
}
export function browseResolver () {
return (source, { first = 25, after, type = [], status = [], ...args }, { loaders }, info) => {
const pluralName = toDashed(info.fieldName)
const singularName = toSingular(pluralName)
let params = {
...args,
type,
status,
limit: first,
offset: getOffsetWithDefault(after, -1) + 1
}
params = includeSubqueries(params, info)
params = includeRelationships(params, info, info.fragments)
const formatValue = value => value.toLowerCase().replace(/ /g, '')
params.type = params.type.map(formatValue)
params.status = params.status.map(formatValue)
return loaders.browse.load([singularName, params]).then(list => {
// Grab the list, offet, and count from the response and use them to build
// a Relay connection object.
const {
[pluralName]: arraySlice,
[`${singularName}-offset`]: sliceStart,
[`${singularName}-count`]: arrayLength
} = list
const meta = { sliceStart, arrayLength }
return {
totalCount: arrayLength,
...connectionFromArraySlice(arraySlice, { first, after }, meta)
}
})
export function resolveBrowse (root, {
first,
after,
type = [],
status = [],
...args
}, { loaders }, info) {
const pluralName = toDashed(info.fieldName)
const singularName = toSingular(pluralName)
let params = {
...args,
type,
status,
limit: first,
offset: getOffsetWithDefault(after, -1) + 1 || undefined
}
}
export function searchResolver () {
return (source, { first = 25, after, query, ...args }, { loaders }, info) => {
const pluralName = toDashed(info.fieldName)
const singularName = toSingular(pluralName)
let params = {
...args,
limit: first,
offset: getOffsetWithDefault(after, -1) + 1
}
params = includeSubqueries(params, info)
return loaders.search.load([singularName, query, params]).then(list => {
const {
[pluralName]: arraySlice,
offset: sliceStart,
count: arrayLength
} = list
const meta = { sliceStart, arrayLength }
const connection = {
totalCount: arrayLength,
...connectionFromArraySlice(arraySlice, { first, after }, meta)
}
// Move the `score` field up to the edge object and make sure it's a
// number (MusicBrainz returns a string).
connection.edges.forEach(edge => {
edge.score = parseInt(edge.node.score, 10)
})
return connection
})
}
}
export function relationshipResolver () {
return (source, args, context, info) => {
const targetType = toDashed(toSingular(info.fieldName)).replace('-', '_')
// There's no way to filter these at the API level, so do it here.
const relationships = source.filter(rel => {
if (rel['target-type'] !== targetType) {
return false
}
if (args.direction != null && rel.direction !== args.direction) {
return false
}
if (args.type != null && rel.type !== args.type) {
return false
}
if (args.typeID != null && rel['type-id'] !== args.typeID) {
return false
}
return true
})
params = includeSubqueries(params, info)
params = includeRelationships(params, info, info.fragments)
const formatParam = value => value.toLowerCase().replace(/ /g, '')
params.type = params.type.map(formatParam)
params.status = params.status.map(formatParam)
return loaders.browse.load([singularName, params]).then(list => {
// Grab the list, offet, and count from the response and use them to build
// a Relay connection object.
const {
[pluralName]: arraySlice,
[`${singularName}-offset`]: sliceStart,
[`${singularName}-count`]: arrayLength
} = list
const meta = { sliceStart, arrayLength }
return {
totalCount: relationships.length,
...connectionFromArray(relationships, args)
totalCount: arrayLength,
...connectionFromArraySlice(arraySlice, { first, after }, meta)
}
})
}
export function resolveSearch (root, {
after,
first,
query,
...args
}, { loaders }, info) {
const pluralName = toDashed(info.fieldName)
const singularName = toSingular(pluralName)
let params = {
...args,
limit: first,
offset: getOffsetWithDefault(after, -1) + 1 || undefined
}
params = includeSubqueries(params, info)
return loaders.search.load([singularName, query, params]).then(list => {
const {
[pluralName]: arraySlice,
offset: sliceStart,
count: arrayLength
} = list
const meta = { sliceStart, arrayLength }
const connection = {
totalCount: arrayLength,
...connectionFromArraySlice(arraySlice, { first, after }, meta)
}
// Move the `score` field up to the edge object and make sure it's a
// number (MusicBrainz returns a string).
connection.edges.forEach(edge => { edge.score = +edge.node.score })
return connection
})
}
export function resolveRelationship (rels, args, context, info) {
const targetType = toDashed(toSingular(info.fieldName)).replace('-', '_')
// There's no way to filter these at the API level, so do it here.
const matches = rels.filter(rel => {
if (rel['target-type'] !== targetType) {
return false
}
if (args.direction != null && rel.direction !== args.direction) {
return false
}
if (args.type != null && rel.type !== args.type) {
return false
}
if (args.typeID != null && rel['type-id'] !== args.typeID) {
return false
}
return true
})
return {
totalCount: matches.length,
...connectionFromArray(matches, args)
}
}
export function linkedResolver () {
return (source, args, context, info) => {
const parentEntity = toDashed(info.parentType.name)
args = { ...args, [parentEntity]: source.id }
return browseResolver()(source, args, context, info)
}
export function resolveLinked (entity, args, context, info) {
const parentEntity = toDashed(info.parentType.name)
args = { ...args, [parentEntity]: entity.id }
return resolveBrowse(entity, args, context, info)
}
/**
@ -175,17 +174,17 @@ export function linkedResolver () {
* for a particular field that's being requested, make another request to grab
* it (after making sure it isn't already available).
*/
export function subqueryResolver (includeValue, handler = value => value) {
return (source, args, { loaders }, info) => {
export function createSubqueryResolver (includeValue, handler = value => value) {
return (entity, args, { loaders }, info) => {
const key = toDashed(info.fieldName)
if (key in source || (source._inc && source._inc.indexOf(key) !== -1)) {
return handler(source[key], args)
let promise
if (key in entity || (entity._inc && entity._inc.indexOf(key) >= 0)) {
promise = Promise.resolve(entity)
} else {
const { _type: entityType, id } = source
const { _type: entityType, id } = entity
const params = { inc: [includeValue || key] }
return loaders.lookup.load([entityType, id, params]).then(entity => {
return handler(entity[key], args)
})
promise = loaders.lookup.load([entityType, id, params])
}
return promise.then(entity => handler(entity[key], args))
}
}

View file

@ -1,5 +1,5 @@
import { GraphQLSchema, GraphQLObjectType } from 'graphql'
import { lookupField, browseField, searchField } from './queries'
import { lookup, browse, search } from './queries'
import { nodeField } from './types/node'
export default new GraphQLSchema({
@ -8,10 +8,10 @@ export default new GraphQLSchema({
description: `The query root, from which multiple types of MusicBrainz
requests can be made.`,
fields: () => ({
node: nodeField,
lookup: lookupField,
browse: browseField,
search: searchField
lookup,
browse,
search,
node: nodeField
})
})
})

View file

@ -3,7 +3,7 @@ import Node from './node'
import Entity from './entity'
import Area from './area'
import {
getFallback,
resolveWithFallback,
fieldWithID,
id,
mbid,
@ -50,13 +50,13 @@ is often, but not always, its birth/formation country.`
type: Area,
description: `The area in which an artist began their career (or where
were born, if the artist is a person).`,
resolve: getFallback(['begin-area', 'begin_area'])
resolve: resolveWithFallback(['begin-area', 'begin_area'])
},
endArea: {
type: Area,
description: `The area in which an artist ended their career (or where
they died, if the artist is a person).`,
resolve: getFallback(['end-area', 'end_area'])
resolve: resolveWithFallback(['end-area', 'end_area'])
},
lifeSpan,
...fieldWithID('gender', {

View file

@ -1,7 +1,7 @@
import { GraphQLInterfaceType } from 'graphql'
import { mbid } from './helpers'
import { mbid, connectionWithExtras } from './helpers'
export default new GraphQLInterfaceType({
const Entity = new GraphQLInterfaceType({
name: 'Entity',
description: 'An entity in the MusicBrainz schema.',
resolveType (value) {
@ -11,3 +11,6 @@ export default new GraphQLInterfaceType({
},
fields: () => ({ mbid })
})
export const EntityConnection = connectionWithExtras(Entity)
export default Entity

View file

@ -30,9 +30,9 @@ import { ReleaseGroupConnection } from './release-group'
import { TagConnection } from './tag'
import { WorkConnection } from './work'
import {
linkedResolver,
relationshipResolver,
subqueryResolver,
resolveLinked,
resolveRelationship,
createSubqueryResolver,
includeRelationships
} from '../resolvers'
@ -58,7 +58,7 @@ export function toWords (name) {
export function fieldWithID (name, config = {}) {
config = {
type: GraphQLString,
resolve: getHyphenated,
resolve: resolveHyphenated,
...config
}
const isPlural = config.type instanceof GraphQLList
@ -69,7 +69,7 @@ export function fieldWithID (name, config = {}) {
type: isPlural ? new GraphQLList(MBID) : MBID,
description: `The MBID${s} associated with the value${s} of the \`${name}\`
field.`,
resolve: getHyphenated
resolve: resolveHyphenated
}
return {
[name]: config,
@ -77,17 +77,17 @@ field.`,
}
}
export function getHyphenated (source, args, context, info) {
export function resolveHyphenated (obj, args, context, info) {
const name = dashify(info.fieldName)
return source[name]
return obj[name]
}
export function getFallback (keys) {
return (source) => {
export function resolveWithFallback (keys) {
return (obj) => {
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
if (key in source) {
return source[key]
if (key in obj) {
return obj[key]
}
}
}
@ -97,7 +97,7 @@ export const id = globalIdField()
export const mbid = {
type: new GraphQLNonNull(MBID),
description: 'The MBID of the entity.',
resolve: source => source.id
resolve: entity => entity.id
}
export const name = {
type: GraphQLString,
@ -108,7 +108,7 @@ export const sortName = {
description: `The string to use for the purpose of ordering by name (for
example, by moving articles like the to the end or a persons last name to
the front).`,
resolve: getHyphenated
resolve: resolveHyphenated
}
export const title = {
type: GraphQLString,
@ -122,7 +122,7 @@ export const lifeSpan = {
type: LifeSpan,
description: `The begin and end dates of the entitys existence. Its exact
meaning depends on the type of entity.`,
resolve: getHyphenated
resolve: resolveHyphenated
}
function linkedQuery (connectionType, { args, ...config } = {}) {
@ -134,7 +134,7 @@ function linkedQuery (connectionType, { args, ...config } = {}) {
...forwardConnectionArgs,
...args
},
resolve: linkedResolver(),
resolve: resolveLinked,
...config
}
}
@ -152,7 +152,7 @@ export const relationship = {
description: 'Filter by the relationship type.'
})
},
resolve: relationshipResolver()
resolve: resolveRelationship
}
export const relationships = {
@ -175,16 +175,17 @@ export const relationships = {
})
}),
description: 'Relationships between this entity and other entitites.',
resolve: (source, args, { loaders }, info) => {
if (source.relations != null) {
return source.relations
resolve: (entity, args, { loaders }, info) => {
let promise
if (entity.relations != null) {
promise = Promise.resolve(entity)
} else {
const entityType = toDashed(info.parentType.name)
const id = entity.id
const params = includeRelationships({}, info)
promise = loaders.lookup.load([entityType, id, params])
}
const entityType = toDashed(info.parentType.name)
const id = source.id
const params = includeRelationships({}, info)
return loaders.lookup.load([entityType, id, params]).then(entity => {
return entity.relations
})
return promise.then(entity => entity.relations)
}
}
@ -192,13 +193,13 @@ export const aliases = {
type: new GraphQLList(Alias),
description: `[Aliases](https://musicbrainz.org/doc/Aliases) are used to store
alternate names or misspellings.`,
resolve: subqueryResolver()
resolve: createSubqueryResolver()
}
export const artistCredit = {
type: new GraphQLList(ArtistCredit),
description: 'The main credited artist(s).',
resolve: subqueryResolver()
resolve: createSubqueryResolver()
}
export const artists = linkedQuery(ArtistConnection)
@ -227,7 +228,7 @@ export const releaseGroups = linkedQuery(ReleaseGroupConnection, {
}
})
export const tags = linkedQuery(TagConnection, {
resolve: subqueryResolver('tags', (value = [], args) => ({
resolve: createSubqueryResolver('tags', (value = [], args) => ({
totalCount: value.length,
...connectionFromArray(value, args)
}))

View file

@ -1,7 +1,7 @@
export { MBID, DateType, IPI, URLString } from './scalars'
export { ReleaseGroupType, ReleaseStatus } from './enums'
export { default as Node } from './node'
export { default as Entity } from './entity'
export { default as Entity, EntityConnection } from './entity'
export { default as Area, AreaConnection } from './area'
export { default as Artist, ArtistConnection } from './artist'
export { default as Event, EventConnection } from './event'

View file

@ -8,7 +8,7 @@ import {
import { DateType } from './scalars'
import Entity from './entity'
import {
getHyphenated,
resolveHyphenated,
fieldWithID,
connectionWithExtras
} from './helpers'
@ -36,19 +36,19 @@ other and to URLs outside MusicBrainz.`,
targetType: {
type: new GraphQLNonNull(GraphQLString),
description: 'The type of entity on the receiving end of the relationship.',
resolve: getHyphenated
resolve: resolveHyphenated
},
sourceCredit: {
type: GraphQLString,
description: `How the source entity was actually credited, if different
from its main (performance) name.`,
resolve: getHyphenated
resolve: resolveHyphenated
},
targetCredit: {
type: GraphQLString,
description: `How the target entity was actually credited, if different
from its main (performance) name.`,
resolve: getHyphenated
resolve: resolveHyphenated
},
begin: {
type: DateType,

View file

@ -15,7 +15,7 @@ import {
relationships,
tags,
fieldWithID,
getHyphenated,
resolveHyphenated,
connectionWithExtras
} from './helpers'
@ -40,7 +40,7 @@ album it doesnt matter how many CDs or editions/versions it had.`,
firstReleaseDate: {
type: DateType,
description: 'The date of the earliest release in the group.',
resolve: getHyphenated
resolve: resolveHyphenated
},
...fieldWithID('primaryType', {
type: ReleaseGroupType,

View file

@ -18,7 +18,7 @@ import {
relationships,
tags,
fieldWithID,
getHyphenated,
resolveHyphenated,
connectionWithExtras
} from './helpers'
@ -40,7 +40,7 @@ MusicBrainz as one release.`,
releaseEvents: {
type: new GraphQLList(ReleaseEvent),
description: 'The release events for this release.',
resolve: getHyphenated
resolve: resolveHyphenated
},
date: {
type: DateType,

View file

@ -1733,7 +1733,7 @@ has-color@^0.1.7:
has-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
resolved "http://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
has-unicode@^2.0.0:
version "2.0.1"
@ -1968,7 +1968,7 @@ is-path-inside@^1.0.0:
is-posix-bracket@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
resolved "http://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
is-primitive@^2.0.0:
version "2.0.0"
@ -2066,8 +2066,8 @@ json3@3.3.2:
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
json5@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.0.tgz#9b20715b026cbe3778fd769edccd822d8332a5b2"
version "0.5.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
jsonify@~0.0.0:
version "0.0.0"
@ -2225,8 +2225,8 @@ lowercase-keys@^1.0.0:
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306"
lru-cache@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.1.tgz#1343955edaf2e37d9b9e7ee7241e27c4b9fb72be"
version "4.0.2"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e"
dependencies:
pseudomap "^1.0.1"
yallist "^2.0.0"
@ -2248,6 +2248,10 @@ markdown-to-ast@~3.2.3:
structured-source "^3.0.2"
traverse "^0.6.6"
marked@^0.3.6:
version "0.3.6"
resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7"
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@ -2363,14 +2367,14 @@ nested-error-stacks@^1.0.0:
inherits "~2.0.1"
node-pre-gyp@^0.6.29:
version "0.6.31"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.31.tgz#d8a00ddaa301a940615dbcc8caad4024d58f6017"
version "0.6.32"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.32.tgz#fc452b376e7319b3d255f5f34853ef6fd8fe1fd5"
dependencies:
mkdirp "~0.5.1"
nopt "~3.0.6"
npmlog "^4.0.0"
npmlog "^4.0.1"
rc "~1.1.6"
request "^2.75.0"
request "^2.79.0"
rimraf "~2.5.4"
semver "~5.3.0"
tar "~2.2.1"
@ -2415,7 +2419,7 @@ npm-prefix@^1.0.1:
shellsubstitute "^1.1.0"
untildify "^2.1.0"
npmlog@^4.0.0:
npmlog@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.1.tgz#d14f503b4cd79710375553004ba96e6662fbc0b8"
dependencies:
@ -2647,8 +2651,8 @@ qs@^6.3.0, qs@~6.3.0:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.0.tgz#f403b264f23bc01228c74131b407f18d5ea5d442"
randomatic@^1.1.3:
version "1.1.5"
resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.5.tgz#5e9ef5f2d573c67bd2b8124ae90b5156e457840b"
version "1.1.6"
resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb"
dependencies:
is-number "^2.0.2"
kind-of "^3.0.2"
@ -2758,7 +2762,7 @@ regenerator-runtime@^0.9.5:
regex-cache@^0.4.2:
version "0.4.3"
resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145"
resolved "http://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145"
dependencies:
is-equal-shallow "^0.1.3"
is-primitive "^2.0.0"
@ -2844,7 +2848,7 @@ repeating@^2.0.0:
dependencies:
is-finite "^1.0.0"
request@^2.75.0, request@^2.79.0:
request@^2.79.0:
version "2.79.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
dependencies:
@ -3365,8 +3369,8 @@ uuid@^2.0.1:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
uuid@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.0.tgz#6728fc0459c450d796a99c31837569bdf672d728"
version "3.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
v8flags@^2.0.10:
version "2.0.11"