2016-08-08 07:54:06 +00:00
|
|
|
|
import dashify from 'dashify'
|
2016-08-31 06:33:29 +00:00
|
|
|
|
import pascalCase from 'pascalcase'
|
2016-08-20 05:59:32 +00:00
|
|
|
|
import {
|
|
|
|
|
|
GraphQLObjectType,
|
|
|
|
|
|
GraphQLString,
|
2016-11-28 13:49:04 +00:00
|
|
|
|
GraphQLInt,
|
2016-08-20 05:59:32 +00:00
|
|
|
|
GraphQLList,
|
|
|
|
|
|
GraphQLNonNull
|
2016-08-31 06:33:29 +00:00
|
|
|
|
} from 'graphql'
|
2016-09-01 08:39:27 +00:00
|
|
|
|
import {
|
|
|
|
|
|
globalIdField,
|
|
|
|
|
|
connectionArgs,
|
2016-11-28 13:49:04 +00:00
|
|
|
|
connectionDefinitions,
|
|
|
|
|
|
connectionFromArray,
|
2016-09-01 08:39:27 +00:00
|
|
|
|
forwardConnectionArgs
|
|
|
|
|
|
} from 'graphql-relay'
|
2016-08-31 06:33:29 +00:00
|
|
|
|
import { MBID } from './scalars'
|
2016-08-20 05:59:32 +00:00
|
|
|
|
import { ReleaseGroupType, ReleaseStatus } from './enums'
|
2016-11-28 13:49:04 +00:00
|
|
|
|
import Alias from './alias'
|
2016-08-20 05:59:32 +00:00
|
|
|
|
import ArtistCredit from './artist-credit'
|
2016-12-12 04:03:05 +00:00
|
|
|
|
import { AreaConnection } from './area'
|
2016-09-01 08:39:27 +00:00
|
|
|
|
import { ArtistConnection } from './artist'
|
2016-12-12 08:34:26 +00:00
|
|
|
|
import { CollectionConnection } from './collection'
|
2016-09-01 08:39:27 +00:00
|
|
|
|
import { EventConnection } from './event'
|
2016-12-12 08:34:26 +00:00
|
|
|
|
import { InstrumentConnection } from './instrument'
|
2016-09-01 08:39:27 +00:00
|
|
|
|
import { LabelConnection } from './label'
|
2016-08-20 05:59:32 +00:00
|
|
|
|
import LifeSpan from './life-span'
|
2016-09-01 08:39:27 +00:00
|
|
|
|
import { PlaceConnection } from './place'
|
|
|
|
|
|
import { RecordingConnection } from './recording'
|
2016-11-26 01:38:32 +00:00
|
|
|
|
import { RelationshipConnection } from './relationship'
|
2016-09-01 08:39:27 +00:00
|
|
|
|
import { ReleaseConnection } from './release'
|
|
|
|
|
|
import { ReleaseGroupConnection } from './release-group'
|
2016-12-12 08:34:26 +00:00
|
|
|
|
import { SeriesConnection } from './series'
|
2016-11-28 13:49:04 +00:00
|
|
|
|
import { TagConnection } from './tag'
|
2016-09-01 08:39:27 +00:00
|
|
|
|
import { WorkConnection } from './work'
|
2016-08-20 05:59:32 +00:00
|
|
|
|
import {
|
2016-12-02 08:21:10 +00:00
|
|
|
|
resolveLinked,
|
|
|
|
|
|
resolveRelationship,
|
|
|
|
|
|
createSubqueryResolver,
|
2016-11-26 01:38:32 +00:00
|
|
|
|
includeRelationships
|
2016-08-20 05:59:32 +00:00
|
|
|
|
} from '../resolvers'
|
|
|
|
|
|
|
2016-11-26 01:38:32 +00:00
|
|
|
|
export const toPascal = pascalCase
|
|
|
|
|
|
export const toDashed = dashify
|
|
|
|
|
|
|
|
|
|
|
|
export function toPlural (name) {
|
|
|
|
|
|
return name.endsWith('s') ? name : name + 's'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function toSingular (name) {
|
|
|
|
|
|
return name.endsWith('s') && !/series/i.test(name) ? name.slice(0, -1) : name
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function toWords (name) {
|
|
|
|
|
|
return toPascal(name).replace(/([^A-Z])?([A-Z]+)/g, (match, tail, head) => {
|
|
|
|
|
|
tail = tail ? tail + ' ' : ''
|
|
|
|
|
|
head = head.length > 1 ? head : head.toLowerCase()
|
|
|
|
|
|
return `${tail}${head}`
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2016-08-31 06:33:29 +00:00
|
|
|
|
|
2016-12-11 20:32:58 +00:00
|
|
|
|
export function resolveHyphenated (obj, args, context, info) {
|
|
|
|
|
|
const name = toDashed(info.fieldName)
|
|
|
|
|
|
return obj[name]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function resolveWithFallback (keys) {
|
|
|
|
|
|
return (obj) => {
|
|
|
|
|
|
for (let i = 0; i < keys.length; i++) {
|
|
|
|
|
|
const key = keys[i]
|
|
|
|
|
|
if (key in obj) {
|
|
|
|
|
|
return obj[key]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-08-08 07:54:06 +00:00
|
|
|
|
export function fieldWithID (name, config = {}) {
|
|
|
|
|
|
config = {
|
|
|
|
|
|
type: GraphQLString,
|
2016-12-02 08:21:10 +00:00
|
|
|
|
resolve: resolveHyphenated,
|
2016-08-08 07:54:06 +00:00
|
|
|
|
...config
|
|
|
|
|
|
}
|
|
|
|
|
|
const isPlural = config.type instanceof GraphQLList
|
2016-11-26 01:38:32 +00:00
|
|
|
|
const singularName = isPlural ? toSingular(name) : name
|
2016-08-08 07:54:06 +00:00
|
|
|
|
const idName = isPlural ? `${singularName}IDs` : `${name}ID`
|
2016-11-26 10:37:23 +00:00
|
|
|
|
const s = isPlural ? 's' : ''
|
2016-08-08 07:54:06 +00:00
|
|
|
|
const idConfig = {
|
|
|
|
|
|
type: isPlural ? new GraphQLList(MBID) : MBID,
|
2016-11-26 10:37:23 +00:00
|
|
|
|
description: `The MBID${s} associated with the value${s} of the \`${name}\`
|
|
|
|
|
|
field.`,
|
2016-12-02 08:21:10 +00:00
|
|
|
|
resolve: resolveHyphenated
|
2016-08-08 07:54:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
|
|
|
[name]: config,
|
|
|
|
|
|
[idName]: idConfig
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-08-31 06:33:29 +00:00
|
|
|
|
export const id = globalIdField()
|
2016-09-01 04:31:48 +00:00
|
|
|
|
export const mbid = {
|
|
|
|
|
|
type: new GraphQLNonNull(MBID),
|
2016-09-01 08:39:27 +00:00
|
|
|
|
description: 'The MBID of the entity.',
|
2016-12-02 08:21:10 +00:00
|
|
|
|
resolve: entity => entity.id
|
2016-09-01 04:31:48 +00:00
|
|
|
|
}
|
2016-11-26 01:38:32 +00:00
|
|
|
|
export const name = {
|
|
|
|
|
|
type: GraphQLString,
|
|
|
|
|
|
description: 'The official name of the entity.'
|
|
|
|
|
|
}
|
|
|
|
|
|
export const sortName = {
|
|
|
|
|
|
type: GraphQLString,
|
|
|
|
|
|
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).`,
|
2016-12-02 08:21:10 +00:00
|
|
|
|
resolve: resolveHyphenated
|
2016-11-26 01:38:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
export const title = {
|
|
|
|
|
|
type: GraphQLString,
|
|
|
|
|
|
description: 'The official title of the entity.'
|
|
|
|
|
|
}
|
|
|
|
|
|
export const disambiguation = {
|
|
|
|
|
|
type: GraphQLString,
|
|
|
|
|
|
description: 'A comment used to help distinguish identically named entitites.'
|
|
|
|
|
|
}
|
|
|
|
|
|
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.`,
|
2016-12-02 08:21:10 +00:00
|
|
|
|
resolve: resolveHyphenated
|
2016-11-26 01:38:32 +00:00
|
|
|
|
}
|
2016-08-20 05:59:32 +00:00
|
|
|
|
|
2016-11-28 13:49:04 +00:00
|
|
|
|
function linkedQuery (connectionType, { args, ...config } = {}) {
|
|
|
|
|
|
const typeName = toPlural(toWords(connectionType.name.slice(0, -10)))
|
2016-09-01 08:39:27 +00:00
|
|
|
|
return {
|
|
|
|
|
|
type: connectionType,
|
2016-11-28 13:49:04 +00:00
|
|
|
|
description: `A list of ${typeName} linked to this entity.`,
|
2016-09-01 08:39:27 +00:00
|
|
|
|
args: {
|
2016-12-12 05:09:37 +00:00
|
|
|
|
...args,
|
|
|
|
|
|
...forwardConnectionArgs
|
2016-09-01 08:39:27 +00:00
|
|
|
|
},
|
2016-12-02 08:21:10 +00:00
|
|
|
|
resolve: resolveLinked,
|
2016-11-28 13:49:04 +00:00
|
|
|
|
...config
|
2016-09-01 08:39:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-11-26 01:38:32 +00:00
|
|
|
|
export const relationship = {
|
|
|
|
|
|
type: RelationshipConnection,
|
|
|
|
|
|
description: 'A list of relationships between these two entity types.',
|
2016-08-20 05:59:32 +00:00
|
|
|
|
args: {
|
2016-11-26 01:38:32 +00:00
|
|
|
|
direction: {
|
|
|
|
|
|
type: GraphQLString,
|
|
|
|
|
|
description: 'Filter by the relationship direction.'
|
|
|
|
|
|
},
|
|
|
|
|
|
...fieldWithID('type', {
|
|
|
|
|
|
description: 'Filter by the relationship type.'
|
2016-12-12 08:02:58 +00:00
|
|
|
|
}),
|
|
|
|
|
|
...connectionArgs
|
2016-08-20 05:59:32 +00:00
|
|
|
|
},
|
2016-12-02 08:21:10 +00:00
|
|
|
|
resolve: resolveRelationship
|
2016-08-20 05:59:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-11-26 01:38:32 +00:00
|
|
|
|
export const relationships = {
|
2016-08-20 05:59:32 +00:00
|
|
|
|
type: new GraphQLObjectType({
|
2016-11-26 01:38:32 +00:00
|
|
|
|
name: 'Relationships',
|
|
|
|
|
|
description: 'Lists of entity relationships for each entity type.',
|
2016-08-20 05:59:32 +00:00
|
|
|
|
fields: () => ({
|
2016-11-26 01:38:32 +00:00
|
|
|
|
areas: relationship,
|
|
|
|
|
|
artists: relationship,
|
|
|
|
|
|
events: relationship,
|
|
|
|
|
|
instruments: relationship,
|
|
|
|
|
|
labels: relationship,
|
|
|
|
|
|
places: relationship,
|
|
|
|
|
|
recordings: relationship,
|
|
|
|
|
|
releases: relationship,
|
|
|
|
|
|
releaseGroups: relationship,
|
|
|
|
|
|
series: relationship,
|
|
|
|
|
|
urls: relationship,
|
|
|
|
|
|
works: relationship
|
2016-08-20 05:59:32 +00:00
|
|
|
|
})
|
|
|
|
|
|
}),
|
2016-11-26 01:38:32 +00:00
|
|
|
|
description: 'Relationships between this entity and other entitites.',
|
2016-12-02 08:21:10 +00:00
|
|
|
|
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])
|
2016-08-20 05:59:32 +00:00
|
|
|
|
}
|
2016-12-02 08:21:10 +00:00
|
|
|
|
return promise.then(entity => entity.relations)
|
2016-08-20 05:59:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-11-28 13:49:04 +00:00
|
|
|
|
export const aliases = {
|
|
|
|
|
|
type: new GraphQLList(Alias),
|
|
|
|
|
|
description: `[Aliases](https://musicbrainz.org/doc/Aliases) are used to store
|
|
|
|
|
|
alternate names or misspellings.`,
|
2016-12-02 08:21:10 +00:00
|
|
|
|
resolve: createSubqueryResolver()
|
2016-11-28 13:49:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-12-11 20:32:58 +00:00
|
|
|
|
export const artistCredits = {
|
2016-08-20 05:59:32 +00:00
|
|
|
|
type: new GraphQLList(ArtistCredit),
|
2016-11-26 01:38:32 +00:00
|
|
|
|
description: 'The main credited artist(s).',
|
2016-12-11 20:32:58 +00:00
|
|
|
|
resolve: createSubqueryResolver({ key: 'artist-credit' })
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export const artistCredit = {
|
|
|
|
|
|
...artistCredits,
|
|
|
|
|
|
deprecationReason: `The \`artistCredit\` field has been renamed to
|
|
|
|
|
|
\`artistCredits\`, since it is a list of credits and is referred to in the
|
|
|
|
|
|
plural form throughout the MusicBrainz documentation. This field is deprecated
|
|
|
|
|
|
and will be removed in a major release in the future. Use the equivalent
|
|
|
|
|
|
\`artistCredits\` field.`
|
2016-08-20 05:59:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-12-10 02:55:41 +00:00
|
|
|
|
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.'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-12-12 04:03:05 +00:00
|
|
|
|
export const areas = linkedQuery(AreaConnection)
|
2016-09-01 08:39:27 +00:00
|
|
|
|
export const artists = linkedQuery(ArtistConnection)
|
2016-12-12 17:43:17 +00:00
|
|
|
|
export const collections = linkedQuery(CollectionConnection, {
|
|
|
|
|
|
description: 'A list of collections containing this entity.'
|
|
|
|
|
|
})
|
2016-09-01 08:39:27 +00:00
|
|
|
|
export const events = linkedQuery(EventConnection)
|
2016-12-12 08:34:26 +00:00
|
|
|
|
export const instruments = linkedQuery(InstrumentConnection)
|
2016-09-01 08:39:27 +00:00
|
|
|
|
export const labels = linkedQuery(LabelConnection)
|
|
|
|
|
|
export const places = linkedQuery(PlaceConnection)
|
|
|
|
|
|
export const recordings = linkedQuery(RecordingConnection)
|
|
|
|
|
|
export const releases = linkedQuery(ReleaseConnection, {
|
2016-11-28 13:49:04 +00:00
|
|
|
|
args: {
|
2016-12-10 02:55:41 +00:00
|
|
|
|
type: releaseGroupType,
|
|
|
|
|
|
status: releaseStatus
|
2016-11-28 13:49:04 +00:00
|
|
|
|
}
|
2016-09-01 08:39:27 +00:00
|
|
|
|
})
|
|
|
|
|
|
export const releaseGroups = linkedQuery(ReleaseGroupConnection, {
|
2016-11-28 13:49:04 +00:00
|
|
|
|
args: {
|
2016-12-10 02:55:41 +00:00
|
|
|
|
type: releaseGroupType
|
2016-11-28 13:49:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
})
|
2016-12-12 08:34:26 +00:00
|
|
|
|
export const series = linkedQuery(SeriesConnection)
|
2016-11-28 13:49:04 +00:00
|
|
|
|
export const tags = linkedQuery(TagConnection, {
|
2016-12-11 20:32:58 +00:00
|
|
|
|
resolve: createSubqueryResolver({}, (value = [], args) => ({
|
2016-11-28 13:49:04 +00:00
|
|
|
|
totalCount: value.length,
|
|
|
|
|
|
...connectionFromArray(value, args)
|
|
|
|
|
|
}))
|
2016-09-01 08:39:27 +00:00
|
|
|
|
})
|
|
|
|
|
|
export const works = linkedQuery(WorkConnection)
|
2016-11-28 13:49:04 +00:00
|
|
|
|
|
|
|
|
|
|
export const totalCount = {
|
|
|
|
|
|
type: GraphQLInt,
|
|
|
|
|
|
description: `A count of the total number of items in this connection,
|
|
|
|
|
|
ignoring pagination.`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-11-28 14:43:32 +00:00
|
|
|
|
export const score = {
|
|
|
|
|
|
type: GraphQLInt,
|
|
|
|
|
|
description: `The relevancy score (0–100) assigned by the search engine, if
|
|
|
|
|
|
these results were found through a search.`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function connectionWithExtras (nodeType) {
|
2016-11-28 13:49:04 +00:00
|
|
|
|
return connectionDefinitions({
|
|
|
|
|
|
nodeType,
|
2016-11-28 14:43:32 +00:00
|
|
|
|
connectionFields: () => ({ totalCount }),
|
|
|
|
|
|
edgeFields: () => ({ score })
|
2016-11-28 13:49:04 +00:00
|
|
|
|
}).connectionType
|
|
|
|
|
|
}
|