This commit is contained in:
Brian Beck 2016-08-30 23:33:29 -07:00
parent d67e6433b4
commit 8759943638
20 changed files with 504 additions and 108 deletions

View file

@ -43,6 +43,8 @@
"express": "^4.14.0",
"express-graphql": "^0.5.3",
"graphql": "^0.6.2",
"graphql-relay": "^0.4.2",
"pascalcase": "^0.1.1",
"qs": "^6.2.1",
"request": "^2.74.0",
"retry": "^0.9.0"

View file

@ -65,13 +65,13 @@
"args": [
{
"name": "id",
"description": null,
"description": "The ID of an object",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "MBID",
"name": "ID",
"ofType": null
}
},
@ -92,13 +92,13 @@
"args": [
{
"name": "id",
"description": null,
"description": "The ID of an object",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "MBID",
"name": "ID",
"ofType": null
}
},
@ -119,13 +119,13 @@
"args": [
{
"name": "id",
"description": null,
"description": "The ID of an object",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "MBID",
"name": "ID",
"ofType": null
}
},
@ -146,13 +146,13 @@
"args": [
{
"name": "id",
"description": null,
"description": "The ID of an object",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "MBID",
"name": "ID",
"ofType": null
}
},
@ -173,13 +173,13 @@
"args": [
{
"name": "id",
"description": null,
"description": "The ID of an object",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "MBID",
"name": "ID",
"ofType": null
}
},
@ -200,13 +200,13 @@
"args": [
{
"name": "id",
"description": null,
"description": "The ID of an object",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "MBID",
"name": "ID",
"ofType": null
}
},
@ -227,13 +227,13 @@
"args": [
{
"name": "id",
"description": null,
"description": "The ID of an object",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "MBID",
"name": "ID",
"ofType": null
}
},
@ -254,13 +254,13 @@
"args": [
{
"name": "id",
"description": null,
"description": "The ID of an object",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "MBID",
"name": "ID",
"ofType": null
}
},
@ -281,13 +281,13 @@
"args": [
{
"name": "id",
"description": null,
"description": "The ID of an object",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "MBID",
"name": "ID",
"ofType": null
}
},
@ -308,13 +308,13 @@
"args": [
{
"name": "id",
"description": null,
"description": "The ID of an object",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "MBID",
"name": "ID",
"ofType": null
}
},
@ -335,13 +335,13 @@
"args": [
{
"name": "id",
"description": null,
"description": "The ID of an object",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "MBID",
"name": "ID",
"ofType": null
}
},
@ -364,8 +364,8 @@
},
{
"kind": "SCALAR",
"name": "MBID",
"description": "The `MBID` scalar represents MusicBrainz identifiers, which are 36-character UUIDs.",
"name": "ID",
"description": "The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"4\"`) or integer (such as `4`) input value will be accepted as an ID.",
"fields": null,
"inputFields": null,
"interfaces": null,
@ -379,6 +379,22 @@
"fields": [
{
"name": "id",
"description": "The ID of an object",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -681,6 +697,11 @@
],
"inputFields": null,
"interfaces": [
{
"kind": "INTERFACE",
"name": "Node",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Entity",
@ -690,13 +711,96 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INTERFACE",
"name": "Node",
"description": "An object with an ID",
"fields": [
{
"name": "id",
"description": "The id of the object.",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": null,
"enumValues": null,
"possibleTypes": [
{
"kind": "OBJECT",
"name": "Area",
"ofType": null
},
{
"kind": "OBJECT",
"name": "Artist",
"ofType": null
},
{
"kind": "OBJECT",
"name": "Recording",
"ofType": null
},
{
"kind": "OBJECT",
"name": "Release",
"ofType": null
},
{
"kind": "OBJECT",
"name": "Label",
"ofType": null
},
{
"kind": "OBJECT",
"name": "ReleaseGroup",
"ofType": null
},
{
"kind": "OBJECT",
"name": "Work",
"ofType": null
},
{
"kind": "OBJECT",
"name": "Event",
"ofType": null
},
{
"kind": "OBJECT",
"name": "Place",
"ofType": null
},
{
"kind": "OBJECT",
"name": "Instrument",
"ofType": null
},
{
"kind": "OBJECT",
"name": "URL",
"ofType": null
}
]
},
{
"kind": "INTERFACE",
"name": "Entity",
"description": "An entity in the MusicBrainz schema.",
"fields": [
{
"name": "id",
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -773,6 +877,16 @@
}
]
},
{
"kind": "SCALAR",
"name": "MBID",
"description": "The `MBID` scalar represents MusicBrainz identifiers, which are 36-character UUIDs.",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "SCALAR",
"name": "String",
@ -800,6 +914,22 @@
"fields": [
{
"name": "id",
"description": "The ID of an object",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -1209,6 +1339,11 @@
],
"inputFields": null,
"interfaces": [
{
"kind": "INTERFACE",
"name": "Node",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Entity",
@ -1375,6 +1510,22 @@
"fields": [
{
"name": "id",
"description": "The ID of an object",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -1590,6 +1741,11 @@
],
"inputFields": null,
"interfaces": [
{
"kind": "INTERFACE",
"name": "Node",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Entity",
@ -1795,6 +1951,22 @@
"fields": [
{
"name": "id",
"description": "The ID of an object",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -2148,6 +2320,11 @@
],
"inputFields": null,
"interfaces": [
{
"kind": "INTERFACE",
"name": "Node",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Entity",
@ -2199,6 +2376,22 @@
"fields": [
{
"name": "id",
"description": "The ID of an object",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -2425,6 +2618,11 @@
],
"inputFields": null,
"interfaces": [
{
"kind": "INTERFACE",
"name": "Node",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Entity",
@ -2451,6 +2649,22 @@
"fields": [
{
"name": "id",
"description": "The ID of an object",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -2710,6 +2924,11 @@
],
"inputFields": null,
"interfaces": [
{
"kind": "INTERFACE",
"name": "Node",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Entity",
@ -3700,6 +3919,22 @@
"fields": [
{
"name": "id",
"description": "The ID of an object",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -3842,6 +4077,11 @@
],
"inputFields": null,
"interfaces": [
{
"kind": "INTERFACE",
"name": "Node",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Entity",
@ -3858,6 +4098,22 @@
"fields": [
{
"name": "id",
"description": "The ID of an object",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -3971,6 +4227,11 @@
],
"inputFields": null,
"interfaces": [
{
"kind": "INTERFACE",
"name": "Node",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Entity",
@ -3997,6 +4258,22 @@
"fields": [
{
"name": "id",
"description": "The ID of an object",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -4147,6 +4424,11 @@
],
"inputFields": null,
"interfaces": [
{
"kind": "INTERFACE",
"name": "Node",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Entity",
@ -4208,6 +4490,22 @@
"fields": [
{
"name": "id",
"description": "The ID of an object",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -4285,6 +4583,11 @@
],
"inputFields": null,
"interfaces": [
{
"kind": "INTERFACE",
"name": "Node",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Entity",
@ -4301,6 +4604,22 @@
"fields": [
{
"name": "id",
"description": "The ID of an object",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mbid",
"description": null,
"args": [],
"type": {
@ -4346,6 +4665,11 @@
],
"inputFields": null,
"interfaces": [
{
"kind": "INTERFACE",
"name": "Node",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Entity",

View file

@ -40,8 +40,8 @@ export default class MusicBrainz {
// we then wait a few seconds before making more. In practice this can
// seemingly be set to about 5 requests every 5 seconds before we're
// considered to exceed the rate limit.
limit: 3,
limitPeriod: 3000,
limit: 5,
limitPeriod: 5000,
concurrency: 10,
retries: 10,
// It's OK for `retryDelayMin` to be less than one second, even 0, because

View file

@ -1,10 +1,12 @@
import { GraphQLSchema, GraphQLObjectType } from 'graphql'
import { LookupQuery, BrowseQuery, SearchQuery } from './queries'
import { nodeField } from './types/node'
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'RootQuery',
fields: () => ({
node: nodeField,
lookup: { type: LookupQuery, resolve: () => ({}) },
browse: { type: BrowseQuery, resolve: () => ({}) },
search: { type: SearchQuery, resolve: () => ({}) }

View file

@ -1,7 +1,10 @@
import { GraphQLObjectType, GraphQLString, GraphQLList } from 'graphql/type'
import { GraphQLObjectType, GraphQLString, GraphQLList } from 'graphql'
import { connectionDefinitions } from 'graphql-relay'
import Node from './node'
import Entity from './entity'
import {
id,
mbid,
name,
sortName,
disambiguation,
@ -9,16 +12,16 @@ import {
events,
labels,
places,
releases,
createPageType
releases
} from './helpers'
const Area = new GraphQLObjectType({
name: 'Area',
description: 'A country, region, city or the like.',
interfaces: () => [Entity],
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
name,
sortName,
disambiguation,
@ -34,5 +37,6 @@ const Area = new GraphQLObjectType({
})
})
export const AreaPage = createPageType(Area)
const { connectionType: AreaConnection } = connectionDefinitions({ nodeType: Area })
export { AreaConnection }
export default Area

View file

@ -1,4 +1,6 @@
import { GraphQLObjectType, GraphQLString, GraphQLList } from 'graphql/type'
import { connectionDefinitions } from 'graphql-relay'
import Node from './node'
import Entity from './entity'
import Alias from './alias'
import Area from './area'
@ -6,6 +8,7 @@ import {
getFallback,
fieldWithID,
id,
mbid,
name,
sortName,
disambiguation,
@ -14,8 +17,7 @@ import {
releases,
releaseGroups,
works,
relations,
createPageType
relations
} from './helpers'
const Artist = new GraphQLObjectType({
@ -23,9 +25,10 @@ const Artist = new GraphQLObjectType({
description:
'An artist is generally a musician, a group of musicians, or another ' +
'music professional (composer, engineer, illustrator, producer, etc.)',
interfaces: () => [Entity],
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
name,
sortName,
disambiguation,
@ -65,5 +68,6 @@ const Artist = new GraphQLObjectType({
})
})
export const ArtistPage = createPageType(Artist)
const { connectionType: ArtistConnection } = connectionDefinitions({ nodeType: Artist })
export { ArtistConnection }
export default Artist

View file

@ -1,5 +1,5 @@
import { GraphQLInterfaceType } from 'graphql/type'
import { id } from './helpers'
import { GraphQLInterfaceType } from 'graphql'
import { mbid } from './helpers'
export default new GraphQLInterfaceType({
name: 'Entity',
@ -10,6 +10,6 @@ export default new GraphQLInterfaceType({
}
},
fields: () => ({
id
mbid
})
})

View file

@ -1,13 +1,15 @@
import { GraphQLObjectType, GraphQLString, GraphQLBoolean } from 'graphql/type'
import { connectionDefinitions } from 'graphql-relay'
import Node from './node'
import Entity from './entity'
import { Time } from './scalars'
import {
fieldWithID,
id,
mbid,
name,
disambiguation,
lifeSpan,
createPageType
lifeSpan
} from './helpers'
const Event = new GraphQLObjectType({
@ -15,9 +17,10 @@ const Event = new GraphQLObjectType({
description:
'An organized event which people can attend, usually live performances ' +
'like concerts and festivals.',
interfaces: () => [Entity],
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
name,
disambiguation,
lifeSpan,
@ -28,5 +31,6 @@ const Event = new GraphQLObjectType({
})
})
export const EventPage = createPageType(Event)
const { connectionType: EventConnection } = connectionDefinitions({ nodeType: Event })
export { EventConnection }
export default Event

View file

@ -1,12 +1,14 @@
import dashify from 'dashify'
import pascalCase from 'pascalcase'
import {
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLList,
GraphQLNonNull
} from 'graphql/type'
import { MBID, DateType } from './scalars'
} from 'graphql'
import { globalIdField } from 'graphql-relay'
import { MBID } from './scalars'
import { ReleaseGroupType, ReleaseStatus } from './enums'
import ArtistCredit from './artist-credit'
import Artist from './artist'
@ -27,6 +29,9 @@ import {
includeRelations
} from '../resolvers'
export const toNodeType = pascalCase
export const toEntityType = dashify
export function getByline (data) {
const credit = data['artist-credit']
if (credit && credit.length) {
@ -94,41 +99,8 @@ export function searchQuery (entityPage) {
}
}
export function createPageType (type) {
const singularName = dashify(type.name)
const pluralName = singularName + (singularName.endsWith('s') ? '' : 's')
return new GraphQLObjectType({
name: `${type.name}Page`,
description: `A page of ${type.name} results from browsing or searching.`,
fields: {
count: {
type: new GraphQLNonNull(GraphQLInt),
resolve: list => {
if (list.count != null) {
return list.count
}
return list[`${singularName}-count`]
}
},
offset: {
type: new GraphQLNonNull(GraphQLInt),
resolve: list => {
if (list.offset != null) {
return list.offset
}
return list[`${singularName}-offset`]
}
},
created: { type: DateType },
results: {
type: new GraphQLNonNull(new GraphQLList(type)),
resolve: list => list[pluralName]
}
}
})
}
export const id = { type: new GraphQLNonNull(MBID) }
export const id = globalIdField()
export const mbid = { type: new GraphQLNonNull(MBID) }
export const name = { type: GraphQLString }
export const sortName = { type: GraphQLString, resolve: getHyphenated }
export const title = { type: GraphQLString }

View file

@ -1,5 +1,6 @@
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 Area, AreaPage } from './area'
export { default as Artist, ArtistPage } from './artist'
@ -10,5 +11,6 @@ export { default as Place, PlacePage } from './place'
export { default as Recording, RecordingPage } from './recording'
export { default as Release, ReleasePage } from './release'
export { default as ReleaseGroup, ReleaseGroupPage } from './release-group'
export { default as Series, SeriesPage } from './series'
export { default as URL, URLPage } from './url'
export { default as Work, WorkPage } from './work'

View file

@ -1,8 +1,10 @@
import { GraphQLObjectType, GraphQLString } from 'graphql/type'
import Node from './node'
import Entity from './entity'
import {
fieldWithID,
id,
mbid,
name,
disambiguation
} from './helpers'
@ -11,9 +13,10 @@ const Instrument = new GraphQLObjectType({
name: 'Instrument',
description:
'Instruments are devices created or adapted to make musical sounds.',
interfaces: () => [Entity],
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
name,
disambiguation,
description: { type: GraphQLString },

View file

@ -4,26 +4,29 @@ import {
GraphQLString,
GraphQLInt
} from 'graphql/type'
import { connectionDefinitions } from 'graphql-relay'
import Node from './node'
import Entity from './entity'
import { IPI } from './scalars'
import Area from './area'
import {
id,
mbid,
name,
sortName,
disambiguation,
lifeSpan,
releases,
fieldWithID,
createPageType
fieldWithID
} from './helpers'
const Label = new GraphQLObjectType({
name: 'Label',
description: 'Labels represent mostly (but not only) imprints.',
interfaces: () => [Entity],
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
name,
sortName,
disambiguation,
@ -37,5 +40,6 @@ const Label = new GraphQLObjectType({
})
})
export const LabelPage = createPageType(Label)
const { connectionType: LabelConnection } = connectionDefinitions({ nodeType: Label })
export { LabelConnection }
export default Label

21
src/types/node.js Normal file
View file

@ -0,0 +1,21 @@
import { nodeDefinitions, fromGlobalId } from 'graphql-relay'
import { lookupLoader } from '../loaders'
import { toEntityType } from './helpers'
const { nodeInterface, nodeField } = nodeDefinitions(
(globalID) => {
const { type, id } = fromGlobalId(globalID)
const entityType = toEntityType(type)
return lookupLoader.load([entityType, id])
},
(obj) => {
try {
return require(`./${obj.entityType}`)
} catch (err) {
return null
}
}
)
export default nodeInterface
export { nodeInterface, nodeField }

View file

@ -1,15 +1,17 @@
import { GraphQLObjectType, GraphQLString } from 'graphql/type'
import { connectionDefinitions } from 'graphql-relay'
import Node from './node'
import Entity from './entity'
import { Degrees } from './scalars'
import Area from './area'
import {
id,
mbid,
name,
disambiguation,
lifeSpan,
events,
fieldWithID,
createPageType
fieldWithID
} from './helpers'
export const Coordinates = new GraphQLObjectType({
@ -26,9 +28,10 @@ const Place = new GraphQLObjectType({
description:
'A venue, studio or other place where music is performed, recorded, ' +
'engineered, etc.',
interfaces: () => [Entity],
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
name,
disambiguation,
address: { type: GraphQLString },
@ -40,5 +43,6 @@ const Place = new GraphQLObjectType({
})
})
export const PlacePage = createPageType(Place)
const { connectionType: PlaceConnection } = connectionDefinitions({ nodeType: Place })
export { PlaceConnection }
export default Place

View file

@ -1,14 +1,16 @@
import { GraphQLObjectType, GraphQLInt, GraphQLBoolean } from 'graphql/type'
import { connectionDefinitions } from 'graphql-relay'
import Node from './node'
import Entity from './entity'
import {
id,
mbid,
title,
disambiguation,
artistCredit,
artists,
releases,
relations,
createPageType
relations
} from './helpers'
const Recording = new GraphQLObjectType({
@ -16,9 +18,10 @@ const Recording = new GraphQLObjectType({
description:
'Represents a unique mix or edit. Has title, artist credit, duration, ' +
'list of PUIDs and ISRCs.',
interfaces: () => [Entity],
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
title,
disambiguation,
artistCredit,
@ -30,5 +33,6 @@ const Recording = new GraphQLObjectType({
})
})
export const RecordingPage = createPageType(Recording)
const { connectionType: RecordingConnection } = connectionDefinitions({ nodeType: Recording })
export { RecordingConnection }
export default Recording

View file

@ -1,8 +1,11 @@
import { GraphQLObjectType, GraphQLString, GraphQLList } from 'graphql/type'
import { connectionDefinitions } from 'graphql-relay'
import Node from './node'
import Entity from './entity'
import { DateType } from './scalars'
import {
id,
mbid,
title,
disambiguation,
artistCredit,
@ -10,8 +13,7 @@ import {
releases,
relations,
getHyphenated,
fieldWithID,
createPageType
fieldWithID
} from './helpers'
const ReleaseGroup = new GraphQLObjectType({
@ -19,9 +21,10 @@ const ReleaseGroup = new GraphQLObjectType({
description:
'Represents an abstract "album" (or "single", or "EP") entity. ' +
'Technically its a group of releases, with a specified type.',
interfaces: () => [Entity],
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
title,
disambiguation,
artistCredit,
@ -34,5 +37,6 @@ const ReleaseGroup = new GraphQLObjectType({
})
})
export const ReleaseGroupPage = createPageType(ReleaseGroup)
const { connectionType: ReleaseGroupConnection } = connectionDefinitions({ nodeType: ReleaseGroup })
export { ReleaseGroupConnection }
export default ReleaseGroup

View file

@ -1,9 +1,12 @@
import { GraphQLObjectType, GraphQLString, GraphQLList } from 'graphql/type'
import { connectionDefinitions } from 'graphql-relay'
import Node from './node'
import Entity from './entity'
import { DateType } from './scalars'
import ReleaseEvent from './release-event'
import {
id,
mbid,
title,
disambiguation,
artistCredit,
@ -13,8 +16,7 @@ import {
releaseGroups,
relations,
getHyphenated,
fieldWithID,
createPageType
fieldWithID
} from './helpers'
const Release = new GraphQLObjectType({
@ -23,9 +25,10 @@ const Release = new GraphQLObjectType({
'Real-world release object you can buy in your music store. It has ' +
'release date and country, list of catalog number and label pairs, ' +
'packaging type and release status.',
interfaces: () => [Entity],
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
title,
disambiguation,
artistCredit,
@ -47,5 +50,6 @@ const Release = new GraphQLObjectType({
})
})
export const ReleasePage = createPageType(Release)
const { connectionType: ReleaseConnection } = connectionDefinitions({ nodeType: Release })
export { ReleaseConnection }
export default Release

View file

@ -0,0 +1,30 @@
import { GraphQLObjectType } from 'graphql/type'
import { connectionDefinitions } from 'graphql-relay'
import Node from './node'
import Entity from './entity'
import {
id,
mbid,
name,
disambiguation,
fieldWithID
} from './helpers'
const Series = new GraphQLObjectType({
name: 'Series',
description:
'A series is a sequence of separate release groups, releases, ' +
'recordings, works or events with a common theme.',
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
name,
disambiguation,
...fieldWithID('type')
})
})
const { connectionType: SeriesConnection } = connectionDefinitions({ nodeType: Series })
export { SeriesConnection }
export default Series

View file

@ -1,7 +1,9 @@
import { GraphQLObjectType, GraphQLNonNull } from 'graphql/type'
import { connectionDefinitions } from 'graphql-relay'
import Node from './node'
import Entity from './entity'
import { URLString } from './scalars'
import { id, relations, createPageType } from './helpers'
import { id, mbid, relations } from './helpers'
const URL = new GraphQLObjectType({
name: 'URL',
@ -9,13 +11,15 @@ const URL = new GraphQLObjectType({
'A URL pointing to a resource external to MusicBrainz, i.e. an official ' +
'homepage, a site where music can be acquired, an entry in another ' +
'database, etc.',
interfaces: () => [Entity],
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
resource: { type: new GraphQLNonNull(URLString) },
relations
})
})
export const URLPage = createPageType(URL)
const { connectionType: URLConnection } = connectionDefinitions({ nodeType: URL })
export { URLConnection }
export default URL

View file

@ -1,13 +1,15 @@
import { GraphQLObjectType, GraphQLString, GraphQLList } from 'graphql/type'
import { connectionDefinitions } from 'graphql-relay'
import Node from './node'
import Entity from './entity'
import {
id,
mbid,
title,
disambiguation,
artists,
relations,
fieldWithID,
createPageType
fieldWithID
} from './helpers'
const Work = new GraphQLObjectType({
@ -15,9 +17,10 @@ const Work = new GraphQLObjectType({
description:
'A distinct intellectual or artistic creation, which can be expressed in ' +
'the form of one or more audio recordings',
interfaces: () => [Entity],
interfaces: () => [Node, Entity],
fields: () => ({
id,
mbid,
title,
disambiguation,
iswcs: { type: new GraphQLList(GraphQLString) },
@ -28,5 +31,6 @@ const Work = new GraphQLObjectType({
})
})
export const WorkPage = createPageType(Work)
const { connectionType: WorkConnection } = connectionDefinitions({ nodeType: Work })
export { WorkConnection }
export default Work