From 5e5bcf8c8fcefef0db969ea48cdc7b89f346db0d Mon Sep 17 00:00:00 2001 From: Alexandre Bodin Date: Thu, 4 Apr 2024 22:37:55 +0200 Subject: [PATCH] chore: improve middleware api --- .../server/src/history/services/history.ts | 13 +-- .../src/services/document-service/common.ts | 6 +- .../src/services/document-service/index.ts | 6 +- .../middlewares/middleware-manager.ts | 2 +- .../types/src/modules/documents/middleware.ts | 28 +++--- .../src/modules/documents/service-instance.ts | 87 ++++++++++--------- 6 files changed, 76 insertions(+), 66 deletions(-) diff --git a/packages/core/content-manager/server/src/history/services/history.ts b/packages/core/content-manager/server/src/history/services/history.ts index 4c76729bb7..69c3ba8956 100644 --- a/packages/core/content-manager/server/src/history/services/history.ts +++ b/packages/core/content-manager/server/src/history/services/history.ts @@ -137,9 +137,13 @@ const createHistoryService = ({ strapi }: { strapi: Core.Strapi }) => { return next(); } - // Ignore actions that don't mutate documents + // NOTE: can do type narrowing with array includes if ( - !['create', 'update', 'publish', 'unpublish', 'discardDraft'].includes(context.action) + context.action !== 'create' && + context.action !== 'update' && + context.action !== 'publish' && + context.action !== 'unpublish' && + context.action !== 'discardDraft' ) { return next(); } @@ -154,9 +158,8 @@ const createHistoryService = ({ strapi }: { strapi: Core.Strapi }) => { const documentContext = context.action === 'create' - ? // @ts-expect-error The context args are not typed correctly - { documentId: result.documentId, locale: context.args[0]?.locale } - : { documentId: context.args[0], locale: context.args[1]?.locale }; + ? { documentId: result.documentId, locale: context.params?.locale } + : { documentId: context.params.documentId, locale: context.params?.locale }; const locale = documentContext.locale ?? (await localesService.getDefaultLocale()); const document = await strapi.documents(contentTypeUid).findOne({ diff --git a/packages/core/core/src/services/document-service/common.ts b/packages/core/core/src/services/document-service/common.ts index a150484396..5ccfc49363 100644 --- a/packages/core/core/src/services/document-service/common.ts +++ b/packages/core/core/src/services/document-service/common.ts @@ -1,8 +1,8 @@ import type { UID, Modules } from '@strapi/types'; -export type RepositoryFactoryMethod = ( - uid: TCollectionTypeUID -) => Modules.Documents.ServiceInstance; +export type RepositoryFactoryMethod = ( + uid: TContentTypeUID +) => Modules.Documents.ServiceInstance; export const wrapInTransaction = (fn: (...args: any) => any) => { return (...args: any[]) => strapi.db.transaction?.(() => fn(...args)); diff --git a/packages/core/core/src/services/document-service/index.ts b/packages/core/core/src/services/document-service/index.ts index 9385ad6931..85ab0d82fa 100644 --- a/packages/core/core/src/services/document-service/index.ts +++ b/packages/core/core/src/services/document-service/index.ts @@ -1,4 +1,4 @@ -import type { Core, Modules } from '@strapi/types'; +import type { Core, Modules, UID } from '@strapi/types'; import { createMiddlewareManager, databaseErrorsMiddleware } from './middlewares'; import { createContentTypeRepository } from './repository'; @@ -24,7 +24,7 @@ export const createDocumentService = (strapi: Core.Strapi): Modules.Documents.Se middlewares.use(databaseErrorsMiddleware); - const factory = function factory(uid) { + const factory = function factory(uid: UID.ContentType) { if (repositories.has(uid)) { return repositories.get(uid)!; } @@ -32,7 +32,7 @@ export const createDocumentService = (strapi: Core.Strapi): Modules.Documents.Se const contentType = strapi.contentType(uid); const repository = createContentTypeRepository(uid); - repositories.set(uid, middlewares.wrapObject(repository, { contentType })); + repositories.set(uid, middlewares.wrapObject(repository, { uid, contentType })); return repository; } as Modules.Documents.Service; diff --git a/packages/core/core/src/services/document-service/middlewares/middleware-manager.ts b/packages/core/core/src/services/document-service/middlewares/middleware-manager.ts index c7ce6027cb..39249d336b 100644 --- a/packages/core/core/src/services/document-service/middlewares/middleware-manager.ts +++ b/packages/core/core/src/services/document-service/middlewares/middleware-manager.ts @@ -24,7 +24,7 @@ export const createMiddlewareManager = () => { return next(); }, - wrapObject>(source: TSource, ctxDefaults = {}): TSource { + wrapObject(source: TSource, ctxDefaults = {}): TSource { const facade: TSource = {} as TSource; for (const key in source) { diff --git a/packages/core/types/src/modules/documents/middleware.ts b/packages/core/types/src/modules/documents/middleware.ts index 6b92cd5675..128b6e7b8d 100644 --- a/packages/core/types/src/modules/documents/middleware.ts +++ b/packages/core/types/src/modules/documents/middleware.ts @@ -1,19 +1,19 @@ // Utility type to reuse Param definition in MiddlewareContext -import type { Schema } from '../..'; -import type { ServiceInstance } from './service-instance'; +import type { Schema, UID } from '../..'; +import type { ServiceInstance, ServiceParams } from './service-instance'; -export interface Context< - TAction extends keyof ServiceInstance = keyof ServiceInstance, - TArgs = Parameters, -> { - contentType: Schema.ContentType; - action: TAction; - args: TArgs; -} +export type Context = { + [TUIDKey in TUID]: { + [TKey in keyof ServiceParams]: { + contentType: Schema.ContentType; + uid: TUIDKey; + action: TKey; + params: ServiceParams[TKey]; + }; + }[keyof ServiceParams]; +}[TUID]; export type Middleware = ( ctx: Context, - next: () => Promise> -) => - | ReturnType - | Promise>; + next: () => ReturnType +) => ReturnType; diff --git a/packages/core/types/src/modules/documents/service-instance.ts b/packages/core/types/src/modules/documents/service-instance.ts index 776d38966a..b15d797266 100644 --- a/packages/core/types/src/modules/documents/service-instance.ts +++ b/packages/core/types/src/modules/documents/service-instance.ts @@ -8,6 +8,34 @@ import type { IsDraftAndPublishEnabled } from './draft-and-publish'; import type * as Params from './params/document-engine'; import type * as Result from './result/document-engine'; +export type ServiceParams = { + findMany: Params.FindMany; + findFirst: Params.FindFirst; + findOne: Params.FindOne; + delete: Params.Delete; + create: Params.Create; + clone: Params.Clone; + update: Params.Update; + count: Params.Count; + publish: Params.Publish; + unpublish: Params.Unpublish; + discardDraft: Params.DiscardDraft; +}; + +export type ServiceResults = { + findMany: Result.FindMany>; + findFirst: Result.FindFirst>; + findOne: Result.FindOne>; + delete: Result.Delete; + create: Result.Create>; + clone: Result.Clone>; + update: Result.Update>; + count: Result.Count; + publish: Result.Publish>; + unpublish: Result.Unpublish>; + discardDraft: Result.DiscardDraft>; +}; + // TODO: move to common place type ComponentBody = { [key: string]: AttributeUtils.GetValue< @@ -17,65 +45,44 @@ type ComponentBody = { >; }; -export type ServiceInstance = { - findMany: >( - params?: TParams - ) => Result.FindMany; - - findFirst: >( - params?: TParams - ) => Result.FindFirst; - - findOne: >( - params: TParams - ) => Result.FindOne; - - delete: >(params: TParams) => Result.Delete; - - create: >( - params: TParams - ) => Result.Create; +export type ServiceInstance< + TContentTypeUID extends UID.ContentType = UID.ContentType, + TServiceParams extends ServiceParams = ServiceParams, + TServiceResults extends ServiceResults = ServiceResults, +> = { + findMany: (params?: TServiceParams['findMany']) => TServiceResults['findMany']; + findFirst: (params?: TServiceParams['findFirst']) => TServiceResults['findFirst']; + findOne: (params: TServiceParams['findOne']) => TServiceResults['findOne']; + delete: (params: TServiceParams['delete']) => TServiceResults['delete']; + create: (params: TServiceParams['create']) => TServiceResults['create']; /** * @internal - * Exposed for use within the Strapi Admin Panel */ - clone: >( - params: TParams - ) => Result.Clone; - - update: >( - params: TParams - ) => Result.Update; - - count: >(params?: TParams) => Result.Count; + clone: (params: TServiceParams['clone']) => TServiceResults['clone']; + update: (params: TServiceParams['update']) => TServiceResults['update']; + count: (params?: TServiceParams['count']) => TServiceResults['count']; // Publication methods are only enabled if D&P is enabled for the content type publish: Utils.If< // If draft and publish is enabled for the content type IsDraftAndPublishEnabled, // Then, publish method is enabled - >( - params: TParams - ) => Result.Publish, + (params: TServiceParams['publish']) => TServiceResults['publish'], // Otherwise, disable it - undefined + never >; unpublish: Utils.If< IsDraftAndPublishEnabled, - >( - params: TParams - ) => Result.Unpublish, - undefined + (params: TServiceParams['unpublish']) => TServiceResults['unpublish'], + never >; discardDraft: Utils.If< IsDraftAndPublishEnabled, - >( - params: TParams - ) => Result.DiscardDraft, - undefined + (params: TServiceParams['discardDraft']) => TServiceResults['discardDraft'], + never >; /**