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>
This commit is contained in:
co-authored by
Oli Juhl
parent
80feb972cb
commit
130c641e5c
@@ -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<Cart[]> {
|
||||
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||
|
||||
const entities = data.map(({ cart, update }) => {
|
||||
return manager.assign(cart, update)
|
||||
})
|
||||
|
||||
manager.persist(entities)
|
||||
|
||||
return entities
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TEntity extends Address = Address> {
|
||||
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<AddressDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity> {
|
||||
return (await retrieveEntity<Address, AddressDTO>({
|
||||
id: id,
|
||||
entityName: Address.name,
|
||||
repository: this.addressRepository_,
|
||||
config,
|
||||
sharedContext,
|
||||
})) as TEntity
|
||||
}
|
||||
|
||||
@InjectManager("addressRepository_")
|
||||
async list(
|
||||
filters: FilterableAddressProps = {},
|
||||
config: FindConfig<CartAddressDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[]> {
|
||||
const queryOptions = ModulesSdkUtils.buildQuery<Address>(filters, config)
|
||||
|
||||
return (await this.addressRepository_.find(
|
||||
queryOptions,
|
||||
sharedContext
|
||||
)) as TEntity[]
|
||||
}
|
||||
|
||||
@InjectManager("addressRepository_")
|
||||
async listAndCount(
|
||||
filters: FilterableAddressProps = {},
|
||||
config: FindConfig<AddressDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<[TEntity[], number]> {
|
||||
const queryOptions = ModulesSdkUtils.buildQuery<Address>(filters, config)
|
||||
|
||||
return (await this.addressRepository_.findAndCount(
|
||||
queryOptions,
|
||||
sharedContext
|
||||
)) as [TEntity[], number]
|
||||
}
|
||||
|
||||
@InjectTransactionManager("addressRepository_")
|
||||
async create(
|
||||
data: CreateAddressDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[]> {
|
||||
return (await (this.addressRepository_ as AddressRepository).create(
|
||||
data,
|
||||
sharedContext
|
||||
)) as TEntity[]
|
||||
}
|
||||
|
||||
@InjectTransactionManager("addressRepository_")
|
||||
async update(
|
||||
data: UpdateAddressDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[]> {
|
||||
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<void> {
|
||||
await this.addressRepository_.delete(ids, sharedContext)
|
||||
>(Address)<TEntity> {
|
||||
constructor(container: InjectedDependencies) {
|
||||
// @ts-ignore
|
||||
super(...arguments)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TEntity extends Cart = Cart> {
|
||||
protected readonly cartRepository_: DAL.RepositoryService
|
||||
|
||||
export default class CartService<
|
||||
TEntity extends Cart = Cart
|
||||
> extends ModulesSdkUtils.abstractServiceFactory<
|
||||
InjectedDependencies,
|
||||
{
|
||||
create: CreateCartDTO
|
||||
update: UpdateCartDTO
|
||||
}
|
||||
>(Cart)<TEntity> {
|
||||
constructor({ cartRepository }: InjectedDependencies) {
|
||||
this.cartRepository_ = cartRepository
|
||||
}
|
||||
|
||||
@InjectManager("cartRepository_")
|
||||
async retrieve(
|
||||
id: string,
|
||||
config: FindConfig<CartDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity> {
|
||||
return (await retrieveEntity<Cart, CartDTO>({
|
||||
id: id,
|
||||
entityName: Cart.name,
|
||||
repository: this.cartRepository_,
|
||||
config,
|
||||
sharedContext,
|
||||
})) as TEntity
|
||||
}
|
||||
|
||||
@InjectManager("cartRepository_")
|
||||
async list(
|
||||
filters: FilterableCartProps = {},
|
||||
config: FindConfig<CartDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[]> {
|
||||
const queryOptions = ModulesSdkUtils.buildQuery<Cart>(filters, config)
|
||||
|
||||
return (await this.cartRepository_.find(
|
||||
queryOptions,
|
||||
sharedContext
|
||||
)) as TEntity[]
|
||||
}
|
||||
|
||||
@InjectManager("cartRepository_")
|
||||
async listAndCount(
|
||||
filters: FilterableCartProps = {},
|
||||
config: FindConfig<CartDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<[TEntity[], number]> {
|
||||
const queryOptions = ModulesSdkUtils.buildQuery<Cart>(filters, config)
|
||||
|
||||
return (await this.cartRepository_.findAndCount(
|
||||
queryOptions,
|
||||
sharedContext
|
||||
)) as [TEntity[], number]
|
||||
}
|
||||
|
||||
@InjectTransactionManager("cartRepository_")
|
||||
async create(
|
||||
data: CreateCartDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[]> {
|
||||
return (await (this.cartRepository_ as CartRepository).create(
|
||||
data,
|
||||
sharedContext
|
||||
)) as TEntity[]
|
||||
}
|
||||
|
||||
@InjectTransactionManager("cartRepository_")
|
||||
async update(
|
||||
data: UpdateCartDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[]> {
|
||||
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<void> {
|
||||
await this.cartRepository_.delete(ids, sharedContext)
|
||||
// @ts-ignore
|
||||
super(...arguments)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TEntity extends LineItem = LineItem> {
|
||||
protected readonly lineItemRepository_: DAL.RepositoryService<LineItem>
|
||||
|
||||
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<CartLineItemDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity> {
|
||||
return (await retrieveEntity<LineItem, CartLineItemDTO>({
|
||||
id: id,
|
||||
entityName: LineItem.name,
|
||||
repository: this.lineItemRepository_,
|
||||
config,
|
||||
sharedContext,
|
||||
})) as TEntity
|
||||
}
|
||||
|
||||
@InjectManager("lineItemRepository_")
|
||||
async list(
|
||||
filters: FilterableLineItemProps = {},
|
||||
config: FindConfig<CartLineItemDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[]> {
|
||||
const queryOptions = ModulesSdkUtils.buildQuery<LineItem>(filters, config)
|
||||
|
||||
return (await this.lineItemRepository_.find(
|
||||
queryOptions,
|
||||
sharedContext
|
||||
)) as TEntity[]
|
||||
}
|
||||
|
||||
@InjectManager("lineItemRepository_")
|
||||
async listAndCount(
|
||||
filters: FilterableLineItemProps = {},
|
||||
config: FindConfig<CartLineItemDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<[TEntity[], number]> {
|
||||
const queryOptions = ModulesSdkUtils.buildQuery<LineItem>(filters, config)
|
||||
|
||||
return (await this.lineItemRepository_.findAndCount(
|
||||
queryOptions,
|
||||
sharedContext
|
||||
)) as [TEntity[], number]
|
||||
}
|
||||
|
||||
@InjectTransactionManager("lineItemRepository_")
|
||||
async create(
|
||||
data: CreateLineItemDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[]> {
|
||||
return (await (this.lineItemRepository_ as LineItemRepository).create(
|
||||
data,
|
||||
sharedContext
|
||||
)) as TEntity[]
|
||||
}
|
||||
|
||||
@InjectTransactionManager("lineItemRepository_")
|
||||
async update(
|
||||
data: UpdateLineItemDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[]> {
|
||||
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<void> {
|
||||
await this.lineItemRepository_.delete(ids, sharedContext)
|
||||
}
|
||||
}
|
||||
>(LineItem)<TEntity> {}
|
||||
|
||||
Reference in New Issue
Block a user