graphbrainz/src/types/helpers.js

157 lines
4.1 KiB
JavaScript
Raw Normal View History

import GraphQL from 'graphql';
import GraphQLRelay from 'graphql-relay';
import { MBID } from './scalars.js';
import { ReleaseGroupType, ReleaseStatus } from './enums.js';
import { resolveLinked } from '../resolvers.js';
import { toDashed, toPascal, toSingular, toPlural, toWords } from '../util.js';
const { GraphQLString, GraphQLInt, GraphQLList, GraphQLNonNull } = GraphQL;
const {
2016-09-01 08:39:27 +00:00
globalIdField,
connectionDefinitions,
forwardConnectionArgs,
} = GraphQLRelay;
2016-08-20 05:59:32 +00:00
const TYPE_NAMES = {
discid: 'Disc',
url: 'URL',
};
2016-11-26 01:38:32 +00:00
export function resolveType(value, context, info) {
const typeName = TYPE_NAMES[value._type] || toPascal(value._type);
const typeMap = info.schema.getTypeMap();
return typeMap[typeName];
2016-11-26 01:38:32 +00:00
}
2016-08-31 06:33:29 +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];
}
}
};
}
export function fieldWithID(name, config = {}) {
2016-08-08 07:54:06 +00:00
config = {
type: GraphQLString,
resolve: resolveHyphenated,
...config,
};
const isPlural = config.type instanceof GraphQLList;
const singularName = isPlural ? toSingular(name) : name;
const idName = isPlural ? `${singularName}IDs` : `${name}ID`;
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.`,
resolve: (entity, args, { loaders }) => {
const fieldName = toDashed(idName);
if (fieldName in entity) {
return entity[fieldName];
}
return loaders.lookup
.load([entity._type, entity.id])
.then((data) => data[fieldName]);
},
};
2016-08-08 07:54:06 +00:00
return {
[name]: config,
[idName]: idConfig,
};
2016-08-08 07:54:06 +00:00
}
export function createCollectionField(config) {
const typeName = toPlural(toWords(config.type.name.slice(0, -10)));
return {
...config,
description: `The list of ${typeName} found in this collection.`,
};
}
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.',
resolve: (entity) => entity.id,
};
2016-11-26 01:38:32 +00:00
export const name = {
type: GraphQLString,
description: 'The official name of the entity.',
};
2016-11-26 01:38:32 +00:00
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 persons last name to
the front).`,
resolve: resolveHyphenated,
};
2016-11-26 01:38:32 +00:00
export const title = {
type: GraphQLString,
description: 'The official title of the entity.',
};
2016-11-26 01:38:32 +00:00
export const disambiguation = {
type: GraphQLString,
description:
'A comment used to help distinguish identically named entitites.',
};
2016-08-20 05:59:32 +00:00
export 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,
description: `A list of ${typeName} linked to this entity.`,
2016-09-01 08:39:27 +00:00
args: {
...args,
...forwardConnectionArgs,
2016-09-01 08:39:27 +00:00
},
resolve: resolveLinked,
...config,
};
}
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 (0100) assigned by the search engine, if
these results were found through a search.`,
};
2016-11-28 14:43:32 +00:00
export function connectionWithExtras(nodeType) {
return connectionDefinitions({
nodeType,
connectionFields: () => ({
nodes: {
type: new GraphQLList(nodeType),
description: `A list of nodes in the connection (without going through the
\`edges\` field).`,
},
totalCount,
}),
edgeFields: () => ({ score }),
}).connectionType;
}
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.',
};