mirror of
https://github.com/BradNut/graphbrainz
synced 2025-09-08 17:40:32 +00:00
* wip: Modernize dependencies, syntax, imports * Use final release of ava-nock v2 * Update Travis config * Remove Node 13 from test matrix * Replace errorClass with parseErrorMessage in subclasses * define exports, apply updated lint rules * Remove markdown eslint plugin * Update README * v9.0.0-beta.1 * Add gql tag to exports * v9.0.0-beta.2 * Bump ava-nock, add test * Update dataloader loadMany usage * Add modules note to README * Add retry option to got calls
156 lines
4.1 KiB
JavaScript
156 lines
4.1 KiB
JavaScript
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 {
|
||
globalIdField,
|
||
connectionDefinitions,
|
||
forwardConnectionArgs,
|
||
} = GraphQLRelay;
|
||
|
||
const TYPE_NAMES = {
|
||
discid: 'Disc',
|
||
url: 'URL',
|
||
};
|
||
|
||
export function resolveType(value, context, info) {
|
||
const typeName = TYPE_NAMES[value._type] || toPascal(value._type);
|
||
const typeMap = info.schema.getTypeMap();
|
||
return typeMap[typeName];
|
||
}
|
||
|
||
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 = {}) {
|
||
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' : '';
|
||
const idConfig = {
|
||
type: isPlural ? new GraphQLList(MBID) : MBID,
|
||
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]);
|
||
},
|
||
};
|
||
return {
|
||
[name]: config,
|
||
[idName]: idConfig,
|
||
};
|
||
}
|
||
|
||
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();
|
||
export const mbid = {
|
||
type: new GraphQLNonNull(MBID),
|
||
description: 'The MBID of the entity.',
|
||
resolve: (entity) => entity.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: resolveHyphenated,
|
||
};
|
||
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 function linkedQuery(connectionType, { args, ...config } = {}) {
|
||
const typeName = toPlural(toWords(connectionType.name.slice(0, -10)));
|
||
return {
|
||
type: connectionType,
|
||
description: `A list of ${typeName} linked to this entity.`,
|
||
args: {
|
||
...args,
|
||
...forwardConnectionArgs,
|
||
},
|
||
resolve: resolveLinked,
|
||
...config,
|
||
};
|
||
}
|
||
|
||
export const totalCount = {
|
||
type: GraphQLInt,
|
||
description: `A count of the total number of items in this connection,
|
||
ignoring pagination.`,
|
||
};
|
||
|
||
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) {
|
||
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.',
|
||
};
|