Merge branch 'develop' into feat/payment-module-models
# Conflicts: # packages/payment/src/models/index.ts # packages/payment/src/models/payment.ts
This commit is contained in:
commit
b601212398
20 files changed
+847
-33
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/types": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat(cart): Add CartService and AddressService
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
export const defaultCartsData = [
|
||||||
|
{
|
||||||
|
id: "cart-id-1",
|
||||||
|
region_id: "region-id-1",
|
||||||
|
customer_id: "customer-id-1",
|
||||||
|
email: "test@email.com",
|
||||||
|
currency_code: "usd",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "cart-id-2",
|
||||||
|
region_id: "region-id-1",
|
||||||
|
customer_id: "customer-id-1",
|
||||||
|
shipping_address: {
|
||||||
|
first_name: "Tony",
|
||||||
|
last_name: "Stark",
|
||||||
|
},
|
||||||
|
billing_address_id: {
|
||||||
|
address_1: "Stark Industries",
|
||||||
|
city: "New York",
|
||||||
|
},
|
||||||
|
currency_code: "usd",
|
||||||
|
},
|
||||||
|
]
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { CreateCartDTO } from "@medusajs/types"
|
||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
import { Cart } from "../../../src/models"
|
||||||
|
import { defaultCartsData } from "./data"
|
||||||
|
|
||||||
|
export * from "./data"
|
||||||
|
|
||||||
|
export async function createCarts(
|
||||||
|
manager: SqlEntityManager,
|
||||||
|
cartsData: CreateCartDTO[] = defaultCartsData
|
||||||
|
): Promise<Cart[]> {
|
||||||
|
const carts: Cart[] = []
|
||||||
|
|
||||||
|
for (let cartData of cartsData) {
|
||||||
|
let cart = manager.create(Cart, cartData)
|
||||||
|
|
||||||
|
await manager.persistAndFlush(cart)
|
||||||
|
}
|
||||||
|
|
||||||
|
return carts
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
import { AddressRepository } from "../../../../src/repositories"
|
||||||
|
import { AddressService } from "../../../../src/services"
|
||||||
|
import { MikroOrmWrapper } from "../../../utils"
|
||||||
|
|
||||||
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
|
describe("Address Service", () => {
|
||||||
|
let service: AddressService
|
||||||
|
let testManager: SqlEntityManager
|
||||||
|
let repositoryManager: SqlEntityManager
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await MikroOrmWrapper.setupDatabase()
|
||||||
|
repositoryManager = await MikroOrmWrapper.forkManager()
|
||||||
|
testManager = await MikroOrmWrapper.forkManager()
|
||||||
|
|
||||||
|
const addressRepository = new AddressRepository({
|
||||||
|
manager: repositoryManager,
|
||||||
|
})
|
||||||
|
|
||||||
|
service = new AddressService({
|
||||||
|
addressRepository: addressRepository,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await MikroOrmWrapper.clearDatabase()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("create", () => {
|
||||||
|
it("should create an address successfully", async () => {
|
||||||
|
const [createdAddress] = await service.create([
|
||||||
|
{
|
||||||
|
first_name: "John",
|
||||||
|
last_name: "Doe",
|
||||||
|
address_1: "Test street 1",
|
||||||
|
city: "Test city",
|
||||||
|
country_code: "US",
|
||||||
|
postal_code: "12345",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const [address] = await service.list({ id: [createdAddress.id] })
|
||||||
|
|
||||||
|
expect(address).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: createdAddress.id,
|
||||||
|
first_name: "John",
|
||||||
|
last_name: "Doe",
|
||||||
|
address_1: "Test street 1",
|
||||||
|
city: "Test city",
|
||||||
|
country_code: "US",
|
||||||
|
postal_code: "12345",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("update", () => {
|
||||||
|
it("should throw an error if address does not exist", async () => {
|
||||||
|
const error = await service
|
||||||
|
.update([
|
||||||
|
{
|
||||||
|
id: "none-existing",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.catch((e) => e)
|
||||||
|
|
||||||
|
expect(error.message).toContain(
|
||||||
|
"Address with id \"none-existing\" not found"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should update an address successfully", async () => {
|
||||||
|
const [createdAddress] = await service.create([
|
||||||
|
{
|
||||||
|
first_name: "Jane",
|
||||||
|
last_name: "Doe",
|
||||||
|
address_1: "Test street 1",
|
||||||
|
city: "Test city",
|
||||||
|
country_code: "US",
|
||||||
|
postal_code: "12345",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
await service.update([
|
||||||
|
{
|
||||||
|
id: createdAddress.id,
|
||||||
|
address_1: "Test street 2",
|
||||||
|
city: "Test city 2",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const [address] = await service.list({ id: [createdAddress.id] })
|
||||||
|
|
||||||
|
expect(address).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: createdAddress.id,
|
||||||
|
first_name: "Jane",
|
||||||
|
last_name: "Doe",
|
||||||
|
address_1: "Test street 2",
|
||||||
|
city: "Test city 2",
|
||||||
|
country_code: "US",
|
||||||
|
postal_code: "12345",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("delete", () => {
|
||||||
|
it("should delete a cart successfully", async () => {
|
||||||
|
const [createdAddress] = await service.create([
|
||||||
|
{
|
||||||
|
first_name: "Jane",
|
||||||
|
last_name: "Doe",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
await service.delete([createdAddress.id])
|
||||||
|
|
||||||
|
const carts = await service.list({ id: [createdAddress.id] })
|
||||||
|
|
||||||
|
expect(carts.length).toEqual(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
import { CartRepository } from "../../../../src/repositories"
|
||||||
|
import { CartService } from "../../../../src/services"
|
||||||
|
import { createCarts } from "../../../__fixtures__/cart"
|
||||||
|
import { MikroOrmWrapper } from "../../../utils"
|
||||||
|
|
||||||
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
|
describe("Cart Service", () => {
|
||||||
|
let service: CartService
|
||||||
|
let testManager: SqlEntityManager
|
||||||
|
let repositoryManager: SqlEntityManager
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await MikroOrmWrapper.setupDatabase()
|
||||||
|
repositoryManager = await MikroOrmWrapper.forkManager()
|
||||||
|
testManager = await MikroOrmWrapper.forkManager()
|
||||||
|
|
||||||
|
const cartRepository = new CartRepository({
|
||||||
|
manager: repositoryManager,
|
||||||
|
})
|
||||||
|
|
||||||
|
service = new CartService({
|
||||||
|
cartRepository: cartRepository,
|
||||||
|
})
|
||||||
|
|
||||||
|
await createCarts(testManager)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await MikroOrmWrapper.clearDatabase()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("create", () => {
|
||||||
|
it("should throw an error when required params are not passed", async () => {
|
||||||
|
const error = await service
|
||||||
|
.create([
|
||||||
|
{
|
||||||
|
email: "test@email.com",
|
||||||
|
} as any,
|
||||||
|
])
|
||||||
|
.catch((e) => e)
|
||||||
|
|
||||||
|
expect(error.message).toContain(
|
||||||
|
"Value for Cart.currency_code is required, 'undefined' found"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should create a cart successfully", async () => {
|
||||||
|
const [createdCart] = await service.create([
|
||||||
|
{
|
||||||
|
currency_code: "eur",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const [cart] = await service.list({ id: [createdCart.id] })
|
||||||
|
|
||||||
|
expect(cart).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: createdCart.id,
|
||||||
|
currency_code: "eur",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("update", () => {
|
||||||
|
it("should throw an error if cart does not exist", async () => {
|
||||||
|
const error = await service
|
||||||
|
.update([
|
||||||
|
{
|
||||||
|
id: "none-existing",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.catch((e) => e)
|
||||||
|
|
||||||
|
expect(error.message).toContain(
|
||||||
|
"Cart with id \"none-existing\" not found"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should update a cart successfully", async () => {
|
||||||
|
const [createdCart] = await service.create([
|
||||||
|
{
|
||||||
|
currency_code: "eur",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const [updatedCart] = await service.update([
|
||||||
|
|
||||||
|
{
|
||||||
|
id: createdCart.id,
|
||||||
|
email: "test@email.com",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const [cart] = await service.list({ id: [createdCart.id] })
|
||||||
|
|
||||||
|
expect(cart).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: createdCart.id,
|
||||||
|
currency_code: "eur",
|
||||||
|
email: updatedCart.email,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("delete", () => {
|
||||||
|
it("should delete a cart successfully", async () => {
|
||||||
|
const [createdCart] = await service.create([
|
||||||
|
{
|
||||||
|
currency_code: "eur",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
await service.delete([createdCart.id])
|
||||||
|
|
||||||
|
const carts = await service.list({ id: [createdCart.id] })
|
||||||
|
|
||||||
|
expect(carts.length).toEqual(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -67,12 +67,13 @@ export default class Cart {
|
|||||||
metadata?: Record<string, unknown> | null
|
metadata?: Record<string, unknown> | null
|
||||||
|
|
||||||
@OneToMany(() => LineItem, (lineItem) => lineItem.cart, {
|
@OneToMany(() => LineItem, (lineItem) => lineItem.cart, {
|
||||||
orphanRemoval: true,
|
cascade: [Cascade.REMOVE],
|
||||||
})
|
})
|
||||||
items = new Collection<LineItem>(this)
|
items = new Collection<LineItem>(this)
|
||||||
|
|
||||||
@OneToMany(() => ShippingMethod, (shippingMethod) => shippingMethod.cart, {
|
@OneToMany(() => ShippingMethod, (shippingMethod) => shippingMethod.cart, {
|
||||||
orphanRemoval: true,
|
cascade: [Cascade.REMOVE],
|
||||||
|
|
||||||
})
|
})
|
||||||
shipping_methods = new Collection<ShippingMethod>(this)
|
shipping_methods = new Collection<ShippingMethod>(this)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Context } from "@medusajs/types"
|
||||||
|
import { DALUtils } from "@medusajs/utils"
|
||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
import { Address } from "@models"
|
||||||
|
import { CreateAddressDTO, UpdateAddressDTO } from "../types"
|
||||||
|
|
||||||
|
export class AddressRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
|
||||||
|
Address,
|
||||||
|
{
|
||||||
|
create: CreateAddressDTO
|
||||||
|
}
|
||||||
|
>(Address) {
|
||||||
|
async update(
|
||||||
|
data: { address: Address; update: UpdateAddressDTO }[],
|
||||||
|
context: Context = {}
|
||||||
|
): Promise<Address[]> {
|
||||||
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
|
||||||
|
const entities = data.map(({ address, update }) => {
|
||||||
|
return manager.assign(address, update)
|
||||||
|
})
|
||||||
|
|
||||||
|
manager.persist(entities)
|
||||||
|
|
||||||
|
return entities
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
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"
|
||||||
|
|
||||||
|
export class CartRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
|
||||||
|
Cart,
|
||||||
|
{
|
||||||
|
create: CreateCartDTO
|
||||||
|
}
|
||||||
|
>(Cart) {
|
||||||
|
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 +1,4 @@
|
|||||||
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
|
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
|
||||||
|
export * from "./address"
|
||||||
|
export * from "./cart"
|
||||||
|
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
import {
|
||||||
|
AddressDTO,
|
||||||
|
Context,
|
||||||
|
DAL,
|
||||||
|
FilterableAddressProps,
|
||||||
|
FindConfig,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import {
|
||||||
|
InjectManager,
|
||||||
|
InjectTransactionManager,
|
||||||
|
MedusaContext,
|
||||||
|
MedusaError,
|
||||||
|
ModulesSdkUtils,
|
||||||
|
retrieveEntity,
|
||||||
|
} from "@medusajs/utils"
|
||||||
|
import { Address } from "@models"
|
||||||
|
import { AddressRepository } from "../repositories/address"
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
@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<AddressDTO> = {},
|
||||||
|
@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: { address: Address; update: 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({ address, update })
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +1,35 @@
|
|||||||
import {
|
import {
|
||||||
|
CartDTO,
|
||||||
|
Context,
|
||||||
|
CreateCartDTO,
|
||||||
DAL,
|
DAL,
|
||||||
|
FilterableCartProps,
|
||||||
|
FindConfig,
|
||||||
|
ICartModuleService,
|
||||||
InternalModuleDeclaration,
|
InternalModuleDeclaration,
|
||||||
ModuleJoinerConfig,
|
ModuleJoinerConfig,
|
||||||
|
UpdateCartDTO,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
|
|
||||||
import { Cart } from "@models"
|
import {
|
||||||
|
InjectManager,
|
||||||
|
InjectTransactionManager,
|
||||||
|
MedusaContext,
|
||||||
|
} from "@medusajs/utils"
|
||||||
import { joinerConfig } from "../joiner-config"
|
import { joinerConfig } from "../joiner-config"
|
||||||
|
import AddressService from "./address"
|
||||||
|
import CartService from "./cart"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
baseRepository: DAL.RepositoryService
|
baseRepository: DAL.RepositoryService
|
||||||
|
cartService: CartService
|
||||||
|
addressService: AddressService
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement ICartModuleService from @medusajs/types
|
export default class CartModuleService implements ICartModuleService {
|
||||||
export default class CartModuleService<TCart extends Cart = Cart> {
|
|
||||||
protected baseRepository_: DAL.RepositoryService
|
protected baseRepository_: DAL.RepositoryService
|
||||||
|
protected cartService_: CartService
|
||||||
|
protected addressService_: AddressService
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
{ baseRepository }: InjectedDependencies,
|
{ baseRepository }: InjectedDependencies,
|
||||||
@@ -26,4 +41,138 @@ export default class CartModuleService<TCart extends Cart = Cart> {
|
|||||||
__joinerConfig(): ModuleJoinerConfig {
|
__joinerConfig(): ModuleJoinerConfig {
|
||||||
return joinerConfig
|
return joinerConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async retrieve(
|
||||||
|
id: string,
|
||||||
|
config: FindConfig<CartDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<CartDTO> {
|
||||||
|
const cart = await this.cartService_.retrieve(id, config, sharedContext)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<CartDTO>(cart, {
|
||||||
|
populate: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async list(
|
||||||
|
filters: FilterableCartProps = {},
|
||||||
|
config: FindConfig<CartDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<CartDTO[]> {
|
||||||
|
const carts = await this.cartService_.list(filters, config, sharedContext)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<CartDTO[]>(carts, {
|
||||||
|
populate: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async listAndCount(
|
||||||
|
filters: FilterableCartProps = {},
|
||||||
|
config: FindConfig<CartDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<[CartDTO[], number]> {
|
||||||
|
const [carts, count] = await this.cartService_.listAndCount(
|
||||||
|
filters,
|
||||||
|
config,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
return [
|
||||||
|
await this.baseRepository_.serialize<CartDTO[]>(carts, {
|
||||||
|
populate: true,
|
||||||
|
}),
|
||||||
|
count,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(
|
||||||
|
data: CreateCartDTO[],
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<CartDTO[]>
|
||||||
|
|
||||||
|
async create(data: CreateCartDTO, sharedContext?: Context): Promise<CartDTO>
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async create(
|
||||||
|
data: CreateCartDTO[] | CreateCartDTO,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<CartDTO[] | CartDTO> {
|
||||||
|
const input = Array.isArray(data) ? data : [data]
|
||||||
|
|
||||||
|
const carts = await this.create_(input, sharedContext)
|
||||||
|
|
||||||
|
const result = await this.list(
|
||||||
|
{ id: carts.map((p) => p!.id) },
|
||||||
|
{
|
||||||
|
relations: ["shipping_address", "billing_address"],
|
||||||
|
},
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
return (Array.isArray(data) ? result : result[0]) as CartDTO | CartDTO[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
protected async create_(
|
||||||
|
data: CreateCartDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
) {
|
||||||
|
return await this.cartService_.create(data, sharedContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(
|
||||||
|
data: UpdateCartDTO[],
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<CartDTO[]>
|
||||||
|
|
||||||
|
async update(data: UpdateCartDTO, sharedContext?: Context): Promise<CartDTO>
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async update(
|
||||||
|
data: UpdateCartDTO[] | UpdateCartDTO,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<CartDTO[] | CartDTO> {
|
||||||
|
const input = Array.isArray(data) ? data : [data]
|
||||||
|
const carts = await this.update_(input, sharedContext)
|
||||||
|
|
||||||
|
const result = await this.list(
|
||||||
|
{ id: carts.map((p) => p!.id) },
|
||||||
|
{
|
||||||
|
relations: ["shipping_address", "billing_address"],
|
||||||
|
},
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
return (Array.isArray(data) ? result : result[0]) as CartDTO | CartDTO[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
protected async update_(
|
||||||
|
data: UpdateCartDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
) {
|
||||||
|
return await this.cartService_.update(data, sharedContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(
|
||||||
|
ids: string[],
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<void>
|
||||||
|
|
||||||
|
async delete(
|
||||||
|
ids: string,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<void>
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
async delete(
|
||||||
|
ids: string[] | string,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
const cartIds = Array.isArray(ids) ? ids : [ids]
|
||||||
|
await this.cartService_.delete(cartIds, sharedContext)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
import {
|
||||||
|
CartDTO,
|
||||||
|
Context,
|
||||||
|
DAL,
|
||||||
|
FilterableCartProps,
|
||||||
|
FindConfig,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import {
|
||||||
|
InjectManager,
|
||||||
|
InjectTransactionManager,
|
||||||
|
MedusaContext,
|
||||||
|
MedusaError,
|
||||||
|
ModulesSdkUtils,
|
||||||
|
retrieveEntity,
|
||||||
|
} 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
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
export { default as CartModuleService } from "./cart-module";
|
export { default as AddressService } from "./address"
|
||||||
|
export { default as CartService } from "./cart"
|
||||||
|
export { default as CartModuleService } from "./cart-module"
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export interface UpsertAddressDTO {
|
||||||
|
customer_id?: string
|
||||||
|
company?: string
|
||||||
|
first_name?: string
|
||||||
|
last_name?: string
|
||||||
|
address_1?: string
|
||||||
|
address_2?: string
|
||||||
|
city?: string
|
||||||
|
country_code?: string
|
||||||
|
province?: string
|
||||||
|
postal_code?: string
|
||||||
|
phone?: string
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateAddressDTO extends UpsertAddressDTO {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateAddressDTO extends UpsertAddressDTO {}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export interface CreateCartDTO {
|
||||||
|
region_id?: string
|
||||||
|
customer_id?: string
|
||||||
|
sales_channel_id?: string
|
||||||
|
email?: string
|
||||||
|
currency_code: string
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateCartDTO {
|
||||||
|
id: string
|
||||||
|
region_id?: string
|
||||||
|
customer_id?: string
|
||||||
|
sales_channel_id?: string
|
||||||
|
email?: string
|
||||||
|
currency_code?: string
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
import { Logger } from "@medusajs/types"
|
import { Logger } from "@medusajs/types"
|
||||||
|
export * from "./address"
|
||||||
|
export * from "./cart"
|
||||||
|
|
||||||
export type InitializeModuleInjectableDependencies = {
|
export type InitializeModuleInjectableDependencies = {
|
||||||
logger?: Logger
|
logger?: Logger
|
||||||
|
|||||||
@@ -22,7 +22,8 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"@models": ["./src/models"],
|
"@models": ["./src/models"],
|
||||||
"@services": ["./src/services"],
|
"@services": ["./src/services"],
|
||||||
"@repositories": ["./src/repositories"]
|
"@repositories": ["./src/repositories"],
|
||||||
|
"@types": ["./src/types"],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src"],
|
||||||
|
|||||||
@@ -465,8 +465,13 @@ export interface FilterableCartProps
|
|||||||
updated_at?: OperatorMap<string>
|
updated_at?: OperatorMap<string>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FilterableAddressProps
|
||||||
|
extends BaseFilterable<FilterableAddressProps> {
|
||||||
|
id?: string | string[]
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Remove this in favor of new__CartDTO, when module is released
|
* TODO: Remove this in favor of CartDTO, when module is released
|
||||||
* @deprecated Use CartDTO instead
|
* @deprecated Use CartDTO instead
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { FindConfig } from "../common"
|
|||||||
import { IModuleService } from "../modules-sdk"
|
import { IModuleService } from "../modules-sdk"
|
||||||
import { Context } from "../shared-context"
|
import { Context } from "../shared-context"
|
||||||
import { CartDTO, FilterableCartProps } from "./common"
|
import { CartDTO, FilterableCartProps } from "./common"
|
||||||
import { AddLineItemsDTO, CreateCartDTO, UpdateCartDTO, UpdateLineItemsDTO } from "./mutations"
|
import { CreateCartDTO, UpdateCartDTO } from "./mutations"
|
||||||
|
|
||||||
export interface ICartModuleService extends IModuleService {
|
export interface ICartModuleService extends IModuleService {
|
||||||
retrieve(
|
retrieve(
|
||||||
@@ -24,25 +24,28 @@ export interface ICartModuleService extends IModuleService {
|
|||||||
): Promise<[CartDTO[], number]>
|
): Promise<[CartDTO[], number]>
|
||||||
|
|
||||||
create(data: CreateCartDTO[], sharedContext?: Context): Promise<CartDTO[]>
|
create(data: CreateCartDTO[], sharedContext?: Context): Promise<CartDTO[]>
|
||||||
|
create(data: CreateCartDTO, sharedContext?: Context): Promise<CartDTO>
|
||||||
|
|
||||||
update(data: UpdateCartDTO[], sharedContext?: Context): Promise<CartDTO[]>
|
update(data: UpdateCartDTO[], sharedContext?: Context): Promise<CartDTO[]>
|
||||||
|
update(data: UpdateCartDTO, sharedContext?: Context): Promise<CartDTO>
|
||||||
|
|
||||||
delete(cartIds: string[], sharedContext?: Context): Promise<void>
|
delete(cartIds: string[], sharedContext?: Context): Promise<void>
|
||||||
|
delete(cartId: string, sharedContext?: Context): Promise<void>
|
||||||
|
|
||||||
addLineItems(data: AddLineItemsDTO, sharedContext?: Context): Promise<CartDTO>
|
// addLineItems(data: AddLineItemsDTO, sharedContext?: Context): Promise<CartDTO>
|
||||||
addLineItems(
|
// addLineItems(
|
||||||
data: AddLineItemsDTO[],
|
// data: AddLineItemsDTO[],
|
||||||
sharedContext?: Context
|
// sharedContext?: Context
|
||||||
): Promise<CartDTO[]>
|
// ): Promise<CartDTO[]>
|
||||||
|
|
||||||
updateLineItems(
|
// updateLineItems(
|
||||||
data: UpdateLineItemsDTO,
|
// data: UpdateLineItemsDTO,
|
||||||
sharedContext?: Context
|
// sharedContext?: Context
|
||||||
): Promise<CartDTO>
|
// ): Promise<CartDTO>
|
||||||
updateLineItems(
|
// updateLineItems(
|
||||||
data: UpdateLineItemsDTO[],
|
// data: UpdateLineItemsDTO[],
|
||||||
sharedContext?: Context
|
// sharedContext?: Context
|
||||||
): Promise<CartDTO[]>
|
// ): Promise<CartDTO[]>
|
||||||
|
|
||||||
removeLineItems(lineItemIds: string[], sharedContext?: Context): Promise<void>
|
// removeLineItems(lineItemIds: string[], sharedContext?: Context): Promise<void>
|
||||||
}
|
}
|
||||||
@@ -4,14 +4,6 @@ import {
|
|||||||
FilterQuery as InternalFilerQuery,
|
FilterQuery as InternalFilerQuery,
|
||||||
RepositoryTransformOptions,
|
RepositoryTransformOptions,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import { arrayDifference, isString, MedusaError } from "../../common"
|
|
||||||
import { MedusaContext } from "../../decorators"
|
|
||||||
import { buildQuery, InjectTransactionManager } from "../../modules-sdk"
|
|
||||||
import {
|
|
||||||
getSoftDeletedCascadedEntitiesIdsMappedBy,
|
|
||||||
transactionWrapper,
|
|
||||||
} from "../utils"
|
|
||||||
import { mikroOrmSerializer, mikroOrmUpdateDeletedAtRecursively } from "./utils"
|
|
||||||
import {
|
import {
|
||||||
EntityManager,
|
EntityManager,
|
||||||
EntitySchema,
|
EntitySchema,
|
||||||
@@ -19,12 +11,20 @@ import {
|
|||||||
LoadStrategy,
|
LoadStrategy,
|
||||||
RequiredEntityData,
|
RequiredEntityData,
|
||||||
} from "@mikro-orm/core"
|
} from "@mikro-orm/core"
|
||||||
|
import { FindOptions as MikroOptions } from "@mikro-orm/core/drivers/IDatabaseDriver"
|
||||||
import {
|
import {
|
||||||
EntityClass,
|
EntityClass,
|
||||||
EntityName,
|
EntityName,
|
||||||
FilterQuery as MikroFilterQuery,
|
FilterQuery as MikroFilterQuery,
|
||||||
} from "@mikro-orm/core/typings"
|
} from "@mikro-orm/core/typings"
|
||||||
import { FindOptions as MikroOptions } from "@mikro-orm/core/drivers/IDatabaseDriver"
|
import { MedusaError, arrayDifference, isString } from "../../common"
|
||||||
|
import { MedusaContext } from "../../decorators"
|
||||||
|
import { InjectTransactionManager, buildQuery } from "../../modules-sdk"
|
||||||
|
import {
|
||||||
|
getSoftDeletedCascadedEntitiesIdsMappedBy,
|
||||||
|
transactionWrapper,
|
||||||
|
} from "../utils"
|
||||||
|
import { mikroOrmSerializer, mikroOrmUpdateDeletedAtRecursively } from "./utils"
|
||||||
|
|
||||||
export class MikroOrmBase<T = any> {
|
export class MikroOrmBase<T = any> {
|
||||||
readonly manager_: any
|
readonly manager_: any
|
||||||
|
|||||||
Reference in new issue
Block a user