mirror of
https://github.com/BradNut/graphbrainz
synced 2025-09-08 17:40:32 +00:00
212 lines
6 KiB
JavaScript
212 lines
6 KiB
JavaScript
import dashify from 'dashify'
|
||
import pascalCase from 'pascalcase'
|
||
import {
|
||
GraphQLObjectType,
|
||
GraphQLString,
|
||
GraphQLList,
|
||
GraphQLNonNull
|
||
} from 'graphql'
|
||
import {
|
||
globalIdField,
|
||
connectionArgs,
|
||
forwardConnectionArgs
|
||
} from 'graphql-relay'
|
||
import { MBID } from './scalars'
|
||
import { ReleaseGroupType, ReleaseStatus } from './enums'
|
||
import ArtistCredit from './artist-credit'
|
||
import { ArtistConnection } from './artist'
|
||
import { EventConnection } from './event'
|
||
import { LabelConnection } from './label'
|
||
import LifeSpan from './life-span'
|
||
import { PlaceConnection } from './place'
|
||
import { RecordingConnection } from './recording'
|
||
import { RelationshipConnection } from './relationship'
|
||
import { ReleaseConnection } from './release'
|
||
import { ReleaseGroupConnection } from './release-group'
|
||
import { WorkConnection } from './work'
|
||
import {
|
||
linkedResolver,
|
||
relationshipResolver,
|
||
includeRelationships
|
||
} from '../resolvers'
|
||
|
||
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}`
|
||
})
|
||
}
|
||
|
||
export function fieldWithID (name, config = {}) {
|
||
config = {
|
||
type: GraphQLString,
|
||
resolve: getHyphenated,
|
||
...config
|
||
}
|
||
const isPlural = config.type instanceof GraphQLList
|
||
const singularName = isPlural ? toSingular(name) : name
|
||
const idName = isPlural ? `${singularName}IDs` : `${name}ID`
|
||
const idConfig = {
|
||
type: isPlural ? new GraphQLList(MBID) : MBID,
|
||
description: `The MBID${isPlural ? 's' : ''} associated with the
|
||
value${isPlural ? 's' : ''} of the \`${name}\` field.`,
|
||
resolve: getHyphenated
|
||
}
|
||
return {
|
||
[name]: config,
|
||
[idName]: idConfig
|
||
}
|
||
}
|
||
|
||
export function getHyphenated (source, args, context, info) {
|
||
const name = dashify(info.fieldName)
|
||
return source[name]
|
||
}
|
||
|
||
export function getFallback (keys) {
|
||
return (source) => {
|
||
for (let i = 0; i < keys.length; i++) {
|
||
const key = keys[i]
|
||
if (key in source) {
|
||
return source[key]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
export const id = globalIdField()
|
||
export const mbid = {
|
||
type: new GraphQLNonNull(MBID),
|
||
description: 'The MBID of the entity.',
|
||
resolve: source => source.id
|
||
}
|
||
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).`,
|
||
resolve: getHyphenated
|
||
}
|
||
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.`,
|
||
resolve: getHyphenated
|
||
}
|
||
|
||
function linkedQuery (connectionType, args) {
|
||
const typeName = toWords(connectionType.name.slice(0, -10))
|
||
return {
|
||
type: connectionType,
|
||
description: `A list of ${typeName} entities linked to this entity.`,
|
||
args: {
|
||
...forwardConnectionArgs,
|
||
...args
|
||
},
|
||
resolve: linkedResolver()
|
||
}
|
||
}
|
||
|
||
export const relationship = {
|
||
type: RelationshipConnection,
|
||
description: 'A list of relationships between these two entity types.',
|
||
args: {
|
||
...connectionArgs,
|
||
direction: {
|
||
type: GraphQLString,
|
||
description: 'Filter by the relationship direction.'
|
||
},
|
||
...fieldWithID('type', {
|
||
description: 'Filter by the relationship type.'
|
||
})
|
||
},
|
||
resolve: relationshipResolver()
|
||
}
|
||
|
||
export const relationships = {
|
||
type: new GraphQLObjectType({
|
||
name: 'Relationships',
|
||
description: 'Lists of entity relationships for each entity type.',
|
||
fields: () => ({
|
||
areas: relationship,
|
||
artists: relationship,
|
||
events: relationship,
|
||
instruments: relationship,
|
||
labels: relationship,
|
||
places: relationship,
|
||
recordings: relationship,
|
||
releases: relationship,
|
||
releaseGroups: relationship,
|
||
series: relationship,
|
||
urls: relationship,
|
||
works: relationship
|
||
})
|
||
}),
|
||
description: 'Relationships between this entity and other entitites.',
|
||
resolve: (source, args, { loaders }, info) => {
|
||
if (source.relations != null) {
|
||
return source.relations
|
||
}
|
||
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
|
||
})
|
||
}
|
||
}
|
||
|
||
export const artistCredit = {
|
||
type: new GraphQLList(ArtistCredit),
|
||
description: 'The main credited artist(s).',
|
||
resolve: (source, args, { loaders }, info) => {
|
||
const key = 'artist-credit'
|
||
if (key in source) {
|
||
return source[key]
|
||
} else {
|
||
const { entityType, id } = source
|
||
const params = { inc: ['artists'] }
|
||
return loaders.lookup.load([entityType, id, params]).then(entity => {
|
||
return entity[key]
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
export const artists = linkedQuery(ArtistConnection)
|
||
export const events = linkedQuery(EventConnection)
|
||
export const labels = linkedQuery(LabelConnection)
|
||
export const places = linkedQuery(PlaceConnection)
|
||
export const recordings = linkedQuery(RecordingConnection)
|
||
export const releases = linkedQuery(ReleaseConnection, {
|
||
type: { type: new GraphQLList(ReleaseGroupType) },
|
||
status: { type: new GraphQLList(ReleaseStatus) }
|
||
})
|
||
export const releaseGroups = linkedQuery(ReleaseGroupConnection, {
|
||
type: { type: new GraphQLList(ReleaseGroupType) }
|
||
})
|
||
export const works = linkedQuery(WorkConnection)
|