diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3e69b31 --- /dev/null +++ b/.travis.yml @@ -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 diff --git a/src/queries/browse.js b/src/queries/browse.js index 451f5c9..06bb8d5 100644 --- a/src/queries/browse.js +++ b/src/queries/browse.js @@ -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, diff --git a/src/queries/index.js b/src/queries/index.js index eea0a46..5bd9800 100644 --- a/src/queries/index.js +++ b/src/queries/index.js @@ -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' diff --git a/src/queries/lookup.js b/src/queries/lookup.js index 9260edb..07d542b 100644 --- a/src/queries/lookup.js +++ b/src/queries/lookup.js @@ -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, diff --git a/src/queries/search.js b/src/queries/search.js index 98ae607..4d9f7c7 100644 --- a/src/queries/search.js +++ b/src/queries/search.js @@ -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, diff --git a/src/resolvers.js b/src/resolvers.js index 2303d7c..2c86270 100644 --- a/src/resolvers.js +++ b/src/resolvers.js @@ -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)) } } diff --git a/src/schema.js b/src/schema.js index 7fbcff9..3dd0a7b 100644 --- a/src/schema.js +++ b/src/schema.js @@ -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 }) }) }) diff --git a/src/types/artist.js b/src/types/artist.js index 881e0f3..da7661f 100644 --- a/src/types/artist.js +++ b/src/types/artist.js @@ -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', { diff --git a/src/types/entity.js b/src/types/entity.js index 7a1da6a..f1f29d7 100644 --- a/src/types/entity.js +++ b/src/types/entity.js @@ -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 diff --git a/src/types/helpers.js b/src/types/helpers.js index 7bc2cd1..67d06ae 100644 --- a/src/types/helpers.js +++ b/src/types/helpers.js @@ -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 person’s 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 entity’s 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) })) diff --git a/src/types/index.js b/src/types/index.js index 696694e..afeb92f 100644 --- a/src/types/index.js +++ b/src/types/index.js @@ -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' diff --git a/src/types/relationship.js b/src/types/relationship.js index 6cc25c8..750cc37 100644 --- a/src/types/relationship.js +++ b/src/types/relationship.js @@ -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, diff --git a/src/types/release-group.js b/src/types/release-group.js index 21459b5..6ae6d9a 100644 --- a/src/types/release-group.js +++ b/src/types/release-group.js @@ -15,7 +15,7 @@ import { relationships, tags, fieldWithID, - getHyphenated, + resolveHyphenated, connectionWithExtras } from './helpers' @@ -40,7 +40,7 @@ album – it doesn’t 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, diff --git a/src/types/release.js b/src/types/release.js index 91e28f0..011f1db 100644 --- a/src/types/release.js +++ b/src/types/release.js @@ -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, diff --git a/yarn.lock b/yarn.lock index 2e92390..98b8d9f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"