101 lines
3.0 KiB
JavaScript

const _ = require('lodash');
const { getPluginService } = require('../utils/getPluginService');
const { isValidFindSlugParams } = require('../utils/isValidFindSlugParams');
const { hasRequiredModelScopes } = require('../utils/hasRequiredModelScopes');
const { sanitizeOutput } = require('../utils/sanitizeOutput');
const { ForbiddenError, ValidationError } = require('@strapi/utils').errors;
const getCustomTypes = (strapi, nexus) => {
const { naming } = getPluginService('utils', 'graphql');
const { toEntityResponse } = getPluginService('format', 'graphql').returnTypes;
const { modelsByUID } = getPluginService('settingsService').get();
const { getEntityResponseName } = naming;
// get all types required for findSlug query
let findSlugTypes = {
response: [],
};
_.forEach(strapi.contentTypes, (contentType, uid) => {
if (modelsByUID[uid]) {
findSlugTypes.response.push(getEntityResponseName(contentType));
}
});
// ensure we have at least one type before attempting to register
if (!findSlugTypes.response.length) {
return [];
}
// build custom union type based on defined models
const FindSlugResponse = nexus.unionType({
name: 'FindSlugResponse',
description: 'Union Type of all registered slug content types',
definition(t) {
t.members(...findSlugTypes.response);
},
resolveType: (ctx) => {
return getEntityResponseName(modelsByUID[ctx.info.resourceUID].contentType);
},
});
return [
FindSlugResponse,
nexus.extendType({
type: 'Query',
definition: (t) => {
t.field('findSlug', {
type: FindSlugResponse,
args: {
modelName: nexus.stringArg('The model name of the content type'),
slug: nexus.stringArg('The slug to query for'),
publicationState: nexus.stringArg('The publication state of the entry'),
},
resolve: async (_parent, args, ctx) => {
const { modelsByName } = getPluginService('settingsService').get();
const { modelName, slug, publicationState } = args;
const { auth } = ctx.state;
try {
isValidFindSlugParams({
modelName,
slug,
modelsByName,
publicationState,
});
} catch (error) {
throw new ValidationError(error.message);
}
const { uid, field, contentType } = modelsByName[modelName];
try {
await hasRequiredModelScopes(strapi, uid, auth);
} catch (error) {
throw new ForbiddenError();
}
// build query
let query = {
filters: {
[field]: slug,
},
};
// only return published entries by default if content type has draftAndPublish enabled
if (_.get(contentType, ['options', 'draftAndPublish'], false)) {
query.publicationState = publicationState || 'live';
}
const data = await getPluginService('slugService').findOne(uid, query);
const sanitizedEntity = await sanitizeOutput(data, contentType, auth);
return toEntityResponse(sanitizedEntity, { resourceUID: uid });
},
});
},
}),
];
};
module.exports = {
getCustomTypes,
};