From 0f374b47b12f628b44045de85c7ba06f77e24e38 Mon Sep 17 00:00:00 2001 From: Alexandre Bodin Date: Mon, 11 Mar 2024 15:05:27 +0100 Subject: [PATCH] chore: cleanup i18n dead code --- .../src/services/__tests__/core-api.test.ts | 107 --------- .../i18n/server/src/services/core-api.ts | 224 ------------------ .../plugins/i18n/server/src/services/index.ts | 2 - .../plugins/i18n/server/src/utils/index.ts | 2 - 4 files changed, 335 deletions(-) delete mode 100644 packages/plugins/i18n/server/src/services/__tests__/core-api.test.ts delete mode 100644 packages/plugins/i18n/server/src/services/core-api.ts diff --git a/packages/plugins/i18n/server/src/services/__tests__/core-api.test.ts b/packages/plugins/i18n/server/src/services/__tests__/core-api.test.ts deleted file mode 100644 index d248b9f333..0000000000 --- a/packages/plugins/i18n/server/src/services/__tests__/core-api.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -import coreApiServiceFactory from '../core-api'; - -const { createSanitizer } = coreApiServiceFactory(); - -describe('Core API', () => { - describe('sanitizer', () => { - test('sanitizeInput keeps only writable fields', () => { - const contentType = { - attributes: { - title: { - type: 'string', - }, - nonWritables: { - type: 'string', - writable: false, - }, - }, - }; - - const { sanitizeInput } = createSanitizer(contentType); - - const input = { - title: 'test', - nonWritables: 'test', - }; - - const output = sanitizeInput(input); - - expect(output).toStrictEqual({ - title: 'test', - }); - }); - - test('sanitizeInput excludes locale & localizations', () => { - const contentType = { - attributes: { - title: { - type: 'string', - }, - nonWritables: { - type: 'string', - writable: false, - }, - locale: { - type: 'string', - writable: true, - }, - localizations: { - type: 'string', - writable: true, - }, - }, - }; - - const { sanitizeInput } = createSanitizer(contentType); - - const input = { - title: 'test', - nonWritables: 'test', - locale: 'FR', - localizations: [1, 2], - }; - - const output = sanitizeInput(input); - - expect(output).toStrictEqual({ - title: 'test', - }); - }); - - test('sanitizeInputFiles keeps only writable fields', () => { - const contentType = { - attributes: { - title: { - type: 'string', - }, - nonWritableCompo: { - type: 'component', - writable: false, - }, - writableCompo: { - type: 'component', - writable: true, - }, - image: { - model: 'file', - plugin: 'upload', - writable: false, - }, - }, - }; - - const { sanitizeInputFiles } = createSanitizer(contentType); - - const input = { - 'writableCompo.image': {}, - 'nonWritableCompo.image': {}, - }; - - const output = sanitizeInputFiles(input); - - expect(output).toStrictEqual({ - 'writableCompo.image': {}, - }); - }); - }); -}); diff --git a/packages/plugins/i18n/server/src/services/core-api.ts b/packages/plugins/i18n/server/src/services/core-api.ts deleted file mode 100644 index fe59ba83d7..0000000000 --- a/packages/plugins/i18n/server/src/services/core-api.ts +++ /dev/null @@ -1,224 +0,0 @@ -import _ from 'lodash'; -import { prop, pick, reduce, map, keys, toPath, isNil } from 'lodash/fp'; -import utils from '@strapi/utils'; -import { getService } from '../utils'; - -const { contentTypes, sanitize } = utils; -const { ApplicationError, NotFoundError } = utils.errors; - -const { isSingleType, getWritableAttributes } = contentTypes; - -/** - * Returns all locales for an entry - * @param {object} entry - * @returns {string[]} - */ -const getAllLocales = (entry: any) => { - return [entry.locale, ...map(prop('locale'), entry.localizations)]; -}; - -/** - * Returns all localizations ids for an entry - * @param {object} entry - * @returns {any[]} - */ -const getAllLocalizationsIds = (entry: any) => { - return [entry.id, ...map(prop('id'), entry.localizations)]; -}; - -/** - * Returns a sanitizer object with a data & a file sanitizer for a content type - * @param {object} contentType - * @returns {{ - * sanitizeInput(data: object): object, - * sanitizeInputFiles(files: object): object - * }} - */ -const createSanitizer = (contentType: any) => { - /** - * Returns the writable attributes of a content type in the localization routes - * @returns {string[]} - */ - const getAllowedAttributes = () => { - return getWritableAttributes(contentType).filter( - (attributeName) => !['locale', 'localizations'].includes(attributeName) - ); - }; - - /** - * Sanitizes uploaded files to keep only writable ones - * @param {object} files - input files to sanitize - * @returns {object} - */ - const sanitizeInputFiles = (files: any) => { - const allowedFields = getAllowedAttributes(); - return reduce( - (acc, keyPath) => { - const [rootKey] = toPath(keyPath); - if (allowedFields.includes(rootKey)) { - acc[keyPath] = files[keyPath]; - } - - return acc; - }, - {} as any, - keys(files) - ); - }; - - /** - * Sanitizes input data to keep only writable attributes - * @param {object} data - input data to sanitize - * @returns {object} - */ - const sanitizeInput = (data: any) => { - return pick(getAllowedAttributes(), data); - }; - - return { sanitizeInput, sanitizeInputFiles }; -}; - -const createCreateLocalizationHandler = - (contentType: any) => - async (args: any = {}) => { - const { copyNonLocalizedAttributes } = getService('content-types'); - - const { sanitizeInput } = createSanitizer(contentType); - - const entry = isSingleType(contentType) - ? await strapi.query(contentType.uid).findOne({ populate: ['localizations'] }) - : await strapi - .query(contentType.uid) - .findOne({ where: { id: args.id }, populate: ['localizations'] }); - - if (!entry) { - throw new NotFoundError(); - } - - const { data } = args; - - const { findByCode } = getService('locales'); - - if (isNil(data.locale)) { - throw new ApplicationError('locale is missing'); - } - - const matchingLocale = await findByCode(data.locale); - if (!matchingLocale) { - throw new ApplicationError('locale is invalid'); - } - - const usedLocales = getAllLocales(entry); - if (usedLocales.includes(data.locale)) { - throw new ApplicationError('locale is already used'); - } - - const sanitizedData = { - ...copyNonLocalizedAttributes(contentType, entry), - ...sanitizeInput(data), - locale: data.locale, - localizations: getAllLocalizationsIds(entry), - }; - - const newEntry = await strapi.entityService.create(contentType.uid, { - data: sanitizedData, - populate: ['localizations'], - }); - - return sanitize.contentAPI.output(newEntry, strapi.getModel(contentType.uid)); - }; - -const mergeCustomizer = (dest: any, src: any) => { - if (typeof dest === 'string') { - return `${dest}\n${src}`; - } -}; - -/** - * Add a graphql schema to the plugin's global graphl schema to be processed - * @param {object} schema - */ -const addGraphqlSchema = (schema: any) => { - _.mergeWith(strapi.config.get('plugin::i18n.schema.graphql'), schema, mergeCustomizer); -}; - -/** - * Add localization mutation & filters to use with the graphql plugin - * @param {object} contentType - */ -const addGraphqlLocalizationAction = (contentType: any) => { - const { globalId, modelName } = contentType; - - if (!strapi.plugins.graphql) { - return; - } - - const { toSingular, toPlural } = strapi.plugin('graphql').service('naming'); - - // We use a string instead of an enum as the locales can be changed in the admin - // NOTE: We could use a custom scalar so the validation becomes dynamic - const localeArgs = { - args: { - locale: 'String', - }, - }; - - // add locale arguments in the existing queries - if (isSingleType(contentType)) { - const queryName = toSingular(modelName); - const mutationSuffix = _.upperFirst(queryName); - - addGraphqlSchema({ - resolver: { - Query: { - [queryName]: localeArgs, - }, - Mutation: { - [`update${mutationSuffix}`]: localeArgs, - [`delete${mutationSuffix}`]: localeArgs, - }, - }, - }); - } else { - const queryName = toPlural(modelName); - - addGraphqlSchema({ - resolver: { - Query: { - [queryName]: localeArgs, - [`${queryName}Connection`]: localeArgs, - }, - }, - }); - } - - // add new mutation to create a localization - const typeName = globalId; - - const capitalizedName = _.upperFirst(toSingular(modelName)); - const mutationName = `create${capitalizedName}Localization`; - const mutationDef = `${mutationName}(input: update${capitalizedName}Input!): ${typeName}!`; - const actionName = `${contentType.uid}.createLocalization`; - - addGraphqlSchema({ - mutation: mutationDef, - resolver: { - Mutation: { - [mutationName]: { - resolver: actionName, - }, - }, - }, - }); -}; - -const coreApi = () => ({ - addGraphqlLocalizationAction, - createSanitizer, - createCreateLocalizationHandler, -}); - -type CoreApiService = typeof coreApi; - -export default coreApi; -export { CoreApiService }; diff --git a/packages/plugins/i18n/server/src/services/index.ts b/packages/plugins/i18n/server/src/services/index.ts index 23bbf14458..011eb0fd4c 100644 --- a/packages/plugins/i18n/server/src/services/index.ts +++ b/packages/plugins/i18n/server/src/services/index.ts @@ -4,7 +4,6 @@ import localizations from './localizations'; import locales from './locales'; import isoLocales from './iso-locales'; import entityServiceDecorator from './entity-service-decorator'; -import coreApi from './core-api'; import contentTypes from './content-types'; export default { @@ -14,6 +13,5 @@ export default { locales, 'iso-locales': isoLocales, 'entity-service-decorator': entityServiceDecorator, - 'core-api': coreApi, 'content-types': contentTypes, }; diff --git a/packages/plugins/i18n/server/src/utils/index.ts b/packages/plugins/i18n/server/src/utils/index.ts index a19a67b327..f4bc5a7125 100644 --- a/packages/plugins/i18n/server/src/utils/index.ts +++ b/packages/plugins/i18n/server/src/utils/index.ts @@ -3,7 +3,6 @@ import type { PermissionsService } from '../services/permissions'; import type { ContentTypesService } from '../services/content-types'; import type { MetricsService } from '../services/metrics'; import type { EntityServiceDecoratorService } from '../services/entity-service-decorator'; -import type { CoreApiService } from '../services/core-api'; import type { ISOLocalesService } from '../services/iso-locales'; import type { LocalizationsService } from '../services/localizations'; @@ -15,7 +14,6 @@ type S = { ['iso-locales']: ISOLocalesService; ['content-types']: ContentTypesService; ['entity-service-decorator']: EntityServiceDecoratorService; - ['core-api']: CoreApiService; }; const getCoreStore = () => {