'use strict'; const { camelCase, upperFirst, lowerFirst, pipe, get } = require('lodash/fp'); const { singular } = require('pluralize'); module.exports = ({ strapi }) => { /** * Build a type name for a enum based on a content type & an attribute name * @param {object} contentType * @param {string} attributeName * @return {string} */ const getEnumName = (contentType, attributeName) => { const { attributes } = contentType; const { enumName } = attributes[attributeName]; const { modelType } = contentType; const typeName = modelType === 'component' ? getComponentName(contentType) : getTypeName(contentType); const defaultEnumName = `ENUM_${typeName.toUpperCase()}_${attributeName.toUpperCase()}`; return enumName || defaultEnumName; }; /** * Build the base type name for a given content type * @param {object} contentType * @param {object} options * @param {'singular' | 'plural'} options.plurality * @return {string} */ const getTypeName = (contentType, { plurality = 'singular' } = {}) => { const plugin = get('plugin', contentType); const modelName = get('modelName', contentType); const name = plurality === 'singular' ? get('info.singularName', contentType) : get('info.pluralName', contentType); const transformedPlugin = upperFirst(camelCase(plugin)); const transformedModelName = upperFirst(camelCase(name || singular(modelName))); return `${transformedPlugin}${transformedModelName}`; }; /** * Build the entity's type name for a given content type * @param {object} contentType * @return {string} */ const getEntityName = contentType => { return `${getTypeName(contentType)}Entity`; }; /** * Build the entity meta type name for a given content type * @param {object} contentType * @return {string} */ const getEntityMetaName = contentType => { return `${getEntityName(contentType)}Meta`; }; /** * Build the entity response's type name for a given content type * @param {object} contentType * @return {string} */ const getEntityResponseName = contentType => { return `${getEntityName(contentType)}Response`; }; /** * Build the entity response collection's type name for a given content type * @param {object} contentType * @return {string} */ const getEntityResponseCollectionName = contentType => { return `${getEntityName(contentType)}ResponseCollection`; }; /** * Build the relation response collection's type name for a given content type * @param {object} contentType * @return {string} */ const getRelationResponseCollectionName = contentType => { return `${getTypeName(contentType)}RelationResponseCollection`; }; /** * Build a component type name based on its definition * @param {object} contentType * @return {string} */ const getComponentName = contentType => { return contentType.globalId; }; /** * Build a component type name based on a content type's attribute * @param {object} attribute * @return {string} */ const getComponentNameFromAttribute = attribute => { return strapi.components[attribute.component].globalId; }; /** * Build a dynamic zone type name based on a content type and an attribute name * @param {object} contentType * @param {string} attributeName * @return {string} */ const getDynamicZoneName = (contentType, attributeName) => { const typeName = getTypeName(contentType); const dzName = upperFirst(camelCase(attributeName)); const suffix = 'DynamicZone'; return `${typeName}${dzName}${suffix}`; }; /** * Build a dynamic zone input type name based on a content type and an attribute name * @param {object} contentType * @param {string} attributeName * @return {string} */ const getDynamicZoneInputName = (contentType, attributeName) => { const dzName = getDynamicZoneName(contentType, attributeName); return `${dzName}Input`; }; /** * Build a component input type name based on a content type and an attribute name * @param {object} contentType * @return {string} */ const getComponentInputName = contentType => { const componentName = getComponentName(contentType); return `${componentName}Input`; }; /** * Build a content type input name based on a content type and an attribute name * @param {object} contentType * @return {string} */ const getContentTypeInputName = contentType => { const typeName = getTypeName(contentType); return `${typeName}Input`; }; /** * Build the queries type name for a given content type * @param {object} contentType * @return {string} */ const getEntityQueriesTypeName = contentType => { return `${getEntityName(contentType)}Queries`; }; /** * Build the mutations type name for a given content type * @param {object} contentType * @return {string} */ const getEntityMutationsTypeName = contentType => { return `${getEntityName(contentType)}Mutations`; }; /** * Build the filters type name for a given content type * @param {object} contentType * @return {string} */ const getFiltersInputTypeName = contentType => { const isComponent = contentType.modelType === 'component'; const baseName = isComponent ? getComponentName(contentType) : getTypeName(contentType); return `${baseName}FiltersInput`; }; /** * Build a filters type name for a given GraphQL scalar type * @param {NexusGenScalars} scalarType * @return {string} */ const getScalarFilterInputTypeName = scalarType => { return `${scalarType}FilterInput`; }; /** * Build a type name for a given content type & polymorphic attribute * @param {object} contentType * @param {string} attributeName * @return {string} */ const getMorphRelationTypeName = (contentType, attributeName) => { const typeName = getTypeName(contentType); const formattedAttr = upperFirst(camelCase(attributeName)); return `${typeName}${formattedAttr}Morph`; }; /** * Build a custom type name generator with different customization options * @param {object} options * @param {string} [options.prefix] * @param {string} [options.suffix] * @param {'upper' | 'lower'} [options.firstLetterCase] * @param {'plural' | 'singular'} [options.plurality] * @return {function(*=): string} */ const buildCustomTypeNameGenerator = (options = {}) => { // todo[v4]: use singularName & pluralName is available const { prefix = '', suffix = '', plurality = 'singular', firstLetterCase = 'upper' } = options; if (!['plural', 'singular'].includes(plurality)) { throw new Error( `"plurality" param must be either "plural" or "singular", but got: "${plurality}"` ); } const getCustomTypeName = pipe( ct => getTypeName(ct, { plurality }), firstLetterCase === 'upper' ? upperFirst : lowerFirst ); return contentType => `${prefix}${getCustomTypeName(contentType)}${suffix}`; }; const getFindQueryName = buildCustomTypeNameGenerator({ plurality: 'plural', firstLetterCase: 'lower', }); const getFindOneQueryName = buildCustomTypeNameGenerator({ firstLetterCase: 'lower' }); const getCreateMutationTypeName = buildCustomTypeNameGenerator({ prefix: 'create', firstLetterCase: 'upper', }); const getUpdateMutationTypeName = buildCustomTypeNameGenerator({ prefix: 'update', firstLetterCase: 'upper', }); const getDeleteMutationTypeName = buildCustomTypeNameGenerator({ prefix: 'delete', firstLetterCase: 'upper', }); return { getEnumName, getTypeName, getEntityName, getEntityMetaName, getEntityResponseName, getEntityResponseCollectionName, getRelationResponseCollectionName, getComponentName, getComponentNameFromAttribute, getDynamicZoneName, getDynamicZoneInputName, getComponentInputName, getContentTypeInputName, getEntityQueriesTypeName, getEntityMutationsTypeName, getFiltersInputTypeName, getScalarFilterInputTypeName, getMorphRelationTypeName, buildCustomTypeNameGenerator, getFindQueryName, getFindOneQueryName, getCreateMutationTypeName, getUpdateMutationTypeName, getDeleteMutationTypeName, }; };