From 130c641e5c91cf831de64fb87aebbfdc4d23530d Mon Sep 17 00:00:00 2001 From: Adrien de Peretti Date: Thu, 18 Jan 2024 10:20:08 +0100 Subject: [PATCH] chore: Abstract module services (#6087) **What** Create a service abstraction for the modules internal service layer. The objective is to reduce the effort of building new modules when the logic is the same or otherwise allow to override the default behavior. Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com> --- .changeset/twenty-emus-roll.md | 8 + .../src/repositories/auth-provider.ts | 18 +- .../src/repositories/auth-user.ts | 42 +-- .../src/services/auth-provider.ts | 139 +--------- .../authentication/src/services/auth-user.ts | 129 +-------- packages/cart/src/repositories/cart.ts | 20 +- packages/cart/src/services/address.ts | 134 +--------- packages/cart/src/services/cart.ts | 131 +--------- packages/cart/src/services/line-item.ts | 130 +--------- .../src/services/__fixtures__/currency.ts | 8 + packages/pricing/src/services/currency.ts | 109 +------- packages/pricing/src/services/money-amount.ts | 123 ++------- .../src/services/price-list-rule-value.ts | 119 ++------- .../pricing/src/services/price-list-rule.ts | 107 ++------ packages/pricing/src/services/price-list.ts | 105 ++------ packages/pricing/src/services/price-rule.ts | 103 ++------ .../services/price-set-money-amount-rules.ts | 109 +------- .../src/services/price-set-money-amount.ts | 101 ++------ .../src/services/price-set-rule-type.ts | 99 ++----- packages/pricing/src/services/price-set.ts | 103 ++------ packages/pricing/src/services/rule-type.ts | 84 ++---- packages/product/jest.config.js | 1 + packages/product/src/repositories/product.ts | 28 +- .../product/src/services/product-category.ts | 2 +- .../src/services/product-collection.ts | 104 +++----- .../product/src/services/product-image.ts | 4 +- .../src/services/product-module-service.ts | 62 ++--- .../src/services/product-option-value.ts | 24 +- .../product/src/services/product-option.ts | 97 ++----- packages/product/src/services/product-tag.ts | 98 ++----- packages/product/src/services/product-type.ts | 100 ++----- .../product/src/services/product-variant.ts | 119 ++------- packages/product/src/services/product.ts | 161 ++---------- packages/product/src/types/services/index.ts | 1 + packages/product/tsconfig.json | 3 +- .../src/services/application-method.ts | 113 ++------ .../promotion/src/services/campaign-budget.ts | 108 ++------ packages/promotion/src/services/campaign.ts | 103 ++------ .../src/services/promotion-rule-value.ts | 108 ++------ .../promotion/src/services/promotion-rule.ts | 108 ++------ packages/promotion/src/services/promotion.ts | 103 ++------ packages/types/src/dal/repository-service.ts | 6 +- .../src/dal/mikro-orm/mikro-orm-repository.ts | 19 +- .../modules-sdk/abstract-service-factory.ts | 245 ++++++++++++++++++ packages/utils/src/modules-sdk/index.ts | 2 +- .../utils/src/modules-sdk/retrieve-entity.ts | 53 ---- 46 files changed, 857 insertions(+), 2836 deletions(-) create mode 100644 .changeset/twenty-emus-roll.md create mode 100644 packages/utils/src/modules-sdk/abstract-service-factory.ts delete mode 100644 packages/utils/src/modules-sdk/retrieve-entity.ts diff --git a/.changeset/twenty-emus-roll.md b/.changeset/twenty-emus-roll.md new file mode 100644 index 0000000000..561ea8d3aa --- /dev/null +++ b/.changeset/twenty-emus-roll.md @@ -0,0 +1,8 @@ +--- +"@medusajs/pricing": patch +"@medusajs/product": patch +"@medusajs/utils": patch +"@medusajs/types": patch +--- + +chore: Abstract module services diff --git a/packages/authentication/src/repositories/auth-provider.ts b/packages/authentication/src/repositories/auth-provider.ts index 6445266d14..6246ead8c6 100644 --- a/packages/authentication/src/repositories/auth-provider.ts +++ b/packages/authentication/src/repositories/auth-provider.ts @@ -2,32 +2,16 @@ import { DALUtils } from "@medusajs/utils" import { AuthProvider } from "@models" import { RepositoryTypes } from "@types" -import { SqlEntityManager } from "@mikro-orm/postgresql" -import { Context } from "@medusajs/types" export class AuthProviderRepository extends DALUtils.mikroOrmBaseRepositoryFactory< AuthProvider, { create: RepositoryTypes.CreateAuthProviderDTO + update: RepositoryTypes.UpdateAuthProviderDTO } >(AuthProvider) { constructor(...args: any[]) { // @ts-ignore super(...arguments) } - - async update( - data: RepositoryTypes.UpdateAuthProviderDTO[], - context: Context = {} - ): Promise { - const manager = this.getActiveManager(context) - - const authProviders = data.map(({ provider, update }) => { - return manager.assign(provider, update) - }) - - manager.persist(authProviders) - - return authProviders - } } diff --git a/packages/authentication/src/repositories/auth-user.ts b/packages/authentication/src/repositories/auth-user.ts index 6e5fa10f9c..a5b47652f0 100644 --- a/packages/authentication/src/repositories/auth-user.ts +++ b/packages/authentication/src/repositories/auth-user.ts @@ -1,45 +1,17 @@ -import { Context } from "@medusajs/types" import { DALUtils } from "@medusajs/utils" import { AuthUser } from "@models" import { RepositoryTypes } from "@types" -import { SqlEntityManager } from "@mikro-orm/postgresql" -export class AuthUserRepository extends DALUtils.mikroOrmBaseRepositoryFactory( - AuthUser -) { +export class AuthUserRepository extends DALUtils.mikroOrmBaseRepositoryFactory< + AuthUser, + { + create: RepositoryTypes.CreateAuthUserDTO + update: RepositoryTypes.UpdateAuthUserDTO + } +>(AuthUser) { constructor(...args: any[]) { // @ts-ignore super(...arguments) } - - async create( - data: RepositoryTypes.CreateAuthUserDTO[], - context: Context = {} - ): Promise { - const toCreate = data.map((authUser) => { - const authUserClone = { ...authUser } as any - - authUserClone.provider ??= authUser.provider_id - - return authUserClone - }) - - return await super.create(toCreate, context) - } - - async update( - data: RepositoryTypes.UpdateAuthUserDTO[], - context: Context = {} - ): Promise { - const manager = this.getActiveManager(context) - - const authUsers = data.map(({ user, update }) => { - return manager.assign(user, update) - }) - - manager.persist(authUsers) - - return authUsers - } } diff --git a/packages/authentication/src/services/auth-provider.ts b/packages/authentication/src/services/auth-provider.ts index ee6ccd8b86..241fb56e80 100644 --- a/packages/authentication/src/services/auth-provider.ts +++ b/packages/authentication/src/services/auth-provider.ts @@ -1,16 +1,8 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - MedusaError, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { AuthProvider } from "@models" -import { AuthProviderRepository } from "@repositories" -import { RepositoryTypes, ServiceTypes } from "@types" +import { ServiceTypes } from "@types" type InjectedDependencies = { authProviderRepository: DAL.RepositoryService @@ -18,122 +10,15 @@ type InjectedDependencies = { export default class AuthProviderService< TEntity extends AuthProvider = AuthProvider -> { - protected readonly authProviderRepository_: DAL.RepositoryService - - constructor({ authProviderRepository }: InjectedDependencies) { - this.authProviderRepository_ = authProviderRepository +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreateAuthProviderDTO + update: ServiceTypes.UpdateAuthProviderDTO } - - @InjectManager("authProviderRepository_") - async retrieve( - provider: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: provider, - identifierColumn: "provider", - entityName: AuthProvider.name, - repository: this.authProviderRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("authProviderRepository_") - async list( - filters: ServiceTypes.FilterableAuthProviderProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryConfig = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.authProviderRepository_.find( - queryConfig, - sharedContext - )) as TEntity[] - } - - @InjectManager("authProviderRepository_") - async listAndCount( - filters: ServiceTypes.FilterableAuthProviderProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryConfig = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.authProviderRepository_.findAndCount( - queryConfig, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("authProviderRepository_") - async create( - data: ServiceTypes.CreateAuthProviderDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.authProviderRepository_ as AuthProviderRepository - ).create(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("authProviderRepository_") - async update( - data: ServiceTypes.UpdateAuthProviderDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - const authProviderIds = data.map( - (authProviderData) => authProviderData.provider - ) - - const existingAuthProviders = await this.list( - { - provider: authProviderIds, - }, - {}, - sharedContext - ) - - const updates: RepositoryTypes.UpdateAuthProviderDTO[] = [] - - const existingAuthProvidersMap = new Map( - existingAuthProviders.map<[string, AuthProvider]>((authProvider) => [ - authProvider.provider, - authProvider, - ]) - ) - - for (const update of data) { - const provider = existingAuthProvidersMap.get(update.provider) - - if (!provider) { - throw new MedusaError( - MedusaError.Types.NOT_FOUND, - `AuthProvider with provider "${update.provider}" not found` - ) - } - - updates.push({ update, provider }) - } - - return (await ( - this.authProviderRepository_ as AuthProviderRepository - ).update(updates, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("authProviderRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.authProviderRepository_.delete(ids, sharedContext) +>(AuthProvider) { + constructor(container: InjectedDependencies) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/authentication/src/services/auth-user.ts b/packages/authentication/src/services/auth-user.ts index a7573852b7..6cb6336ebe 100644 --- a/packages/authentication/src/services/auth-user.ts +++ b/packages/authentication/src/services/auth-user.ts @@ -1,126 +1,23 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - MedusaError, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { AuthUser } from "@models" -import { AuthUserRepository } from "@repositories" -import { RepositoryTypes, ServiceTypes } from "@types" +import { ServiceTypes } from "@types" type InjectedDependencies = { authUserRepository: DAL.RepositoryService } -export default class AuthUserService { - protected readonly authUserRepository_: DAL.RepositoryService - +export default class AuthUserService< + TEntity extends AuthUser = AuthUser +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreateAuthUserDTO + } +>(AuthUser) { constructor({ authUserRepository }: InjectedDependencies) { - this.authUserRepository_ = authUserRepository - } - - @InjectManager("authUserRepository_") - async retrieve( - provider: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: provider, - entityName: AuthUser.name, - repository: this.authUserRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("authUserRepository_") - async list( - filters: ServiceTypes.FilterableAuthProviderProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryConfig = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.authUserRepository_.find( - queryConfig, - sharedContext - )) as TEntity[] - } - - @InjectManager("authUserRepository_") - async listAndCount( - filters: ServiceTypes.FilterableAuthUserProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryConfig = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.authUserRepository_.findAndCount( - queryConfig, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("authUserRepository_") - async create( - data: ServiceTypes.CreateAuthUserDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.authUserRepository_ as AuthUserRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("authUserRepository_") - async update( - data: ServiceTypes.UpdateAuthUserDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - const existingUsers = await this.list( - { id: data.map(({ id }) => id) }, - {}, - sharedContext - ) - - const existingUsersMap = new Map( - existingUsers.map<[string, AuthUser]>((authUser) => [ - authUser.id, - authUser, - ]) - ) - - const updates: RepositoryTypes.UpdateAuthUserDTO[] = [] - - for (const update of data) { - const user = existingUsersMap.get(update.id) - - if (!user) { - throw new MedusaError( - MedusaError.Types.NOT_FOUND, - `AuthUser with id "${update.id}" not found` - ) - } - - updates.push({ update, user }) - } - - return (await (this.authUserRepository_ as AuthUserRepository).update( - updates, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("authUserRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.authUserRepository_.delete(ids, sharedContext) + // @ts-ignore + super(...arguments) } } diff --git a/packages/cart/src/repositories/cart.ts b/packages/cart/src/repositories/cart.ts index 952fc9fd1b..577d826786 100644 --- a/packages/cart/src/repositories/cart.ts +++ b/packages/cart/src/repositories/cart.ts @@ -1,32 +1,16 @@ -import { Context } from "@medusajs/types" import { DALUtils } from "@medusajs/utils" -import { SqlEntityManager } from "@mikro-orm/postgresql" import { Cart } from "@models" -import { CreateCartDTO, UpdateCartDTO } from "../types" +import { CreateCartDTO, UpdateCartDTO } from "@types" export class CartRepository extends DALUtils.mikroOrmBaseRepositoryFactory< Cart, { create: CreateCartDTO + update: UpdateCartDTO } >(Cart) { constructor(...args: any[]) { // @ts-ignore super(...arguments) } - - async update( - data: { cart: Cart; update: UpdateCartDTO }[], - context: Context = {} - ): Promise { - const manager = this.getActiveManager(context) - - const entities = data.map(({ cart, update }) => { - return manager.assign(cart, update) - }) - - manager.persist(entities) - - return entities - } } diff --git a/packages/cart/src/services/address.ts b/packages/cart/src/services/address.ts index 0e4e17d2cf..383a07707b 100644 --- a/packages/cart/src/services/address.ts +++ b/packages/cart/src/services/address.ts @@ -1,129 +1,23 @@ -import { - AddressDTO, - CartAddressDTO, - Context, - DAL, - FilterableAddressProps, - FindConfig, -} from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - MedusaError, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { Address } from "@models" -import { AddressRepository } from "../repositories/address" -import { CreateAddressDTO, UpdateAddressDTO } from "../types" +import { CreateAddressDTO, UpdateAddressDTO } from "@types" type InjectedDependencies = { addressRepository: DAL.RepositoryService } -export default class AddressService { - protected readonly addressRepository_: DAL.RepositoryService - - constructor({ addressRepository }: InjectedDependencies) { - this.addressRepository_ = addressRepository +export default class AddressService< + TEntity extends Address = Address +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: CreateAddressDTO + update: UpdateAddressDTO } - - @InjectManager("addressRepository_") - async retrieve( - id: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: id, - entityName: Address.name, - repository: this.addressRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("addressRepository_") - async list( - filters: FilterableAddressProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery
(filters, config) - - return (await this.addressRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("addressRepository_") - async listAndCount( - filters: FilterableAddressProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery
(filters, config) - - return (await this.addressRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("addressRepository_") - async create( - data: CreateAddressDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.addressRepository_ as AddressRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("addressRepository_") - async update( - data: UpdateAddressDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - const existingAddresses = await this.list( - { id: data.map(({ id }) => id) }, - {}, - sharedContext - ) - - const existingAddressesMap = new Map( - existingAddresses.map<[string, Address]>((addr) => [addr.id, addr]) - ) - - const updates: UpdateAddressDTO[] = [] - - for (const update of data) { - const address = existingAddressesMap.get(update.id) - - if (!address) { - throw new MedusaError( - MedusaError.Types.NOT_FOUND, - `Address with id "${update.id}" not found` - ) - } - - updates.push({ ...update, id: address.id }) - } - - return (await (this.addressRepository_ as AddressRepository).update( - updates, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("addressRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.addressRepository_.delete(ids, sharedContext) +>(Address) { + constructor(container: InjectedDependencies) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/cart/src/services/cart.ts b/packages/cart/src/services/cart.ts index 0cae7e1dee..e206f557c3 100644 --- a/packages/cart/src/services/cart.ts +++ b/packages/cart/src/services/cart.ts @@ -1,128 +1,23 @@ -import { - CartDTO, - Context, - DAL, - FilterableCartProps, - FindConfig, -} from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - MedusaError, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { Cart } from "@models" -import { CartRepository } from "@repositories" import { CreateCartDTO, UpdateCartDTO } from "@types" type InjectedDependencies = { cartRepository: DAL.RepositoryService } -export default class CartService { - protected readonly cartRepository_: DAL.RepositoryService - +export default class CartService< + TEntity extends Cart = Cart +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: CreateCartDTO + update: UpdateCartDTO + } +>(Cart) { constructor({ cartRepository }: InjectedDependencies) { - this.cartRepository_ = cartRepository - } - - @InjectManager("cartRepository_") - async retrieve( - id: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: id, - entityName: Cart.name, - repository: this.cartRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("cartRepository_") - async list( - filters: FilterableCartProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.cartRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("cartRepository_") - async listAndCount( - filters: FilterableCartProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.cartRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("cartRepository_") - async create( - data: CreateCartDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.cartRepository_ as CartRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("cartRepository_") - async update( - data: UpdateCartDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - const existingCarts = await this.list( - { id: data.map(({ id }) => id) }, - {}, - sharedContext - ) - - const existingCartsMap = new Map( - existingCarts.map<[string, Cart]>((cart) => [cart.id, cart]) - ) - - const updates: { cart: Cart; update: UpdateCartDTO }[] = [] - - for (const update of data) { - const cart = existingCartsMap.get(update.id) - - if (!cart) { - throw new MedusaError( - MedusaError.Types.NOT_FOUND, - `Cart with id "${update.id}" not found` - ) - } - - updates.push({ cart, update }) - } - - return (await (this.cartRepository_ as CartRepository).update( - updates, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("cartRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.cartRepository_.delete(ids, sharedContext) + // @ts-ignore + super(...arguments) } } diff --git a/packages/cart/src/services/line-item.ts b/packages/cart/src/services/line-item.ts index 445a631722..0794665e73 100644 --- a/packages/cart/src/services/line-item.ts +++ b/packages/cart/src/services/line-item.ts @@ -1,128 +1,18 @@ -import { - CartLineItemDTO, - Context, - DAL, - FilterableLineItemProps, - FindConfig, -} from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - MedusaError, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { LineItem } from "@models" -import { LineItemRepository } from "@repositories" import { CreateLineItemDTO, UpdateLineItemDTO } from "../types" type InjectedDependencies = { lineItemRepository: DAL.RepositoryService } -export default class LineItemService { - protected readonly lineItemRepository_: DAL.RepositoryService - - constructor({ lineItemRepository }: InjectedDependencies) { - this.lineItemRepository_ = lineItemRepository +export default class LineItemService< + TEntity extends LineItem = LineItem +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: CreateLineItemDTO + update: UpdateLineItemDTO } - - @InjectManager("lineItemRepository_") - async retrieve( - id: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: id, - entityName: LineItem.name, - repository: this.lineItemRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("lineItemRepository_") - async list( - filters: FilterableLineItemProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.lineItemRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("lineItemRepository_") - async listAndCount( - filters: FilterableLineItemProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.lineItemRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("lineItemRepository_") - async create( - data: CreateLineItemDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.lineItemRepository_ as LineItemRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("lineItemRepository_") - async update( - data: UpdateLineItemDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - const existingLines = await this.list( - { id: [...data.map((d) => d.id)] }, - {}, - sharedContext - ) - - const existingLinesMap = new Map( - existingLines.map<[string, LineItem]>((li) => [li.id, li]) - ) - - const updates: UpdateLineItemDTO[] = [] - - for (const update of data) { - const lineItem = existingLinesMap.get(update.id) - - if (!lineItem) { - throw new MedusaError( - MedusaError.Types.NOT_FOUND, - `Line item with id "${update.id}" not found` - ) - } - - updates.push({ ...update, id: lineItem.id }) - } - - return (await (this.lineItemRepository_ as LineItemRepository).update( - updates, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("lineItemRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.lineItemRepository_.delete(ids, sharedContext) - } -} +>(LineItem) {} diff --git a/packages/pricing/src/services/__fixtures__/currency.ts b/packages/pricing/src/services/__fixtures__/currency.ts index 7a356ebbcf..27315b54df 100644 --- a/packages/pricing/src/services/__fixtures__/currency.ts +++ b/packages/pricing/src/services/__fixtures__/currency.ts @@ -1,6 +1,14 @@ +import { Currency } from "@models" import { CurrencyService } from "@services" import { asClass, asValue, createContainer } from "awilix" +;(Currency as any).meta = { + /** + * Need to mock the Currency model as well to expose the primary keys when it is different than `id` + */ + primaryKeys: ["code"], +} + export const nonExistingCurrencyCode = "non-existing-code" export const mockContainer = createContainer() diff --git a/packages/pricing/src/services/currency.ts b/packages/pricing/src/services/currency.ts index 90848f9fbb..4477da7588 100644 --- a/packages/pricing/src/services/currency.ts +++ b/packages/pricing/src/services/currency.ts @@ -1,106 +1,23 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { Currency } from "@models" -import { CurrencyRepository } from "@repositories" import { ServiceTypes } from "@types" type InjectedDependencies = { currencyRepository: DAL.RepositoryService } -export default class CurrencyService { - protected readonly currencyRepository_: DAL.RepositoryService - +export default class CurrencyService< + TEntity extends Currency = Currency +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreateCurrencyDTO + update: ServiceTypes.UpdateCurrencyDTO + } +>(Currency) { constructor({ currencyRepository }: InjectedDependencies) { - this.currencyRepository_ = currencyRepository - } - - @InjectManager("currencyRepository_") - async retrieve( - currencyCode: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: currencyCode, - identifierColumn: "code", - entityName: Currency.name, - repository: this.currencyRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("currencyRepository_") - async list( - filters: ServiceTypes.FilterableCurrencyProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await this.currencyRepository_.find( - this.buildQueryForList(filters, config), - sharedContext - )) as TEntity[] - } - - @InjectManager("currencyRepository_") - async listAndCount( - filters: ServiceTypes.FilterableCurrencyProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - return (await this.currencyRepository_.findAndCount( - this.buildQueryForList(filters, config), - sharedContext - )) as [TEntity[], number] - } - - private buildQueryForList( - filters: ServiceTypes.FilterableCurrencyProps = {}, - config: FindConfig = {} - ) { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - if (filters.code) { - queryOptions.where["code"] = { $in: filters.code } - } - - return queryOptions - } - - @InjectTransactionManager("currencyRepository_") - async create( - data: ServiceTypes.CreateCurrencyDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.currencyRepository_ as CurrencyRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("currencyRepository_") - async update( - data: ServiceTypes.UpdateCurrencyDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.currencyRepository_ as CurrencyRepository).update( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("currencyRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.currencyRepository_.delete(ids, sharedContext) + // @ts-ignore + super(...arguments) } } diff --git a/packages/pricing/src/services/money-amount.ts b/packages/pricing/src/services/money-amount.ts index 640eacd1f7..b73422969e 100644 --- a/packages/pricing/src/services/money-amount.ts +++ b/packages/pricing/src/services/money-amount.ts @@ -1,13 +1,6 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { MoneyAmount } from "@models" -import { MoneyAmountRepository } from "@repositories" import { ServiceTypes } from "@types" type InjectedDependencies = { @@ -16,105 +9,19 @@ type InjectedDependencies = { export default class MoneyAmountService< TEntity extends MoneyAmount = MoneyAmount -> { - protected readonly moneyAmountRepository_: DAL.RepositoryService - - constructor({ moneyAmountRepository }: InjectedDependencies) { - this.moneyAmountRepository_ = moneyAmountRepository +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreateMoneyAmountDTO + update: ServiceTypes.UpdateMoneyAmountDTO + }, + { + list: ServiceTypes.FilterableMoneyAmountProps + listAndCount: ServiceTypes.FilterableMoneyAmountProps } - - @InjectManager("moneyAmountRepository_") - async retrieve( - moneyAmountId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: moneyAmountId, - entityName: MoneyAmount.name, - repository: this.moneyAmountRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("moneyAmountRepository_") - async list( - filters: ServiceTypes.FilterableMoneyAmountProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.moneyAmountRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("moneyAmountRepository_") - async listAndCount( - filters: ServiceTypes.FilterableMoneyAmountProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.moneyAmountRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("moneyAmountRepository_") - async create( - data: ServiceTypes.CreateMoneyAmountDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.moneyAmountRepository_ as MoneyAmountRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("moneyAmountRepository_") - async update( - data: ServiceTypes.UpdateMoneyAmountDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.moneyAmountRepository_ as MoneyAmountRepository).update( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("moneyAmountRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.moneyAmountRepository_.delete(ids, sharedContext) - } - - @InjectTransactionManager("moneyAmountRepository_") - async softDelete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.moneyAmountRepository_.softDelete(ids, sharedContext) - } - - @InjectTransactionManager("moneyAmountRepository_") - async restore( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], Record]> { - return await this.moneyAmountRepository_.restore(ids, sharedContext) +>(MoneyAmount) { + constructor(container: InjectedDependencies) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/pricing/src/services/price-list-rule-value.ts b/packages/pricing/src/services/price-list-rule-value.ts index 52e5370391..d7ee43653a 100644 --- a/packages/pricing/src/services/price-list-rule-value.ts +++ b/packages/pricing/src/services/price-list-rule-value.ts @@ -1,15 +1,6 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" -import { - doNotForceTransaction, - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, - shouldForceTransaction, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { PriceListRuleValue } from "@models" -import { PriceListRuleValueRepository } from "@repositories" import { ServiceTypes } from "@types" type InjectedDependencies = { @@ -18,99 +9,19 @@ type InjectedDependencies = { export default class PriceListRuleValueService< TEntity extends PriceListRuleValue = PriceListRuleValue -> { - protected readonly priceListRuleValueRepository_: DAL.RepositoryService - - constructor({ priceListRuleValueRepository }: InjectedDependencies) { - this.priceListRuleValueRepository_ = priceListRuleValueRepository +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreatePriceListRuleValueDTO + update: ServiceTypes.UpdatePriceListRuleValueDTO + }, + { + list: ServiceTypes.FilterablePriceListRuleValueProps + listAndCount: ServiceTypes.FilterablePriceListRuleValueProps } - - @InjectManager("priceListRuleValueRepository_") - async retrieve( - priceSetId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity< - PriceListRuleValue, - ServiceTypes.PriceListRuleValueDTO - >({ - id: priceSetId, - entityName: PriceListRuleValue.name, - repository: this.priceListRuleValueRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("priceListRuleValueRepository_") - async list( - filters: ServiceTypes.FilterablePriceListRuleValueProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.priceListRuleValueRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("priceListRuleValueRepository_") - async listAndCount( - filters: ServiceTypes.FilterablePriceListRuleValueProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.priceListRuleValueRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager( - shouldForceTransaction, - "priceListRuleValueRepository_" - ) - async create( - data: ServiceTypes.CreatePriceListRuleValueDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.priceListRuleValueRepository_ as PriceListRuleValueRepository - ).create(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager( - shouldForceTransaction, - "priceListRuleValueRepository_" - ) - async update( - data: ServiceTypes.UpdatePriceListRuleValueDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.priceListRuleValueRepository_ as PriceListRuleValueRepository - ).update(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager( - doNotForceTransaction, - "priceListRuleValueRepository_" - ) - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.priceListRuleValueRepository_.delete(ids, sharedContext) +>(PriceListRuleValue) { + constructor(container: InjectedDependencies) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/pricing/src/services/price-list-rule.ts b/packages/pricing/src/services/price-list-rule.ts index 474edb789b..c1f1fc0366 100644 --- a/packages/pricing/src/services/price-list-rule.ts +++ b/packages/pricing/src/services/price-list-rule.ts @@ -1,15 +1,6 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" -import { - doNotForceTransaction, - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, - shouldForceTransaction, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { PriceListRule } from "@models" -import { PriceListRuleRepository } from "@repositories" import { ServiceTypes } from "@types" type InjectedDependencies = { @@ -18,87 +9,19 @@ type InjectedDependencies = { export default class PriceListRuleService< TEntity extends PriceListRule = PriceListRule -> { - protected readonly priceListRuleRepository_: DAL.RepositoryService - - constructor({ priceListRuleRepository }: InjectedDependencies) { - this.priceListRuleRepository_ = priceListRuleRepository +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreatePriceListRuleDTO + update: ServiceTypes.UpdatePriceListRuleDTO + }, + { + list: ServiceTypes.FilterablePriceListRuleProps + listAndCount: ServiceTypes.FilterablePriceListRuleProps } - - @InjectManager("priceListRuleRepository_") - async retrieve( - priceSetId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: priceSetId, - entityName: PriceListRule.name, - repository: this.priceListRuleRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("priceListRuleRepository_") - async list( - filters: ServiceTypes.FilterablePriceListRuleProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.priceListRuleRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("priceListRuleRepository_") - async listAndCount( - filters: ServiceTypes.FilterablePriceListRuleProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.priceListRuleRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager(shouldForceTransaction, "priceListRuleRepository_") - async create( - data: ServiceTypes.CreatePriceListRuleDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.priceListRuleRepository_ as PriceListRuleRepository - ).create(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager(shouldForceTransaction, "priceListRuleRepository_") - async update( - data: ServiceTypes.UpdatePriceListRuleDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.priceListRuleRepository_ as PriceListRuleRepository - ).update(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager(doNotForceTransaction, "priceListRuleRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.priceListRuleRepository_.delete(ids, sharedContext) +>(PriceListRule) { + constructor(container: InjectedDependencies) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/pricing/src/services/price-list.ts b/packages/pricing/src/services/price-list.ts index 11a1b0bfa4..e4fccad003 100644 --- a/packages/pricing/src/services/price-list.ts +++ b/packages/pricing/src/services/price-list.ts @@ -1,98 +1,27 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" -import { - doNotForceTransaction, - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, - shouldForceTransaction, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { PriceList } from "@models" -import { PriceListRepository } from "@repositories" import { ServiceTypes } from "@types" type InjectedDependencies = { priceListRepository: DAL.RepositoryService } -export default class PriceListService { - protected readonly priceListRepository_: DAL.RepositoryService - - constructor({ priceListRepository }: InjectedDependencies) { - this.priceListRepository_ = priceListRepository +export default class PriceListService< + TEntity extends PriceList = PriceList +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreatePriceListDTO + update: ServiceTypes.UpdatePriceListDTO + }, + { + list: ServiceTypes.FilterablePriceListProps + listAndCount: ServiceTypes.FilterablePriceListProps } - - @InjectManager("priceListRepository_") - async retrieve( - priceListId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: priceListId, - entityName: PriceList.name, - repository: this.priceListRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("priceListRepository_") - async list( - filters: ServiceTypes.FilterablePriceListProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.priceListRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("priceListRepository_") - async listAndCount( - filters: ServiceTypes.FilterablePriceListProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.priceListRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager(shouldForceTransaction, "priceListRepository_") - async create( - data: ServiceTypes.CreatePriceListDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.priceListRepository_ as PriceListRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager(shouldForceTransaction, "priceListRepository_") - async update( - data: Omit[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.priceListRepository_ as PriceListRepository).update( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager(doNotForceTransaction, "priceListRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.priceListRepository_.delete(ids, sharedContext) +>(PriceList) { + constructor(container: InjectedDependencies) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/pricing/src/services/price-rule.ts b/packages/pricing/src/services/price-rule.ts index 0c7bb29787..eb9ab85730 100644 --- a/packages/pricing/src/services/price-rule.ts +++ b/packages/pricing/src/services/price-rule.ts @@ -1,13 +1,6 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { PriceRule } from "@models" -import { PriceRuleRepository } from "@repositories" import { ServiceTypes } from "@types" @@ -15,83 +8,21 @@ type InjectedDependencies = { priceRuleRepository: DAL.RepositoryService } -export default class PriceRuleService { - protected readonly priceRuleRepository_: DAL.RepositoryService - - constructor({ priceRuleRepository }: InjectedDependencies) { - this.priceRuleRepository_ = priceRuleRepository +export default class PriceRuleService< + TEntity extends PriceRule = PriceRule +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreatePriceRuleDTO + update: ServiceTypes.UpdatePriceRuleDTO + }, + { + list: ServiceTypes.FilterablePriceRuleProps + listAndCount: ServiceTypes.FilterablePriceRuleProps } - - @InjectManager("priceRuleRepository_") - async retrieve( - priceRuleId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: priceRuleId, - entityName: PriceRule.name, - repository: this.priceRuleRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("priceRuleRepository_") - async list( - filters: ServiceTypes.FilterablePriceRuleProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryConfig = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.priceRuleRepository_.find( - queryConfig, - sharedContext - )) as TEntity[] - } - - @InjectManager("priceRuleRepository_") - async listAndCount( - filters: ServiceTypes.FilterablePriceRuleProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryConfig = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.priceRuleRepository_.findAndCount( - queryConfig, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("priceRuleRepository_") - async create( - data: ServiceTypes.CreatePriceRuleDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.priceRuleRepository_ as PriceRuleRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("priceRuleRepository_") - async update( - data: ServiceTypes.UpdatePriceRuleDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.priceRuleRepository_ as PriceRuleRepository).update( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("priceRuleRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.priceRuleRepository_.delete(ids, sharedContext) +>(PriceRule) { + constructor(container: InjectedDependencies) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/pricing/src/services/price-set-money-amount-rules.ts b/packages/pricing/src/services/price-set-money-amount-rules.ts index c283c5d61c..ec073c342c 100644 --- a/packages/pricing/src/services/price-set-money-amount-rules.ts +++ b/packages/pricing/src/services/price-set-money-amount-rules.ts @@ -1,11 +1,5 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { PriceSetMoneyAmountRules } from "@models" import { ServiceTypes } from "@types" @@ -15,96 +9,15 @@ type InjectedDependencies = { export default class PriceSetMoneyAmountRulesService< TEntity extends PriceSetMoneyAmountRules = PriceSetMoneyAmountRules -> { - protected readonly priceSetMoneyAmountRulesRepository_: DAL.RepositoryService - +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreatePriceSetMoneyAmountRulesDTO + update: ServiceTypes.UpdatePriceSetMoneyAmountRulesDTO + } +>(PriceSetMoneyAmountRules) { constructor({ priceSetMoneyAmountRulesRepository }: InjectedDependencies) { - this.priceSetMoneyAmountRulesRepository_ = - priceSetMoneyAmountRulesRepository - } - - @InjectManager("priceSetMoneyAmountRulesRepository_") - async retrieve( - priceSetMoneyAmountRulesId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity< - PriceSetMoneyAmountRules, - ServiceTypes.PriceSetMoneyAmountRulesDTO - >({ - id: priceSetMoneyAmountRulesId, - identifierColumn: "id", - entityName: PriceSetMoneyAmountRules.name, - repository: this.priceSetMoneyAmountRulesRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("priceSetMoneyAmountRulesRepository_") - async list( - filters: ServiceTypes.FilterablePriceSetMoneyAmountRulesProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await this.priceSetMoneyAmountRulesRepository_.find( - this.buildQueryForList(filters, config), - sharedContext - )) as TEntity[] - } - - @InjectManager("priceSetMoneyAmountRulesRepository_") - async listAndCount( - filters: ServiceTypes.FilterablePriceSetMoneyAmountRulesProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - return (await this.priceSetMoneyAmountRulesRepository_.findAndCount( - this.buildQueryForList(filters, config), - sharedContext - )) as [TEntity[], number] - } - - private buildQueryForList( - filters: ServiceTypes.FilterablePriceSetMoneyAmountRulesProps = {}, - config: FindConfig = {} - ) { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return queryOptions - } - - @InjectTransactionManager("priceSetMoneyAmountRulesRepository_") - async create( - data: ServiceTypes.CreatePriceSetMoneyAmountRulesDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await this.priceSetMoneyAmountRulesRepository_.create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("priceSetMoneyAmountRulesRepository_") - async update( - data: ServiceTypes.UpdatePriceSetMoneyAmountRulesDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await this.priceSetMoneyAmountRulesRepository_.update( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("priceSetMoneyAmountRulesRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.priceSetMoneyAmountRulesRepository_.delete(ids, sharedContext) + // @ts-ignore + super(...arguments) } } diff --git a/packages/pricing/src/services/price-set-money-amount.ts b/packages/pricing/src/services/price-set-money-amount.ts index ff21ef8a22..569cfb5eee 100644 --- a/packages/pricing/src/services/price-set-money-amount.ts +++ b/packages/pricing/src/services/price-set-money-amount.ts @@ -1,13 +1,6 @@ import { Context, DAL, FindConfig } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" -import { PriceSet, PriceSetMoneyAmount } from "@models" -import { PriceSetMoneyAmountRepository } from "@repositories" +import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils" +import { PriceSetMoneyAmount } from "@models" import { ServiceTypes } from "@types" type InjectedDependencies = { @@ -16,95 +9,51 @@ type InjectedDependencies = { export default class PriceSetMoneyAmountService< TEntity extends PriceSetMoneyAmount = PriceSetMoneyAmount -> { - protected readonly priceSetMoneyAmountRepository_: DAL.RepositoryService +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreatePriceSetMoneyAmountDTO + update: ServiceTypes.UpdatePriceSetMoneyAmountDTO + } +>(PriceSetMoneyAmount) { + protected readonly priceSetMoneyAmountRepository_: DAL.RepositoryService constructor({ priceSetMoneyAmountRepository }: InjectedDependencies) { + // @ts-ignore + super(...arguments) this.priceSetMoneyAmountRepository_ = priceSetMoneyAmountRepository } @InjectManager("priceSetMoneyAmountRepository_") - async retrieve( - priceSetId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity< - PriceSetMoneyAmount, - ServiceTypes.PriceSetMoneyAmountDTO - >({ - id: priceSetId, - entityName: PriceSet.name, - repository: this.priceSetMoneyAmountRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("priceSetMoneyAmountRepository_") - async list( + async list( filters: ServiceTypes.FilterablePriceSetMoneyAmountProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise { - return (await this.priceSetMoneyAmountRepository_.find( + return await this.priceSetMoneyAmountRepository_.find( this.buildQueryForList(filters, config), sharedContext - )) as TEntity[] + ) } @InjectManager("priceSetMoneyAmountRepository_") - async listAndCount( + async listAndCount( filters: ServiceTypes.FilterablePriceSetMoneyAmountProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise<[TEntity[], number]> { - return (await this.priceSetMoneyAmountRepository_.findAndCount( + return await this.priceSetMoneyAmountRepository_.findAndCount( this.buildQueryForList(filters, config), sharedContext - )) as [TEntity[], number] + ) } - private buildQueryForList( + private buildQueryForList< + TEntityMethod = ServiceTypes.PriceSetMoneyAmountDTO + >( filters: ServiceTypes.FilterablePriceSetMoneyAmountProps = {}, - config: FindConfig = {} + config: FindConfig = {} ) { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - if (filters.id) { - queryOptions.where.id = { $in: filters.id } - } - - return queryOptions - } - - @InjectTransactionManager("priceSetMoneyAmountRepository_") - async create( - data: ServiceTypes.CreatePriceSetMoneyAmountDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this - .priceSetMoneyAmountRepository_ as unknown as PriceSetMoneyAmountRepository - ).create(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("priceSetMoneyAmountRepository_") - async update( - data: ServiceTypes.UpdatePriceSetMoneyAmountDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this - .priceSetMoneyAmountRepository_ as unknown as PriceSetMoneyAmountRepository - ).update(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("priceSetMoneyAmountRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.priceSetMoneyAmountRepository_.delete(ids, sharedContext) + return ModulesSdkUtils.buildQuery(filters, config) } } diff --git a/packages/pricing/src/services/price-set-rule-type.ts b/packages/pricing/src/services/price-set-rule-type.ts index 08fcb568c8..27fa9e4b25 100644 --- a/packages/pricing/src/services/price-set-rule-type.ts +++ b/packages/pricing/src/services/price-set-rule-type.ts @@ -1,13 +1,6 @@ import { Context, DAL, FindConfig } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" -import { PriceSet, PriceSetRuleType } from "@models" -import { PriceSetRuleTypeRepository } from "src/repositories/price-set-rule-type" +import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils" +import { PriceSetRuleType } from "@models" import { ServiceTypes } from "@types" type InjectedDependencies = { @@ -16,93 +9,51 @@ type InjectedDependencies = { export default class PriceSetRuleTypeService< TEntity extends PriceSetRuleType = PriceSetRuleType -> { - protected readonly priceSetRuleTypeRepository_: DAL.RepositoryService +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreatePriceSetRuleTypeDTO + update: ServiceTypes.UpdatePriceSetRuleTypeDTO + } +>(PriceSetRuleType) { + protected readonly priceSetRuleTypeRepository_: DAL.RepositoryService constructor({ priceSetRuleTypeRepository }: InjectedDependencies) { + // @ts-ignore + super(...arguments) this.priceSetRuleTypeRepository_ = priceSetRuleTypeRepository } @InjectManager("priceSetRuleTypeRepository_") - async retrieve( - priceSetId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity< - PriceSetRuleType, - ServiceTypes.PriceSetRuleTypeDTO - >({ - id: priceSetId, - entityName: PriceSet.name, - repository: this.priceSetRuleTypeRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("priceSetRuleTypeRepository_") - async list( + async list( filters: ServiceTypes.FilterablePriceSetRuleTypeProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise { - return (await this.priceSetRuleTypeRepository_.find( + return await this.priceSetRuleTypeRepository_.find( this.buildQueryForList(filters, config), sharedContext - )) as TEntity[] + ) } @InjectManager("priceSetRuleTypeRepository_") - async listAndCount( + async listAndCount( filters: ServiceTypes.FilterablePriceSetRuleTypeProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise<[TEntity[], number]> { - return (await this.priceSetRuleTypeRepository_.findAndCount( + return await this.priceSetRuleTypeRepository_.findAndCount( this.buildQueryForList(filters, config), sharedContext - )) as [TEntity[], number] + ) } - private buildQueryForList( + private buildQueryForList< + TEntityMethod = ServiceTypes.PriceSetMoneyAmountDTO + >( filters: ServiceTypes.FilterablePriceSetRuleTypeProps = {}, - config: FindConfig = {} + config: FindConfig = {} ) { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - if (filters.id) { - queryOptions.where.id = { $in: filters.id } - } - - return queryOptions - } - - @InjectTransactionManager("priceSetRuleTypeRepository_") - async create( - data: ServiceTypes.CreatePriceSetRuleTypeDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.priceSetRuleTypeRepository_ as PriceSetRuleTypeRepository - ).create(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("priceSetRuleTypeRepository_") - async update( - data: ServiceTypes.UpdatePriceSetRuleTypeDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.priceSetRuleTypeRepository_ as PriceSetRuleTypeRepository - ).update(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("priceSetRuleTypeRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.priceSetRuleTypeRepository_.delete(ids, sharedContext) + return ModulesSdkUtils.buildQuery(filters, config) } } diff --git a/packages/pricing/src/services/price-set.ts b/packages/pricing/src/services/price-set.ts index ba7ad6080a..c850f045d7 100644 --- a/packages/pricing/src/services/price-set.ts +++ b/packages/pricing/src/services/price-set.ts @@ -1,13 +1,6 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { PriceSet } from "@models" -import { PriceSetRepository } from "@repositories" import { ServiceTypes } from "@types" @@ -15,83 +8,21 @@ type InjectedDependencies = { priceSetRepository: DAL.RepositoryService } -export default class PriceSetService { - protected readonly priceSetRepository_: DAL.RepositoryService - - constructor({ priceSetRepository }: InjectedDependencies) { - this.priceSetRepository_ = priceSetRepository +export default class PriceSetService< + TEntity extends PriceSet = PriceSet +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: Omit + update: Omit + }, + { + list: ServiceTypes.FilterablePriceSetProps + listAndCount: ServiceTypes.FilterablePriceSetProps } - - @InjectManager("priceSetRepository_") - async retrieve( - priceSetId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: priceSetId, - entityName: PriceSet.name, - repository: this.priceSetRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("priceSetRepository_") - async list( - filters: ServiceTypes.FilterablePriceSetProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.priceSetRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("priceSetRepository_") - async listAndCount( - filters: ServiceTypes.FilterablePriceSetProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.priceSetRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("priceSetRepository_") - async create( - data: Omit[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.priceSetRepository_ as PriceSetRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("priceSetRepository_") - async update( - data: Omit[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.priceSetRepository_ as PriceSetRepository).update( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("priceSetRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.priceSetRepository_.delete(ids, sharedContext) +>(PriceSet) { + constructor(container: InjectedDependencies) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/pricing/src/services/rule-type.ts b/packages/pricing/src/services/rule-type.ts index 6d1fbe674a..9bd78752c0 100644 --- a/packages/pricing/src/services/rule-type.ts +++ b/packages/pricing/src/services/rule-type.ts @@ -1,10 +1,8 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" +import { Context, DAL } from "@medusajs/types" import { - InjectManager, InjectTransactionManager, MedusaContext, ModulesSdkUtils, - retrieveEntity, validateRuleAttributes, } from "@medusajs/utils" import { RuleType } from "@models" @@ -14,67 +12,34 @@ type InjectedDependencies = { ruleTypeRepository: DAL.RepositoryService } -export default class RuleTypeService { - protected readonly ruleTypeRepository_: DAL.RepositoryService +export default class RuleTypeService< + TEntity extends RuleType = RuleType +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ServiceTypes.CreateRuleTypeDTO + update: ServiceTypes.UpdateRuleTypeDTO + }, + { + list: ServiceTypes.FilterableRuleTypeProps + listAndCount: ServiceTypes.FilterableRuleTypeProps + } +>(RuleType) { + protected readonly ruleTypeRepository_: DAL.RepositoryService constructor({ ruleTypeRepository }: InjectedDependencies) { + // @ts-ignore + super(...arguments) this.ruleTypeRepository_ = ruleTypeRepository } - @InjectManager("ruleTypeRepository_") - async retrieve( - ruleTypeId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: ruleTypeId, - identifierColumn: "id", - entityName: RuleType.name, - repository: this.ruleTypeRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("ruleTypeRepository_") - async list( - filters: ServiceTypes.FilterableRuleTypeProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.ruleTypeRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("ruleTypeRepository_") - async listAndCount( - filters: ServiceTypes.FilterableRuleTypeProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.ruleTypeRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - @InjectTransactionManager("ruleTypeRepository_") async create( data: ServiceTypes.CreateRuleTypeDTO[], @MedusaContext() sharedContext: Context = {} ): Promise { validateRuleAttributes(data.map((d) => d.rule_attribute)) - return (await this.ruleTypeRepository_.create( - data, - sharedContext - )) as TEntity[] + return await this.ruleTypeRepository_.create(data, sharedContext) } @InjectTransactionManager("ruleTypeRepository_") @@ -83,17 +48,6 @@ export default class RuleTypeService { @MedusaContext() sharedContext: Context = {} ): Promise { validateRuleAttributes(data.map((d) => d.rule_attribute)) - return (await this.ruleTypeRepository_.update( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("ruleTypeRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.ruleTypeRepository_.delete(ids, sharedContext) + return await this.ruleTypeRepository_.update(data, sharedContext) } } diff --git a/packages/product/jest.config.js b/packages/product/jest.config.js index fc8bdef49c..dce2002dae 100644 --- a/packages/product/jest.config.js +++ b/packages/product/jest.config.js @@ -3,6 +3,7 @@ module.exports = { "^@models": "/src/models", "^@services": "/src/services", "^@repositories": "/src/repositories", + "^@types": "/src/types", }, transform: { "^.+\\.[jt]s?$": [ diff --git a/packages/product/src/repositories/product.ts b/packages/product/src/repositories/product.ts index 833c61e9d5..eb430a06d4 100644 --- a/packages/product/src/repositories/product.ts +++ b/packages/product/src/repositories/product.ts @@ -13,17 +13,20 @@ import { WithRequiredProperty, } from "@medusajs/types" import { SqlEntityManager } from "@mikro-orm/postgresql" -import { DALUtils, isDefined, MedusaError, promiseAll } from "@medusajs/utils" +import { + DALUtils, + isDefined, + MedusaError, + promiseAll, + ProductUtils, +} from "@medusajs/utils" import { ProductServiceTypes } from "../types/services" // eslint-disable-next-line max-len -export class ProductRepository extends DALUtils.mikroOrmBaseRepositoryFactory< - Product, - { - create: WithRequiredProperty - } ->(Product) { +export class ProductRepository extends DALUtils.mikroOrmBaseRepositoryFactory( + Product +) { constructor(...args: any[]) { // @ts-ignore super(...arguments) @@ -103,6 +106,17 @@ export class ProductRepository extends DALUtils.mikroOrmBaseRepositoryFactory< } } + async create( + data: WithRequiredProperty[], + context: Context = {} + ): Promise { + data.forEach((productData) => { + productData.status ??= ProductUtils.ProductStatus.DRAFT + }) + + return await super.create(data, context) + } + async update( data: WithRequiredProperty[], context: Context = {} diff --git a/packages/product/src/services/product-category.ts b/packages/product/src/services/product-category.ts index a2ef62a041..a2798cccf6 100644 --- a/packages/product/src/services/product-category.ts +++ b/packages/product/src/services/product-category.ts @@ -9,7 +9,7 @@ import { MedusaError, ModulesSdkUtils, } from "@medusajs/utils" -import { ProductCategoryServiceTypes } from "../types" +import { ProductCategoryServiceTypes } from "@types" type InjectedDependencies = { productCategoryRepository: DAL.TreeRepositoryService diff --git a/packages/product/src/services/product-collection.ts b/packages/product/src/services/product-collection.ts index 08199ab1ae..31e85c8731 100644 --- a/packages/product/src/services/product-collection.ts +++ b/packages/product/src/services/product-collection.ts @@ -1,12 +1,5 @@ import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" -import { ProductCollectionRepository } from "../repositories" +import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils" import { ProductCollection } from "@models" @@ -16,98 +9,61 @@ type InjectedDependencies = { export default class ProductCollectionService< TEntity extends ProductCollection = ProductCollection -> { - protected readonly productCollectionRepository_: DAL.RepositoryService +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ProductTypes.CreateProductCollectionDTO + update: ProductTypes.UpdateProductCollectionDTO + } +>(ProductCollection) { + // eslint-disable-next-line max-len + protected readonly productCollectionRepository_: DAL.RepositoryService - constructor({ productCollectionRepository }: InjectedDependencies) { - this.productCollectionRepository_ = productCollectionRepository + constructor(container: InjectedDependencies) { + super(container) + this.productCollectionRepository_ = container.productCollectionRepository } @InjectManager("productCollectionRepository_") - async retrieve( - productCollectionId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity< - ProductCollection, - ProductTypes.ProductCollectionDTO - >({ - id: productCollectionId, - entityName: ProductCollection.name, - repository: this.productCollectionRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("productCollectionRepository_") - async list( + async list( filters: ProductTypes.FilterableProductCollectionProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise { - return (await this.productCollectionRepository_.find( + return await this.productCollectionRepository_.find( this.buildListQueryOptions(filters, config), sharedContext - )) as TEntity[] + ) } @InjectManager("productCollectionRepository_") - async listAndCount( + async listAndCount( filters: ProductTypes.FilterableProductCollectionProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise<[TEntity[], number]> { - return (await this.productCollectionRepository_.findAndCount( + return await this.productCollectionRepository_.findAndCount( this.buildListQueryOptions(filters, config), sharedContext - )) as [TEntity[], number] + ) } - protected buildListQueryOptions( + protected buildListQueryOptions< + TEntityMethod = ProductTypes.ProductCollectionDTO + >( filters: ProductTypes.FilterableProductCollectionProps = {}, - config: FindConfig = {} - ) { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) + config: FindConfig = {} + ): DAL.FindOptions { + const queryOptions = ModulesSdkUtils.buildQuery(filters, config) queryOptions.where ??= {} if (filters.title) { - queryOptions.where["title"] = { $like: filters.title } + queryOptions.where.title = { + $like: `%${filters.title}%`, + } as DAL.FindOptions["where"]["title"] } return queryOptions } - - @InjectTransactionManager("productCollectionRepository_") - async create( - data: ProductTypes.CreateProductCollectionDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.productCollectionRepository_ as ProductCollectionRepository - ).create(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("productCollectionRepository_") - async update( - data: ProductTypes.UpdateProductCollectionDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.productCollectionRepository_ as ProductCollectionRepository - ).update(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("productCollectionRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.productCollectionRepository_.delete(ids, sharedContext) - } } diff --git a/packages/product/src/services/product-image.ts b/packages/product/src/services/product-image.ts index 134ba87a7d..d6c6a62368 100644 --- a/packages/product/src/services/product-image.ts +++ b/packages/product/src/services/product-image.ts @@ -1,7 +1,6 @@ import { Image } from "@models" import { Context, DAL } from "@medusajs/types" import { InjectTransactionManager, MedusaContext } from "@medusajs/utils" -import { ProductImageRepository } from "@repositories" type InjectedDependencies = { productImageRepository: DAL.RepositoryService @@ -19,7 +18,6 @@ export default class ProductImageService { urls: string[], @MedusaContext() sharedContext: Context = {} ): Promise { - return (await (this.productImageRepository_ as ProductImageRepository) - .upsert!(urls, sharedContext)) as TEntity[] + return await this.productImageRepository_.upsert!(urls, sharedContext) } } diff --git a/packages/product/src/services/product-module-service.ts b/packages/product/src/services/product-module-service.ts index c67a27bbbf..76f55e6194 100644 --- a/packages/product/src/services/product-module-service.ts +++ b/packages/product/src/services/product-module-service.ts @@ -35,24 +35,11 @@ import { import ProductImageService from "./product-image" import { - CreateProductCategoryDTO, - ProductCategoryEventData, - ProductCategoryEvents, - UpdateProductCategoryDTO, -} from "../types/services/product-category" - -import { UpdateProductVariantDTO } from "../types/services/product-variant" - -import { - ProductCollectionEventData, - ProductCollectionEvents, -} from "../types/services/product-collection" - -import { - ProductEventData, - ProductEvents, - UpdateProductDTO, -} from "../types/services/product" + ProductCategoryServiceTypes, + ProductCollectionServiceTypes, + ProductServiceTypes, + ProductVariantServiceTypes, +} from "@types" import { arrayDifference, @@ -76,6 +63,11 @@ import { joinerConfig, LinkableKeys, } from "./../joiner-config" +import { + ProductCategoryEventData, + ProductCategoryEvents, +} from "../types/services/product-category" +import { ProductEventData, ProductEvents } from "../types/services/product" type InjectedDependencies = { baseRepository: DAL.RepositoryService @@ -373,7 +365,7 @@ export default class ProductModuleService< const toUpdate = data.map(({ id, options, ...rest }) => { const variant = variantsMap.get(id)! - const toUpdate: UpdateProductVariantDTO = { + const toUpdate: ProductVariantServiceTypes.UpdateProductVariantDTO = { id, product_id: variant.product_id, } @@ -749,9 +741,12 @@ export default class ProductModuleService< sharedContext ) - await this.eventBusModuleService_?.emit( + // eslint-disable-next-line max-len + await this.eventBusModuleService_?.emit( productCollections.map(({ id }) => ({ - eventName: ProductCollectionEvents.COLLECTION_CREATED, + eventName: + ProductCollectionServiceTypes.ProductCollectionEvents + .COLLECTION_CREATED, data: { id }, })) ) @@ -769,9 +764,12 @@ export default class ProductModuleService< sharedContext ) - await this.eventBusModuleService_?.emit( + // eslint-disable-next-line max-len + await this.eventBusModuleService_?.emit( productCollections.map(({ id }) => ({ - eventName: ProductCollectionEvents.COLLECTION_UPDATED, + eventName: + ProductCollectionServiceTypes.ProductCollectionEvents + .COLLECTION_UPDATED, data: { id }, })) ) @@ -789,9 +787,12 @@ export default class ProductModuleService< sharedContext ) - await this.eventBusModuleService_?.emit( + // eslint-disable-next-line max-len + await this.eventBusModuleService_?.emit( productCollectionIds.map((id) => ({ - eventName: ProductCollectionEvents.COLLECTION_DELETED, + eventName: + ProductCollectionServiceTypes.ProductCollectionEvents + .COLLECTION_DELETED, data: { id }, })) ) @@ -829,7 +830,7 @@ export default class ProductModuleService< @InjectTransactionManager("baseRepository_") async createCategory( - data: CreateProductCategoryDTO, + data: ProductCategoryServiceTypes.CreateProductCategoryDTO, @MedusaContext() sharedContext: Context = {} ) { const productCategory = await this.productCategoryService_.create( @@ -848,7 +849,7 @@ export default class ProductModuleService< @InjectTransactionManager("baseRepository_") async updateCategory( categoryId: string, - data: UpdateProductCategoryDTO, + data: ProductCategoryServiceTypes.UpdateProductCategoryDTO, @MedusaContext() sharedContext: Context = {} ) { const productCategory = await this.productCategoryService_.update( @@ -1124,7 +1125,7 @@ export default class ProductModuleService< (productData.options ?? []) as TProductOption[] ) - return productData as UpdateProductDTO + return productData as ProductServiceTypes.UpdateProductDTO }) ) @@ -1203,10 +1204,13 @@ export default class ProductModuleService< }) productVariantsToUpdateMap.forEach((variants, productId) => { + const variants_ = + // eslint-disable-next-line max-len + variants as unknown as ProductVariantServiceTypes.UpdateProductVariantDTO[] promises.push( this.productVariantService_.update( productByIdMap.get(productId)!, - variants as unknown as UpdateProductVariantDTO[], + variants_, sharedContext ) ) diff --git a/packages/product/src/services/product-option-value.ts b/packages/product/src/services/product-option-value.ts index f72a9fb533..b66069c87a 100644 --- a/packages/product/src/services/product-option-value.ts +++ b/packages/product/src/services/product-option-value.ts @@ -1,14 +1,7 @@ import { ProductOptionValue } from "@models" import { Context, DAL } from "@medusajs/types" -import { - ProductOptionRepository, - ProductOptionValueRepository, -} from "@repositories" import { InjectTransactionManager, MedusaContext } from "@medusajs/utils" -import { - CreateProductOptionValueDTO, - UpdateProductOptionValueDTO, -} from "../types/services/product-option-value" +import { ProductOptionValueServiceTypes } from "@types" type InjectedDependencies = { productOptionValueRepository: DAL.RepositoryService @@ -17,11 +10,11 @@ type InjectedDependencies = { export default class ProductOptionValueService< TEntity extends ProductOptionValue = ProductOptionValue > { - protected readonly productOptionValueRepository_: DAL.RepositoryService + // eslint-disable-next-line max-len + protected readonly productOptionValueRepository_: DAL.RepositoryService constructor({ productOptionValueRepository }: InjectedDependencies) { - this.productOptionValueRepository_ = - productOptionValueRepository as ProductOptionRepository + this.productOptionValueRepository_ = productOptionValueRepository } @InjectTransactionManager("productOptionValueRepository_") @@ -34,11 +27,12 @@ export default class ProductOptionValueService< @InjectTransactionManager("productOptionValueRepository_") async upsert( - data: (UpdateProductOptionValueDTO | CreateProductOptionValueDTO)[], + data: ( + | ProductOptionValueServiceTypes.UpdateProductOptionValueDTO + | ProductOptionValueServiceTypes.CreateProductOptionValueDTO + )[], @MedusaContext() sharedContext: Context = {} ): Promise { - return (await ( - this.productOptionValueRepository_ as ProductOptionValueRepository - ).upsert!(data, sharedContext)) as TEntity[] + return await this.productOptionValueRepository_.upsert!(data, sharedContext) } } diff --git a/packages/product/src/services/product-option.ts b/packages/product/src/services/product-option.ts index 0a2b391033..c0258996a4 100644 --- a/packages/product/src/services/product-option.ts +++ b/packages/product/src/services/product-option.ts @@ -1,12 +1,10 @@ import { ProductOption } from "@models" import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types" -import { ProductOptionRepository } from "@repositories" import { InjectManager, InjectTransactionManager, MedusaContext, ModulesSdkUtils, - retrieveEntity, } from "@medusajs/utils" type InjectedDependencies = { @@ -15,99 +13,59 @@ type InjectedDependencies = { export default class ProductOptionService< TEntity extends ProductOption = ProductOption -> { - protected readonly productOptionRepository_: DAL.RepositoryService +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ProductTypes.CreateProductOptionDTO + update: ProductTypes.UpdateProductOptionDTO + } +>(ProductOption) { + protected readonly productOptionRepository_: DAL.RepositoryService - constructor({ productOptionRepository }: InjectedDependencies) { - this.productOptionRepository_ = - productOptionRepository as ProductOptionRepository + constructor(container: InjectedDependencies) { + super(container) + this.productOptionRepository_ = container.productOptionRepository } @InjectManager("productOptionRepository_") - async retrieve( - productOptionId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext?: Context - ): Promise { - return (await retrieveEntity({ - id: productOptionId, - entityName: ProductOption.name, - repository: this.productOptionRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("productOptionRepository_") - async list( + async list( filters: ProductTypes.FilterableProductOptionProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext?: Context ): Promise { - return (await this.productOptionRepository_.find( + return await this.productOptionRepository_.find( this.buildQueryForList(filters, config), sharedContext - )) as TEntity[] + ) } @InjectManager("productOptionRepository_") - async listAndCount( + async listAndCount( filters: ProductTypes.FilterableProductOptionProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext?: Context ): Promise<[TEntity[], number]> { - return (await this.productOptionRepository_.findAndCount( + return await this.productOptionRepository_.findAndCount( this.buildQueryForList(filters, config), sharedContext - )) as [TEntity[], number] + ) } - private buildQueryForList( + private buildQueryForList( filters: ProductTypes.FilterableProductOptionProps = {}, - config: FindConfig = {} - ) { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) + config: FindConfig = {} + ): DAL.FindOptions { + const queryOptions = ModulesSdkUtils.buildQuery(filters, config) if (filters.title) { - queryOptions.where["title"] = { $ilike: filters.title } + queryOptions.where.title = { + $ilike: filters.title, + } as DAL.FindOptions["where"]["title"] } return queryOptions } - @InjectTransactionManager("productOptionRepository_") - async create( - data: ProductTypes.CreateProductOptionOnlyDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.productOptionRepository_ as ProductOptionRepository - ).create(data, { - transactionManager: sharedContext.transactionManager, - })) as TEntity[] - } - - @InjectTransactionManager("productOptionRepository_") - async update( - data: ProductTypes.UpdateProductOptionDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.productOptionRepository_ as ProductOptionRepository - ).update(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("productOptionRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return await this.productOptionRepository_.delete(ids, sharedContext) - } - @InjectTransactionManager("productOptionRepository_") async upsert( data: @@ -115,7 +73,6 @@ export default class ProductOptionService< | ProductTypes.UpdateProductOptionDTO[], @MedusaContext() sharedContext: Context = {} ): Promise { - return (await (this.productOptionRepository_ as ProductOptionRepository) - .upsert!(data, sharedContext)) as TEntity[] + return await this.productOptionRepository_.upsert!(data, sharedContext) } } diff --git a/packages/product/src/services/product-tag.ts b/packages/product/src/services/product-tag.ts index 90a33aa352..400d92ae7c 100644 --- a/packages/product/src/services/product-tag.ts +++ b/packages/product/src/services/product-tag.ts @@ -1,11 +1,9 @@ import { ProductTag } from "@models" import { Context, - CreateProductTagDTO, DAL, FindConfig, ProductTypes, - UpdateProductTagDTO, UpsertProductTagDTO, } from "@medusajs/types" import { @@ -13,11 +11,7 @@ import { InjectTransactionManager, MedusaContext, ModulesSdkUtils, - retrieveEntity, } from "@medusajs/utils" -import { ProductTagRepository } from "@repositories" - -import { shouldForceTransaction } from "../utils" type InjectedDependencies = { productTagRepository: DAL.RepositoryService @@ -25,103 +19,63 @@ type InjectedDependencies = { export default class ProductTagService< TEntity extends ProductTag = ProductTag -> { - protected readonly productTagRepository_: DAL.RepositoryService - - constructor({ productTagRepository }: InjectedDependencies) { - this.productTagRepository_ = productTagRepository +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ProductTypes.CreateProductTagDTO + update: ProductTypes.UpdateProductTagDTO } +>(ProductTag) { + protected readonly productTagRepository_: DAL.RepositoryService - @InjectManager("productTagRepository_") - async retrieve( - productTagId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: productTagId, - entityName: ProductTag.name, - repository: this.productTagRepository_, - config, - sharedContext, - })) as TEntity + constructor(container: InjectedDependencies) { + super(container) + this.productTagRepository_ = container.productTagRepository } - @InjectManager("productTagRepository_") - async list( + async list( filters: ProductTypes.FilterableProductTagProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise { - return (await this.productTagRepository_.find( + return await this.productTagRepository_.find( this.buildQueryForList(filters, config), sharedContext - )) as TEntity[] + ) } @InjectManager("productTagRepository_") - async listAndCount( + async listAndCount( filters: ProductTypes.FilterableProductTagProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise<[TEntity[], number]> { - return (await this.productTagRepository_.findAndCount( + return await this.productTagRepository_.findAndCount( this.buildQueryForList(filters, config), sharedContext - )) as [TEntity[], number] + ) } - private buildQueryForList( + private buildQueryForList( filters: ProductTypes.FilterableProductTagProps = {}, - config: FindConfig = {} - ) { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) + config: FindConfig = {} + ): DAL.FindOptions { + const queryOptions = ModulesSdkUtils.buildQuery(filters, config) if (filters.value) { - queryOptions.where["value"] = { $ilike: filters.value } + queryOptions.where.value = { + $ilike: filters.value, + } as DAL.FindOptions["where"]["value"] } return queryOptions } - @InjectTransactionManager("productTagRepository_") - async create( - data: CreateProductTagDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.productTagRepository_ as ProductTagRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("productTagRepository_") - async update( - data: UpdateProductTagDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.productTagRepository_ as ProductTagRepository).update( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("productTagRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.productTagRepository_.delete(ids, sharedContext) - } - @InjectTransactionManager("productTagRepository_") async upsert( data: UpsertProductTagDTO[], @MedusaContext() sharedContext: Context = {} ): Promise { - return (await (this.productTagRepository_ as ProductTagRepository).upsert!( - data, - sharedContext - )) as TEntity[] + return await this.productTagRepository_.upsert!(data, sharedContext) } } diff --git a/packages/product/src/services/product-type.ts b/packages/product/src/services/product-type.ts index 2d510a3430..ddab918b2a 100644 --- a/packages/product/src/services/product-type.ts +++ b/packages/product/src/services/product-type.ts @@ -1,87 +1,72 @@ import { ProductType } from "@models" import { Context, - CreateProductTypeDTO, DAL, FindConfig, ProductTypes, - UpdateProductTypeDTO, UpsertProductTypeDTO, } from "@medusajs/types" -import { ProductTypeRepository } from "@repositories" import { InjectManager, InjectTransactionManager, MedusaContext, ModulesSdkUtils, - retrieveEntity, } from "@medusajs/utils" -import { shouldForceTransaction } from "../utils" - type InjectedDependencies = { productTypeRepository: DAL.RepositoryService } export default class ProductTypeService< TEntity extends ProductType = ProductType -> { - protected readonly productTypeRepository_: DAL.RepositoryService +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ProductTypes.CreateProductTypeDTO + update: ProductTypes.UpdateProductTypeDTO + } +>(ProductType) { + protected readonly productTypeRepository_: DAL.RepositoryService - constructor({ productTypeRepository }: InjectedDependencies) { - this.productTypeRepository_ = productTypeRepository + constructor(container: InjectedDependencies) { + super(container) + this.productTypeRepository_ = container.productTypeRepository } @InjectManager("productTypeRepository_") - async retrieve( - productTypeId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: productTypeId, - entityName: ProductType.name, - repository: this.productTypeRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("productTypeRepository_") - async list( + async list( filters: ProductTypes.FilterableProductTypeProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise { - return (await this.productTypeRepository_.find( + return await this.productTypeRepository_.find( this.buildQueryForList(filters, config), sharedContext - )) as TEntity[] + ) } @InjectManager("productTypeRepository_") - async listAndCount( + async listAndCount( filters: ProductTypes.FilterableProductTypeProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise<[TEntity[], number]> { - return (await this.productTypeRepository_.findAndCount( + return await this.productTypeRepository_.findAndCount( this.buildQueryForList(filters, config), sharedContext - )) as [TEntity[], number] + ) } - private buildQueryForList( + private buildQueryForList( filters: ProductTypes.FilterableProductTypeProps = {}, - config: FindConfig = {} - ) { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) + config: FindConfig = {} + ): DAL.FindOptions { + const queryOptions = ModulesSdkUtils.buildQuery(filters, config) if (filters.value) { - queryOptions.where["value"] = { $ilike: filters.value } + queryOptions.where.value = { + $ilike: filters.value, + } as DAL.FindOptions["where"]["value"] } return queryOptions @@ -92,37 +77,6 @@ export default class ProductTypeService< types: UpsertProductTypeDTO[], @MedusaContext() sharedContext: Context = {} ): Promise { - return (await (this.productTypeRepository_ as ProductTypeRepository) - .upsert!(types, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("productTypeRepository_") - async create( - data: CreateProductTypeDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.productTypeRepository_ as ProductTypeRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("productTypeRepository_") - async update( - data: UpdateProductTypeDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.productTypeRepository_ as ProductTypeRepository).update( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("productTypeRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.productTypeRepository_.delete(ids, sharedContext) + return await this.productTypeRepository_.upsert!(types, sharedContext) } } diff --git a/packages/product/src/services/product-variant.ts b/packages/product/src/services/product-variant.ts index 06d30a8f02..38abaf1b4d 100644 --- a/packages/product/src/services/product-variant.ts +++ b/packages/product/src/services/product-variant.ts @@ -1,16 +1,13 @@ -import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types" +import { Context, DAL, ProductTypes } from "@medusajs/types" import { - InjectManager, InjectTransactionManager, + isString, MedusaContext, ModulesSdkUtils, - isString, - retrieveEntity, } from "@medusajs/utils" import { Product, ProductVariant } from "@models" -import { ProductVariantRepository } from "@repositories" -import { ProductVariantServiceTypes } from "../types/services" +import { ProductVariantServiceTypes } from "@types" import ProductService from "./product" type InjectedDependencies = { @@ -21,72 +18,29 @@ type InjectedDependencies = { export default class ProductVariantService< TEntity extends ProductVariant = ProductVariant, TProduct extends Product = Product -> { - protected readonly productVariantRepository_: DAL.RepositoryService +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ProductTypes.CreateProductVariantOnlyDTO + update: ProductVariantServiceTypes.UpdateProductVariantDTO + } +>(ProductVariant) { + protected readonly productVariantRepository_: DAL.RepositoryService protected readonly productService_: ProductService constructor({ productVariantRepository, productService, }: InjectedDependencies) { + // @ts-ignore + super(...arguments) this.productVariantRepository_ = productVariantRepository this.productService_ = productService } - @InjectManager("productVariantRepository_") - async retrieve( - productVariantId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity< - ProductVariant, - ProductTypes.ProductVariantDTO - >({ - id: productVariantId, - entityName: ProductVariant.name, - repository: this.productVariantRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("productVariantRepository_") - async list( - filters: ProductTypes.FilterableProductVariantProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.productVariantRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("productVariantRepository_") - async listAndCount( - filters: ProductTypes.FilterableProductVariantProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.productVariantRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - @InjectTransactionManager("productVariantRepository_") - async create( + // @ts-ignore + override async create( productOrId: TProduct | string, data: ProductTypes.CreateProductVariantOnlyDTO[], @MedusaContext() sharedContext: Context = {} @@ -113,15 +67,14 @@ export default class ProductVariantService< }) }) - return (await ( - this.productVariantRepository_ as ProductVariantRepository - ).create(data_, { + return await this.productVariantRepository_.create(data_, { transactionManager: sharedContext.transactionManager, - })) as TEntity[] + }) } @InjectTransactionManager("productVariantRepository_") - async update( + // @ts-ignore + override async update( productOrId: TProduct | string, data: ProductVariantServiceTypes.UpdateProductVariantDTO[], @MedusaContext() sharedContext: Context = {} @@ -139,39 +92,7 @@ export default class ProductVariantService< const variantsData = [...data] variantsData.forEach((variant) => Object.assign(variant, { product })) - return (await ( - this.productVariantRepository_ as ProductVariantRepository - ).update(variantsData, { - transactionManager: sharedContext.transactionManager, - })) as TEntity[] - } - - @InjectTransactionManager("productVariantRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return await this.productVariantRepository_.delete(ids, { - transactionManager: sharedContext.transactionManager, - }) - } - - @InjectTransactionManager("productVariantRepository_") - async softDelete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.productVariantRepository_.softDelete(ids, { - transactionManager: sharedContext.transactionManager, - }) - } - - @InjectTransactionManager("productVariantRepository_") - async restore( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], Record]> { - return await this.productVariantRepository_.restore(ids, { + return await this.productVariantRepository_.update(variantsData, { transactionManager: sharedContext.transactionManager, }) } diff --git a/packages/product/src/services/product.ts b/packages/product/src/services/product.ts index 15d3c010b7..d438fb7513 100644 --- a/packages/product/src/services/product.ts +++ b/packages/product/src/services/product.ts @@ -1,74 +1,35 @@ -import { - Context, - DAL, - FindConfig, - ProductTypes, - WithRequiredProperty, -} from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - isDefined, - MedusaContext, - MedusaError, - ModulesSdkUtils, - ProductUtils, -} from "@medusajs/utils" +import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types" +import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils" import { Product } from "@models" -import { ProductRepository } from "@repositories" - -import { ProductServiceTypes } from "../types/services" +import { ProductServiceTypes } from "@types" type InjectedDependencies = { productRepository: DAL.RepositoryService } -export default class ProductService { - protected readonly productRepository_: DAL.RepositoryService +export default class ProductService< + TEntity extends Product = Product +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: ProductTypes.CreateProductOnlyDTO + update: ProductServiceTypes.UpdateProductDTO + } +>(Product) { + protected readonly productRepository_: DAL.RepositoryService constructor({ productRepository }: InjectedDependencies) { + // @ts-ignore + // eslint-disable-next-line prefer-rest-params + super(...arguments) + this.productRepository_ = productRepository } @InjectManager("productRepository_") - async retrieve( - productId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - if (!isDefined(productId)) { - throw new MedusaError( - MedusaError.Types.NOT_FOUND, - `"productId" must be defined` - ) - } - - const queryOptions = ModulesSdkUtils.buildQuery( - { - id: productId, - }, - config - ) - - const product = await this.productRepository_.find( - queryOptions, - sharedContext - ) - - if (!product?.length) { - throw new MedusaError( - MedusaError.Types.NOT_FOUND, - `Product with id: ${productId} was not found` - ) - } - - return product[0] as TEntity - } - - @InjectManager("productRepository_") - async list( + async list( filters: ProductTypes.FilterableProductProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise { if (filters.category_id) { @@ -84,17 +45,13 @@ export default class ProductService { delete filters.category_id } - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - return (await this.productRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] + return await super.list(filters, config, sharedContext) } @InjectManager("productRepository_") - async listAndCount( + async listAndCount( filters: ProductTypes.FilterableProductProps = {}, - config: FindConfig = {}, + config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ): Promise<[TEntity[], number]> { if (filters.category_id) { @@ -110,76 +67,10 @@ export default class ProductService { delete filters.category_id } - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - return (await this.productRepository_.findAndCount( - queryOptions, + return await super.listAndCount( + filters, + config, sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("productRepository_") - async create( - data: ProductTypes.CreateProductOnlyDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - data.forEach((product) => { - product.status ??= ProductUtils.ProductStatus.DRAFT - }) - - return (await (this.productRepository_ as ProductRepository).create( - data as WithRequiredProperty< - ProductTypes.CreateProductOnlyDTO, - "status" - >[], - { - transactionManager: sharedContext.transactionManager, - } - )) as TEntity[] - } - - @InjectTransactionManager("productRepository_") - async update( - data: ProductServiceTypes.UpdateProductDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.productRepository_ as ProductRepository).update( - data as WithRequiredProperty< - ProductServiceTypes.UpdateProductDTO, - "id" - >[], - { - transactionManager: sharedContext.transactionManager, - } - )) as TEntity[] - } - - @InjectTransactionManager("productRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.productRepository_.delete(ids, { - transactionManager: sharedContext.transactionManager, - }) - } - - @InjectTransactionManager("productRepository_") - async softDelete( - productIds: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], Record]> { - return await this.productRepository_.softDelete(productIds, { - transactionManager: sharedContext.transactionManager, - }) - } - - @InjectTransactionManager("productRepository_") - async restore( - productIds: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], Record]> { - return await this.productRepository_.restore(productIds, { - transactionManager: sharedContext.transactionManager, - }) + ) } } diff --git a/packages/product/src/types/services/index.ts b/packages/product/src/types/services/index.ts index 40c769ce36..efcb994e07 100644 --- a/packages/product/src/types/services/index.ts +++ b/packages/product/src/types/services/index.ts @@ -2,3 +2,4 @@ export * as ProductCategoryServiceTypes from "./product-category" export * as ProductServiceTypes from "./product" export * as ProductVariantServiceTypes from "./product-variant" export * as ProductCollectionServiceTypes from "./product-collection" +export * as ProductOptionValueServiceTypes from "./product-option-value" diff --git a/packages/product/tsconfig.json b/packages/product/tsconfig.json index 213e38fc55..4b79cd6032 100644 --- a/packages/product/tsconfig.json +++ b/packages/product/tsconfig.json @@ -22,7 +22,8 @@ "paths": { "@models": ["./src/models"], "@services": ["./src/services"], - "@repositories": ["./src/repositories"] + "@repositories": ["./src/repositories"], + "@types": ["./src/types"] } }, "include": ["src"], diff --git a/packages/promotion/src/services/application-method.ts b/packages/promotion/src/services/application-method.ts index 250e6c8433..2f0e4d38be 100644 --- a/packages/promotion/src/services/application-method.ts +++ b/packages/promotion/src/services/application-method.ts @@ -1,17 +1,7 @@ -import { Context, DAL, FindConfig, PromotionTypes } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL, PromotionTypes } from "@medusajs/types" import { ApplicationMethod } from "@models" -import { ApplicationMethodRepository } from "@repositories" -import { - CreateApplicationMethodDTO, - UpdateApplicationMethodDTO, -} from "../types" +import { ModulesSdkUtils } from "@medusajs/utils" +import { CreateApplicationMethodDTO, UpdateApplicationMethodDTO } from "@types" type InjectedDependencies = { applicationMethodRepository: DAL.RepositoryService @@ -19,90 +9,19 @@ type InjectedDependencies = { export default class ApplicationMethodService< TEntity extends ApplicationMethod = ApplicationMethod -> { - protected readonly applicationMethodRepository_: DAL.RepositoryService - - constructor({ applicationMethodRepository }: InjectedDependencies) { - this.applicationMethodRepository_ = applicationMethodRepository +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: CreateApplicationMethodDTO + update: UpdateApplicationMethodDTO + }, + { + list: PromotionTypes.FilterableApplicationMethodProps + listAndCount: PromotionTypes.FilterableApplicationMethodProps } - - @InjectManager("applicationMethodRepository_") - async retrieve( - applicationMethodId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity< - ApplicationMethod, - PromotionTypes.ApplicationMethodDTO - >({ - id: applicationMethodId, - entityName: ApplicationMethod.name, - repository: this.applicationMethodRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("applicationMethodRepository_") - async list( - filters: PromotionTypes.FilterableApplicationMethodProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.applicationMethodRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("applicationMethodRepository_") - async listAndCount( - filters: PromotionTypes.FilterableApplicationMethodProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.applicationMethodRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("applicationMethodRepository_") - async create( - data: CreateApplicationMethodDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.applicationMethodRepository_ as ApplicationMethodRepository - ).create(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("applicationMethodRepository_") - async update( - data: UpdateApplicationMethodDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.applicationMethodRepository_ as ApplicationMethodRepository - ).update(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("applicationMethodRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.applicationMethodRepository_.delete(ids, sharedContext) +>(ApplicationMethod) { + constructor(...args: any[]) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/promotion/src/services/campaign-budget.ts b/packages/promotion/src/services/campaign-budget.ts index affef9a89b..269b337787 100644 --- a/packages/promotion/src/services/campaign-budget.ts +++ b/packages/promotion/src/services/campaign-budget.ts @@ -1,13 +1,6 @@ -import { Context, DAL, FindConfig, PromotionTypes } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL, PromotionTypes } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { CampaignBudget } from "@models" -import { CampaignBudgetRepository } from "@repositories" import { CreateCampaignBudgetDTO, UpdateCampaignBudgetDTO } from "../types" type InjectedDependencies = { @@ -16,90 +9,19 @@ type InjectedDependencies = { export default class CampaignBudgetService< TEntity extends CampaignBudget = CampaignBudget -> { - protected readonly campaignBudgetRepository_: DAL.RepositoryService - - constructor({ campaignBudgetRepository }: InjectedDependencies) { - this.campaignBudgetRepository_ = campaignBudgetRepository +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: CreateCampaignBudgetDTO + update: UpdateCampaignBudgetDTO + }, + { + list: PromotionTypes.FilterableCampaignBudgetProps + listAndCount: PromotionTypes.FilterableCampaignBudgetProps } - - @InjectManager("campaignBudgetRepository_") - async retrieve( - campaignBudgetId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity< - CampaignBudget, - PromotionTypes.CampaignBudgetDTO - >({ - id: campaignBudgetId, - entityName: CampaignBudget.name, - repository: this.campaignBudgetRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("campaignBudgetRepository_") - async list( - filters: PromotionTypes.FilterableCampaignBudgetProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.campaignBudgetRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("campaignBudgetRepository_") - async listAndCount( - filters: PromotionTypes.FilterableCampaignBudgetProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.campaignBudgetRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("campaignBudgetRepository_") - async create( - data: CreateCampaignBudgetDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.campaignBudgetRepository_ as CampaignBudgetRepository - ).create(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("campaignBudgetRepository_") - async update( - data: UpdateCampaignBudgetDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.campaignBudgetRepository_ as CampaignBudgetRepository - ).update(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("campaignBudgetRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.campaignBudgetRepository_.delete(ids, sharedContext) +>(CampaignBudget) { + constructor(...args: any[]) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/promotion/src/services/campaign.ts b/packages/promotion/src/services/campaign.ts index e7cf2f6a1d..1f7b83adae 100644 --- a/packages/promotion/src/services/campaign.ts +++ b/packages/promotion/src/services/campaign.ts @@ -1,96 +1,27 @@ -import { Context, DAL, FindConfig, PromotionTypes } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL, PromotionTypes } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { Campaign } from "@models" -import { CampaignRepository } from "@repositories" import { CreateCampaignDTO, UpdateCampaignDTO } from "../types" type InjectedDependencies = { campaignRepository: DAL.RepositoryService } -export default class CampaignService { - protected readonly campaignRepository_: DAL.RepositoryService - - constructor({ campaignRepository }: InjectedDependencies) { - this.campaignRepository_ = campaignRepository +export default class CampaignService< + TEntity extends Campaign = Campaign +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: CreateCampaignDTO + update: UpdateCampaignDTO + }, + { + list: PromotionTypes.FilterableCampaignProps + listAndCount: PromotionTypes.FilterableCampaignProps } - - @InjectManager("campaignRepository_") - async retrieve( - campaignId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: campaignId, - entityName: Campaign.name, - repository: this.campaignRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("campaignRepository_") - async list( - filters: PromotionTypes.FilterableCampaignProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.campaignRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("campaignRepository_") - async listAndCount( - filters: PromotionTypes.FilterableCampaignProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.campaignRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("campaignRepository_") - async create( - data: CreateCampaignDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.campaignRepository_ as CampaignRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("campaignRepository_") - async update( - data: UpdateCampaignDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.campaignRepository_ as CampaignRepository).update( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("campaignRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.campaignRepository_.delete(ids, sharedContext) +>(Campaign) { + constructor(...args: any[]) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/promotion/src/services/promotion-rule-value.ts b/packages/promotion/src/services/promotion-rule-value.ts index e54227f32b..90a0487d94 100644 --- a/packages/promotion/src/services/promotion-rule-value.ts +++ b/packages/promotion/src/services/promotion-rule-value.ts @@ -1,13 +1,6 @@ -import { Context, DAL, FindConfig, PromotionTypes } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL, PromotionTypes } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { PromotionRuleValue } from "@models" -import { PromotionRuleValueRepository } from "@repositories" import { CreatePromotionRuleValueDTO, UpdatePromotionRuleValueDTO, @@ -19,90 +12,19 @@ type InjectedDependencies = { export default class PromotionRuleValueService< TEntity extends PromotionRuleValue = PromotionRuleValue -> { - protected readonly promotionRuleValueRepository_: DAL.RepositoryService - - constructor({ promotionRuleValueRepository }: InjectedDependencies) { - this.promotionRuleValueRepository_ = promotionRuleValueRepository +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: CreatePromotionRuleValueDTO + update: UpdatePromotionRuleValueDTO + }, + { + list: PromotionTypes.FilterablePromotionRuleValueProps + listAndCount: PromotionTypes.FilterablePromotionRuleValueProps } - - @InjectManager("promotionRuleValueRepository_") - async retrieve( - promotionRuleValueId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity< - PromotionRuleValue, - PromotionTypes.PromotionRuleValueDTO - >({ - id: promotionRuleValueId, - entityName: PromotionRuleValue.name, - repository: this.promotionRuleValueRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("promotionRuleValueRepository_") - async list( - filters: PromotionTypes.FilterablePromotionRuleValueProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.promotionRuleValueRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("promotionRuleValueRepository_") - async listAndCount( - filters: PromotionTypes.FilterablePromotionRuleValueProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.promotionRuleValueRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("promotionRuleValueRepository_") - async create( - data: CreatePromotionRuleValueDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.promotionRuleValueRepository_ as PromotionRuleValueRepository - ).create(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("promotionRuleValueRepository_") - async update( - data: UpdatePromotionRuleValueDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.promotionRuleValueRepository_ as PromotionRuleValueRepository - ).update(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("promotionRuleValueRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.promotionRuleValueRepository_.delete(ids, sharedContext) +>(PromotionRuleValue) { + constructor(...args: any[]) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/promotion/src/services/promotion-rule.ts b/packages/promotion/src/services/promotion-rule.ts index 6c8fbd5c24..a8654617c7 100644 --- a/packages/promotion/src/services/promotion-rule.ts +++ b/packages/promotion/src/services/promotion-rule.ts @@ -1,13 +1,6 @@ -import { Context, DAL, FindConfig, PromotionTypes } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL, PromotionTypes } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { PromotionRule } from "@models" -import { PromotionRuleRepository } from "@repositories" import { CreatePromotionRuleDTO, UpdatePromotionRuleDTO } from "../types" type InjectedDependencies = { @@ -16,90 +9,19 @@ type InjectedDependencies = { export default class PromotionRuleService< TEntity extends PromotionRule = PromotionRule -> { - protected readonly promotionRuleRepository_: DAL.RepositoryService - - constructor({ promotionRuleRepository }: InjectedDependencies) { - this.promotionRuleRepository_ = promotionRuleRepository +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: CreatePromotionRuleDTO + update: UpdatePromotionRuleDTO + }, + { + list: PromotionTypes.FilterablePromotionRuleProps + listAndCount: PromotionTypes.FilterablePromotionRuleProps } - - @InjectManager("promotionRuleRepository_") - async retrieve( - promotionRuleId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity< - PromotionRule, - PromotionTypes.PromotionRuleDTO - >({ - id: promotionRuleId, - entityName: PromotionRule.name, - repository: this.promotionRuleRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("promotionRuleRepository_") - async list( - filters: PromotionTypes.FilterablePromotionRuleProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.promotionRuleRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("promotionRuleRepository_") - async listAndCount( - filters: PromotionTypes.FilterablePromotionRuleProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery( - filters, - config - ) - - return (await this.promotionRuleRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("promotionRuleRepository_") - async create( - data: CreatePromotionRuleDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.promotionRuleRepository_ as PromotionRuleRepository - ).create(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("promotionRuleRepository_") - async update( - data: UpdatePromotionRuleDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await ( - this.promotionRuleRepository_ as PromotionRuleRepository - ).update(data, sharedContext)) as TEntity[] - } - - @InjectTransactionManager("promotionRuleRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.promotionRuleRepository_.delete(ids, sharedContext) +>(PromotionRule) { + constructor(...args: any[]) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/promotion/src/services/promotion.ts b/packages/promotion/src/services/promotion.ts index 5461be7df4..74c8e71ba3 100644 --- a/packages/promotion/src/services/promotion.ts +++ b/packages/promotion/src/services/promotion.ts @@ -1,96 +1,27 @@ -import { Context, DAL, FindConfig, PromotionTypes } from "@medusajs/types" -import { - InjectManager, - InjectTransactionManager, - MedusaContext, - ModulesSdkUtils, - retrieveEntity, -} from "@medusajs/utils" +import { DAL, PromotionTypes } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" import { Promotion } from "@models" -import { PromotionRepository } from "@repositories" import { CreatePromotionDTO, UpdatePromotionDTO } from "../types" type InjectedDependencies = { promotionRepository: DAL.RepositoryService } -export default class PromotionService { - protected readonly promotionRepository_: DAL.RepositoryService - - constructor({ promotionRepository }: InjectedDependencies) { - this.promotionRepository_ = promotionRepository +export default class PromotionService< + TEntity extends Promotion = Promotion +> extends ModulesSdkUtils.abstractServiceFactory< + InjectedDependencies, + { + create: CreatePromotionDTO + update: UpdatePromotionDTO + }, + { + list: PromotionTypes.FilterablePromotionProps + listAndCount: PromotionTypes.FilterablePromotionProps } - - @InjectManager("promotionRepository_") - async retrieve( - promotionId: string, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await retrieveEntity({ - id: promotionId, - entityName: Promotion.name, - repository: this.promotionRepository_, - config, - sharedContext, - })) as TEntity - } - - @InjectManager("promotionRepository_") - async list( - filters: PromotionTypes.FilterablePromotionProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.promotionRepository_.find( - queryOptions, - sharedContext - )) as TEntity[] - } - - @InjectManager("promotionRepository_") - async listAndCount( - filters: PromotionTypes.FilterablePromotionProps = {}, - config: FindConfig = {}, - @MedusaContext() sharedContext: Context = {} - ): Promise<[TEntity[], number]> { - const queryOptions = ModulesSdkUtils.buildQuery(filters, config) - - return (await this.promotionRepository_.findAndCount( - queryOptions, - sharedContext - )) as [TEntity[], number] - } - - @InjectTransactionManager("promotionRepository_") - async create( - data: CreatePromotionDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.promotionRepository_ as PromotionRepository).create( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("promotionRepository_") - async update( - data: UpdatePromotionDTO[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - return (await (this.promotionRepository_ as PromotionRepository).update( - data, - sharedContext - )) as TEntity[] - } - - @InjectTransactionManager("promotionRepository_") - async delete( - ids: string[], - @MedusaContext() sharedContext: Context = {} - ): Promise { - await this.promotionRepository_.delete(ids, sharedContext) +>(Promotion) { + constructor(...args: any[]) { + // @ts-ignore + super(...arguments) } } diff --git a/packages/types/src/dal/repository-service.ts b/packages/types/src/dal/repository-service.ts index 483b8d50ff..6e294475c6 100644 --- a/packages/types/src/dal/repository-service.ts +++ b/packages/types/src/dal/repository-service.ts @@ -58,6 +58,8 @@ export interface RepositoryService extends BaseRepositoryService { ids: string[], context?: Context ): Promise<[T[], Record]> + + upsert?(data: unknown[], context?: Context): Promise } export interface TreeRepositoryService @@ -81,7 +83,7 @@ export interface TreeRepositoryService /** * @interface - * + * * An object that is used to specify an entity's related entities that should be soft-deleted when the main entity is soft-deleted. */ export type SoftDeleteReturn = { @@ -93,7 +95,7 @@ export type SoftDeleteReturn = { /** * @interface - * + * * An object that is used to specify an entity's related entities that should be restored when the main entity is restored. */ export type RestoreReturn = { diff --git a/packages/utils/src/dal/mikro-orm/mikro-orm-repository.ts b/packages/utils/src/dal/mikro-orm/mikro-orm-repository.ts index da3f18819c..5adfae04a5 100644 --- a/packages/utils/src/dal/mikro-orm/mikro-orm-repository.ts +++ b/packages/utils/src/dal/mikro-orm/mikro-orm-repository.ts @@ -1,7 +1,7 @@ import { Context, DAL, - FilterQuery as InternalFilerQuery, + FilterQuery as InternalFilterQuery, RepositoryTransformOptions, } from "@medusajs/types" import { @@ -16,9 +16,9 @@ import { EntityName, FilterQuery as MikroFilterQuery, } from "@mikro-orm/core/typings" -import { isString, MedusaError } from "../../common" +import { MedusaError, isString } from "../../common" import { MedusaContext } from "../../decorators" -import { buildQuery, InjectTransactionManager } from "../../modules-sdk" +import { InjectTransactionManager, buildQuery } from "../../modules-sdk" import { getSoftDeletedCascadedEntitiesIdsMappedBy, transactionWrapper, @@ -106,7 +106,7 @@ export class MikroOrmBaseRepository< @InjectTransactionManager() async softDelete( - idsOrFilter: string[] | InternalFilerQuery, + idsOrFilter: string[] | InternalFilterQuery, @MedusaContext() { transactionManager: manager }: Context = {} ): Promise<[T[], Record]> { @@ -138,7 +138,7 @@ export class MikroOrmBaseRepository< @InjectTransactionManager() async restore( - idsOrFilter: string[] | InternalFilerQuery, + idsOrFilter: string[] | InternalFilterQuery, @MedusaContext() { transactionManager: manager }: Context = {} ): Promise<[T[], Record]> { @@ -224,7 +224,7 @@ type DtoBasedMutationMethods = "create" | "update" export function mikroOrmBaseRepositoryFactory< T extends object = object, - TDTos extends { [K in DtoBasedMutationMethods]?: any } = { + TDTOs extends { [K in DtoBasedMutationMethods]?: any } = { [K in DtoBasedMutationMethods]?: any } >(entity: EntityClass | EntitySchema) { @@ -242,11 +242,11 @@ export function mikroOrmBaseRepositoryFactory< static retrievePrimaryKeys(entity: EntityClass | EntitySchema) { return ( (entity as EntitySchema).meta?.primaryKeys ?? - (entity as EntityClass).prototype.__meta.primaryKeys + (entity as EntityClass).prototype.__meta.primaryKeys ?? ["id"] ) } - async create(data: TDTos["create"][], context?: Context): Promise { + async create(data: TDTOs["create"][], context?: Context): Promise { const manager = this.getActiveManager(context) const entities = data.map((data_) => { @@ -261,7 +261,8 @@ export function mikroOrmBaseRepositoryFactory< return entities } - async update(data: TDTos["update"][], context?: Context): Promise { + async update(data: TDTOs["update"][], context?: Context): Promise { + // TODO: Move this logic to the service packages/utils/src/modules-sdk/abstract-service-factory.ts const manager = this.getActiveManager(context) const primaryKeys = diff --git a/packages/utils/src/modules-sdk/abstract-service-factory.ts b/packages/utils/src/modules-sdk/abstract-service-factory.ts new file mode 100644 index 0000000000..b176d6ff45 --- /dev/null +++ b/packages/utils/src/modules-sdk/abstract-service-factory.ts @@ -0,0 +1,245 @@ +import { + Context, + FilterQuery as InternalFilterQuery, + FindConfig, +} from "@medusajs/types" +import { EntitySchema } from "@mikro-orm/core" +import { EntityClass } from "@mikro-orm/core/typings" +import { + doNotForceTransaction, + isDefined, + isString, + lowerCaseFirst, + MedusaError, + shouldForceTransaction, + upperCaseFirst, +} from "../common" +import { MedusaContext } from "../decorators" +import { buildQuery } from "./build-query" +import { InjectManager, InjectTransactionManager } from "./decorators" + +/** + * Utility factory and interfaces for internal module services + */ + +type FilterableMethods = "list" | "listAndCount" +type Methods = "create" | "update" + +export interface AbstractService< + TEntity extends {}, + TContainer extends object = object, + TDTOs extends { [K in Methods]?: any } = { [K in Methods]?: any }, + TFilters extends { [K in FilterableMethods]?: any } = { + [K in FilterableMethods]?: any + } +> { + get __container__(): TContainer + + retrieve( + id: string, + config?: FindConfig, + sharedContext?: Context + ): Promise + list( + filters?: TFilters["list"], + config?: FindConfig, + sharedContext?: Context + ): Promise + listAndCount( + filters?: TFilters["listAndCount"], + config?: FindConfig, + sharedContext?: Context + ): Promise<[TEntity[], number]> + create(data: TDTOs["create"][], sharedContext?: Context): Promise + update(data: TDTOs["update"][], sharedContext?: Context): Promise + delete( + primaryKeyValues: string[] | object[], + sharedContext?: Context + ): Promise + softDelete( + idsOrFilter: string[] | InternalFilterQuery, + sharedContext?: Context + ): Promise<[TEntity[], Record]> + restore( + idsOrFilter: string[] | InternalFilterQuery, + sharedContext?: Context + ): Promise<[TEntity[], Record]> +} + +export function abstractServiceFactory< + TContainer extends object = object, + TDTOs extends { [K in Methods]?: any } = { [K in Methods]?: any }, + TFilters extends { [K in FilterableMethods]?: any } = { + [K in FilterableMethods]?: any + } +>( + model: new (...args: any[]) => any +): { + new (container: TContainer): AbstractService< + TEntity, + TContainer, + TDTOs, + TFilters + > +} { + const injectedRepositoryName = `${lowerCaseFirst(model.name)}Repository` + const propertyRepositoryName = `__${injectedRepositoryName}__` + + class AbstractService_ + implements AbstractService + { + readonly __container__: TContainer; + [key: string]: any + + constructor(container: TContainer) { + this.__container__ = container + this[propertyRepositoryName] = container[injectedRepositoryName] + } + + static retrievePrimaryKeys(entity: EntityClass | EntitySchema) { + return ( + (entity as EntitySchema).meta?.primaryKeys ?? + (entity as EntityClass).prototype.__meta?.primaryKeys ?? ["id"] + ) + } + + @InjectManager(propertyRepositoryName) + async retrieve( + primaryKeyValues: string | string[] | object[], + config: FindConfig = {}, + @MedusaContext() sharedContext: Context = {} + ): Promise { + const primaryKeys = AbstractService_.retrievePrimaryKeys(model) + + if (!isDefined(primaryKeyValues)) { + throw new MedusaError( + MedusaError.Types.NOT_FOUND, + `${ + primaryKeys.length === 1 + ? `"${ + lowerCaseFirst(model.name) + upperCaseFirst(primaryKeys[0]) + }"` + : `${lowerCaseFirst(model.name)} ${primaryKeys.join(", ")}` + } must be defined` + ) + } + + let primaryKeysCriteria = {} + if (primaryKeys.length === 1) { + primaryKeysCriteria[primaryKeys[0]] = primaryKeyValues + } else { + primaryKeysCriteria = (primaryKeyValues as string[] | object[]).map( + (primaryKeyValue) => ({ + $and: primaryKeys.map((key) => ({ [key]: primaryKeyValue[key] })), + }) + ) + } + + const queryOptions = buildQuery(primaryKeysCriteria, config) + + const entities = await this[propertyRepositoryName].find( + queryOptions, + sharedContext + ) + + if (!entities?.length) { + throw new MedusaError( + MedusaError.Types.NOT_FOUND, + `${model.name} with ${primaryKeys.join(", ")}: ${ + Array.isArray(primaryKeyValues) + ? primaryKeyValues.map((v) => + [isString(v) ? v : Object.values(v)].join(", ") + ) + : primaryKeyValues + } was not found` + ) + } + + return entities[0] + } + + @InjectManager(propertyRepositoryName) + async list( + filters: TFilters["list"] = {}, + config: FindConfig = {}, + @MedusaContext() sharedContext: Context = {} + ): Promise { + const queryOptions = buildQuery(filters, config) + + return (await this[propertyRepositoryName].find( + queryOptions, + sharedContext + )) as TEntity[] + } + + @InjectManager(propertyRepositoryName) + async listAndCount( + filters: TFilters["listAndCount"] = {}, + config: FindConfig = {}, + @MedusaContext() sharedContext: Context = {} + ): Promise<[TEntity[], number]> { + const queryOptions = buildQuery(filters, config) + + return (await this[propertyRepositoryName].findAndCount( + queryOptions, + sharedContext + )) as [TEntity[], number] + } + + @InjectTransactionManager(shouldForceTransaction, propertyRepositoryName) + async create( + data: TDTOs["create"][], + @MedusaContext() sharedContext: Context = {} + ): Promise { + return (await this[propertyRepositoryName].create( + data, + sharedContext + )) as TEntity[] + } + + @InjectTransactionManager(shouldForceTransaction, propertyRepositoryName) + async update( + data: TDTOs["update"][], + @MedusaContext() sharedContext: Context = {} + ): Promise { + return (await this[propertyRepositoryName].update( + data, + sharedContext + )) as TEntity[] + } + + @InjectTransactionManager(doNotForceTransaction, propertyRepositoryName) + async delete( + primaryKeyValues: string[] | object[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + await this[propertyRepositoryName].delete(primaryKeyValues, sharedContext) + } + + @InjectTransactionManager(propertyRepositoryName) + async softDelete( + idsOrFilter: string[] | InternalFilterQuery, + @MedusaContext() sharedContext: Context = {} + ): Promise<[TEntity[], Record]> { + return await this[propertyRepositoryName].softDelete( + idsOrFilter, + sharedContext + ) + } + + @InjectTransactionManager(propertyRepositoryName) + async restore( + idsOrFilter: string[] | InternalFilterQuery, + @MedusaContext() sharedContext: Context = {} + ): Promise<[TEntity[], Record]> { + return await this[propertyRepositoryName].restore( + idsOrFilter, + sharedContext + ) + } + } + + return AbstractService_ as unknown as new ( + container: TContainer + ) => AbstractService +} diff --git a/packages/utils/src/modules-sdk/index.ts b/packages/utils/src/modules-sdk/index.ts index 96948c7bff..b63a859db6 100644 --- a/packages/utils/src/modules-sdk/index.ts +++ b/packages/utils/src/modules-sdk/index.ts @@ -1,7 +1,7 @@ export * from "./load-module-database-config" export * from "./decorators" export * from "./build-query" -export * from "./retrieve-entity" export * from "./loaders/mikro-orm-connection-loader" export * from "./create-pg-connection" export * from "./migration-scripts" +export * from "./abstract-service-factory" diff --git a/packages/utils/src/modules-sdk/retrieve-entity.ts b/packages/utils/src/modules-sdk/retrieve-entity.ts deleted file mode 100644 index 62f68a06a2..0000000000 --- a/packages/utils/src/modules-sdk/retrieve-entity.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Context, DAL, FindConfig } from "@medusajs/types" -import { - MedusaError, - isDefined, - lowerCaseFirst, - upperCaseFirst, -} from "../common" -import { buildQuery } from "./build-query" - -type RetrieveEntityParams = { - id: string - identifierColumn?: string - entityName: string - repository: DAL.TreeRepositoryService | DAL.RepositoryService - config: FindConfig - sharedContext?: Context -} - -export async function retrieveEntity({ - id, - identifierColumn = "id", - entityName, - repository, - config = {}, - sharedContext, -}: RetrieveEntityParams): Promise { - if (!isDefined(id)) { - throw new MedusaError( - MedusaError.Types.NOT_FOUND, - `"${lowerCaseFirst(entityName)}${upperCaseFirst( - identifierColumn - )}" must be defined` - ) - } - - const queryOptions = buildQuery( - { - [identifierColumn]: id, - }, - config - ) - - const entities = await repository.find(queryOptions, sharedContext) - - if (!entities?.length) { - throw new MedusaError( - MedusaError.Types.NOT_FOUND, - `${entityName} with ${identifierColumn}: ${id} was not found` - ) - } - - return entities[0] -}