refactor(medusa): Cleanup and fix CartService (#1306)
* refactor(medusa): Cleanup + fix * styles(medusa): Lint * refactor(medusa): Finalize cleanup * feat(medusa): Prefer the usage of bulk operations instead of sequential/conccurent operations * feat(medusa): Improve cart service * refactor(medusa): Explicitly specifying protected methods when needed as well as enfore the usage of the local transactionManager_ in those methods * tests(medusa): Fix tests according to the new changes * feat(medusa): Cleanup after rebase * test(medusa): Fix cart service tests
This commit is contained in:
@@ -24,7 +24,7 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`/store/carts shipping address + region updates updates region only - single to multipe countries 1`] = `
|
exports[`/store/carts shipping address + region updates updates region only - single to multiple countries 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"address_1": null,
|
"address_1": null,
|
||||||
"address_2": null,
|
"address_2": null,
|
||||||
|
|||||||
@@ -924,19 +924,19 @@ describe("/store/carts", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("fails on apply discount if limit has been reached", async () => {
|
it("fails on apply discount if limit has been reached", async () => {
|
||||||
expect.assertions(2)
|
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
|
|
||||||
await api
|
const err = await api
|
||||||
.post("/store/carts/test-cart", {
|
.post("/store/carts/test-cart", {
|
||||||
discounts: [{ code: "SPENT" }],
|
discounts: [{ code: "SPENT" }],
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((err) => err)
|
||||||
expect(error.response.status).toEqual(400)
|
|
||||||
expect(error.response.data.message).toEqual(
|
expect(err).toBeTruthy()
|
||||||
"Discount has been used maximum allowed times"
|
expect(err.response.status).toEqual(400)
|
||||||
)
|
expect(err.response.data.message).toEqual(
|
||||||
})
|
"Discount has been used maximum allowed times"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("successfully passes customer conditions with `in` operator and applies discount", async () => {
|
it("successfully passes customer conditions with `in` operator and applies discount", async () => {
|
||||||
@@ -1755,7 +1755,7 @@ describe("/store/carts", () => {
|
|||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
expect(cartWithGiftcard.data.cart.total).toBe(1900) // 1000 (giftcard) + 900 (standard item with 10% discount)
|
expect(cartWithGiftcard.data.cart.total).toBe(2900) // 1000 (giftcard) + 900 (standard item with 10% discount) + 1000 Shipping
|
||||||
expect(cartWithGiftcard.data.cart.discount_total).toBe(100)
|
expect(cartWithGiftcard.data.cart.discount_total).toBe(100)
|
||||||
expect(cartWithGiftcard.status).toEqual(200)
|
expect(cartWithGiftcard.status).toEqual(200)
|
||||||
})
|
})
|
||||||
@@ -1925,7 +1925,7 @@ describe("/store/carts", () => {
|
|||||||
await doAfterEach()
|
await doAfterEach()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("updates region only - single to multipe countries", async () => {
|
it("updates region only - single to multiple countries", async () => {
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
|
|
||||||
const { data, status } = await api
|
const { data, status } = await api
|
||||||
@@ -1947,7 +1947,7 @@ describe("/store/carts", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it("updates region only - single to multipe countries", async () => {
|
it("should reset the shipping_address on null value", async () => {
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
|
|
||||||
const { data, status } = await api
|
const { data, status } = await api
|
||||||
@@ -1962,7 +1962,5 @@ describe("/store/carts", () => {
|
|||||||
expect(status).toEqual(200)
|
expect(status).toEqual(200)
|
||||||
expect(data.cart.shipping_address).toEqual(null)
|
expect(data.cart.shipping_address).toEqual(null)
|
||||||
})
|
})
|
||||||
|
|
||||||
// it("updates cart.customer_id on cart retrieval if cart.customer_id differ from session customer", async () => {})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -228,8 +228,7 @@ class BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await this.manager_.transaction((m) => doWork(m))
|
return await this.manager_.transaction((m) => doWork(m))
|
||||||
return result
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (errorHandler) {
|
if (errorHandler) {
|
||||||
const result = await errorHandler(error)
|
const result = await errorHandler(error)
|
||||||
|
|||||||
@@ -90,23 +90,20 @@ export default async (req, res) => {
|
|||||||
// Update the cart
|
// Update the cart
|
||||||
const { shipping_address, billing_address, ...rest } = validated
|
const { shipping_address, billing_address, ...rest } = validated
|
||||||
|
|
||||||
const toUpdate: CartUpdateProps = {
|
const cartDataToUpdate: CartUpdateProps = { ...rest };
|
||||||
...rest,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof shipping_address === "string") {
|
if (typeof shipping_address === "string") {
|
||||||
toUpdate.shipping_address_id = shipping_address
|
cartDataToUpdate.shipping_address_id = shipping_address
|
||||||
} else {
|
} else {
|
||||||
toUpdate.shipping_address = shipping_address
|
cartDataToUpdate.shipping_address = shipping_address
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof billing_address === "string") {
|
if (typeof billing_address === "string") {
|
||||||
toUpdate.billing_address_id = billing_address
|
cartDataToUpdate.billing_address_id = billing_address
|
||||||
} else {
|
} else {
|
||||||
toUpdate.billing_address = billing_address
|
cartDataToUpdate.billing_address = billing_address
|
||||||
}
|
}
|
||||||
|
|
||||||
await cartService.update(id, toUpdate)
|
await cartService.update(id, cartDataToUpdate)
|
||||||
|
|
||||||
// If the cart has payment sessions update these
|
// If the cart has payment sessions update these
|
||||||
const updated = await cartService.retrieve(id, {
|
const updated = await cartService.retrieve(id, {
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import { MedusaContainer } from "../types/global"
|
|||||||
import DefaultSearchService from "../services/search"
|
import DefaultSearchService from "../services/search"
|
||||||
import { Logger } from "../types/global"
|
import { Logger } from "../types/global"
|
||||||
|
|
||||||
async function loadProductsIntoSearchEngine(container: MedusaContainer): Promise<void> {
|
async function loadProductsIntoSearchEngine(
|
||||||
|
container: MedusaContainer
|
||||||
|
): Promise<void> {
|
||||||
const searchService = container.resolve<DefaultSearchService>("searchService")
|
const searchService = container.resolve<DefaultSearchService>("searchService")
|
||||||
const productService = container.resolve<ProductService>("productService")
|
const productService = container.resolve<ProductService>("productService")
|
||||||
|
|
||||||
@@ -61,7 +63,11 @@ async function loadProductsIntoSearchEngine(container: MedusaContainer): Promise
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async ({ container }: { container: MedusaContainer }): Promise<void> => {
|
export default async ({
|
||||||
|
container,
|
||||||
|
}: {
|
||||||
|
container: MedusaContainer
|
||||||
|
}): Promise<void> => {
|
||||||
const searchService = container.resolve<DefaultSearchService>("searchService")
|
const searchService = container.resolve<DefaultSearchService>("searchService")
|
||||||
const logger = container.resolve<Logger>("logger")
|
const logger = container.resolve<Logger>("logger")
|
||||||
if (searchService.isDefault) {
|
if (searchService.isDefault) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Cart } from "../models/cart"
|
|||||||
@EntityRepository(Cart)
|
@EntityRepository(Cart)
|
||||||
export class CartRepository extends Repository<Cart> {
|
export class CartRepository extends Repository<Cart> {
|
||||||
public async findWithRelations(
|
public async findWithRelations(
|
||||||
relations: Array<keyof Cart> = [],
|
relations: string[] = [],
|
||||||
optionsWithoutRelations: Omit<FindManyOptions<Cart>, "relations"> = {}
|
optionsWithoutRelations: Omit<FindManyOptions<Cart>, "relations"> = {}
|
||||||
): Promise<Cart[]> {
|
): Promise<Cart[]> {
|
||||||
const entities = await this.find(optionsWithoutRelations)
|
const entities = await this.find(optionsWithoutRelations)
|
||||||
@@ -38,7 +38,7 @@ export class CartRepository extends Repository<Cart> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async findOneWithRelations(
|
public async findOneWithRelations(
|
||||||
relations: Array<keyof Cart> = [],
|
relations: string[] = [],
|
||||||
optionsWithoutRelations: Omit<FindManyOptions<Cart>, "relations"> = {}
|
optionsWithoutRelations: Omit<FindManyOptions<Cart>, "relations"> = {}
|
||||||
): Promise<Cart> {
|
): Promise<Cart> {
|
||||||
// Limit 1
|
// Limit 1
|
||||||
|
|||||||
@@ -193,6 +193,9 @@ describe("CartService", () => {
|
|||||||
|
|
||||||
describe("create", () => {
|
describe("create", () => {
|
||||||
const regionService = {
|
const regionService = {
|
||||||
|
withTransaction: function() {
|
||||||
|
return this
|
||||||
|
},
|
||||||
retrieve: () => {
|
retrieve: () => {
|
||||||
return {
|
return {
|
||||||
id: IdMap.getId("testRegion"),
|
id: IdMap.getId("testRegion"),
|
||||||
@@ -324,7 +327,7 @@ describe("CartService", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const shippingOptionService = {
|
const shippingOptionService = {
|
||||||
deleteShippingMethod: jest.fn(),
|
deleteShippingMethods: jest.fn(),
|
||||||
withTransaction: function() {
|
withTransaction: function() {
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
@@ -378,6 +381,7 @@ describe("CartService", () => {
|
|||||||
totalsService,
|
totalsService,
|
||||||
cartRepository,
|
cartRepository,
|
||||||
lineItemService,
|
lineItemService,
|
||||||
|
lineItemRepository: MockRepository(),
|
||||||
eventBusService,
|
eventBusService,
|
||||||
shippingOptionService,
|
shippingOptionService,
|
||||||
inventoryService,
|
inventoryService,
|
||||||
@@ -476,7 +480,7 @@ describe("CartService", () => {
|
|||||||
|
|
||||||
await cartService.addLineItem(IdMap.getId("cartWithLine"), lineItem)
|
await cartService.addLineItem(IdMap.getId("cartWithLine"), lineItem)
|
||||||
|
|
||||||
expect(lineItemService.update).toHaveBeenCalledTimes(2)
|
expect(lineItemService.update).toHaveBeenCalledTimes(1)
|
||||||
expect(lineItemService.update).toHaveBeenCalledWith(
|
expect(lineItemService.update).toHaveBeenCalledWith(
|
||||||
IdMap.getId("merger"),
|
IdMap.getId("merger"),
|
||||||
{
|
{
|
||||||
@@ -581,7 +585,7 @@ describe("CartService", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const shippingOptionService = {
|
const shippingOptionService = {
|
||||||
deleteShippingMethod: jest.fn(),
|
deleteShippingMethods: jest.fn(),
|
||||||
withTransaction: function() {
|
withTransaction: function() {
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
@@ -592,6 +596,7 @@ describe("CartService", () => {
|
|||||||
totalsService,
|
totalsService,
|
||||||
cartRepository,
|
cartRepository,
|
||||||
lineItemService,
|
lineItemService,
|
||||||
|
lineItemRepository: MockRepository(),
|
||||||
shippingOptionService,
|
shippingOptionService,
|
||||||
eventBusService,
|
eventBusService,
|
||||||
lineItemAdjustmentService: LineItemAdjustmentServiceMock,
|
lineItemAdjustmentService: LineItemAdjustmentServiceMock,
|
||||||
@@ -641,15 +646,15 @@ describe("CartService", () => {
|
|||||||
IdMap.getId("itemToRemove")
|
IdMap.getId("itemToRemove")
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(shippingOptionService.deleteShippingMethod).toHaveBeenCalledTimes(
|
expect(shippingOptionService.deleteShippingMethods).toHaveBeenCalledTimes(
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
expect(shippingOptionService.deleteShippingMethod).toHaveBeenCalledWith({
|
expect(shippingOptionService.deleteShippingMethods).toHaveBeenCalledWith([{
|
||||||
id: IdMap.getId("ship-method"),
|
id: IdMap.getId("ship-method"),
|
||||||
shipping_option: {
|
shipping_option: {
|
||||||
profile_id: IdMap.getId("prevPro"),
|
profile_id: IdMap.getId("prevPro"),
|
||||||
},
|
},
|
||||||
})
|
}])
|
||||||
|
|
||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||||
@@ -1095,6 +1100,9 @@ describe("CartService", () => {
|
|||||||
countries: [{ iso_2: "us" }],
|
countries: [{ iso_2: "us" }],
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
withTransaction: function() {
|
||||||
|
return this
|
||||||
|
},
|
||||||
}
|
}
|
||||||
const cartRepository = MockRepository({
|
const cartRepository = MockRepository({
|
||||||
findOneWithRelations: () =>
|
findOneWithRelations: () =>
|
||||||
@@ -1131,6 +1139,9 @@ describe("CartService", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const priceSelectionStrat = {
|
const priceSelectionStrat = {
|
||||||
|
withTransaction: function() {
|
||||||
|
return this
|
||||||
|
},
|
||||||
calculateVariantPrice: async (variantId, context) => {
|
calculateVariantPrice: async (variantId, context) => {
|
||||||
if (variantId === IdMap.getId("fail")) {
|
if (variantId === IdMap.getId("fail")) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
@@ -1152,6 +1163,7 @@ describe("CartService", () => {
|
|||||||
lineItemService,
|
lineItemService,
|
||||||
productVariantService,
|
productVariantService,
|
||||||
eventBusService,
|
eventBusService,
|
||||||
|
paymentSessionRepository: MockRepository(),
|
||||||
priceSelectionStrategy: priceSelectionStrat,
|
priceSelectionStrategy: priceSelectionStrat,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1192,7 +1204,7 @@ describe("CartService", () => {
|
|||||||
shipping_address: {
|
shipping_address: {
|
||||||
country_code: "us",
|
country_code: "us",
|
||||||
},
|
},
|
||||||
items: [IdMap.getId("testitem"), null],
|
items: [IdMap.getId("testitem")],
|
||||||
payment_session: null,
|
payment_session: null,
|
||||||
payment_sessions: [],
|
payment_sessions: [],
|
||||||
gift_cards: [],
|
gift_cards: [],
|
||||||
@@ -1513,13 +1525,16 @@ describe("CartService", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
deleteShippingMethod: jest.fn(),
|
deleteShippingMethods: jest.fn(),
|
||||||
withTransaction: function() {
|
withTransaction: function() {
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const customShippingOptionService = {
|
const customShippingOptionService = {
|
||||||
|
withTransaction: function() {
|
||||||
|
return this
|
||||||
|
},
|
||||||
list: jest.fn().mockImplementation(({ cart_id }) => {
|
list: jest.fn().mockImplementation(({ cart_id }) => {
|
||||||
if (cart_id === IdMap.getId("cart-with-custom-so")) {
|
if (cart_id === IdMap.getId("cart-with-custom-so")) {
|
||||||
return [
|
return [
|
||||||
@@ -1575,7 +1590,7 @@ describe("CartService", () => {
|
|||||||
expect(
|
expect(
|
||||||
shippingOptionService.createShippingMethod
|
shippingOptionService.createShippingMethod
|
||||||
).toHaveBeenCalledWith(IdMap.getId("profile1"), data, { cart: cart2 })
|
).toHaveBeenCalledWith(IdMap.getId("profile1"), data, { cart: cart2 })
|
||||||
expect(shippingOptionService.deleteShippingMethod).toHaveBeenCalledWith({
|
expect(shippingOptionService.deleteShippingMethods).toHaveBeenCalledWith({
|
||||||
id: IdMap.getId("ship1"),
|
id: IdMap.getId("ship1"),
|
||||||
shipping_option: {
|
shipping_option: {
|
||||||
profile_id: IdMap.getId("profile1"),
|
profile_id: IdMap.getId("profile1"),
|
||||||
@@ -1594,7 +1609,7 @@ describe("CartService", () => {
|
|||||||
data
|
data
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(shippingOptionService.deleteShippingMethod).toHaveBeenCalledTimes(
|
expect(shippingOptionService.deleteShippingMethods).toHaveBeenCalledTimes(
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
expect(shippingOptionService.createShippingMethod).toHaveBeenCalledTimes(
|
expect(shippingOptionService.createShippingMethod).toHaveBeenCalledTimes(
|
||||||
@@ -1616,7 +1631,7 @@ describe("CartService", () => {
|
|||||||
data
|
data
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(shippingOptionService.deleteShippingMethod).toHaveBeenCalledTimes(
|
expect(shippingOptionService.deleteShippingMethods).toHaveBeenCalledTimes(
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
expect(shippingOptionService.createShippingMethod).toHaveBeenCalledTimes(
|
expect(shippingOptionService.createShippingMethod).toHaveBeenCalledTimes(
|
||||||
@@ -1738,6 +1753,9 @@ describe("CartService", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const discountService = {
|
const discountService = {
|
||||||
|
withTransaction: function () {
|
||||||
|
return this
|
||||||
|
},
|
||||||
retrieveByCode: jest.fn().mockImplementation((code) => {
|
retrieveByCode: jest.fn().mockImplementation((code) => {
|
||||||
if (code === "US10") {
|
if (code === "US10") {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
|
|||||||
@@ -1228,7 +1228,7 @@ describe("OrderService", () => {
|
|||||||
.mockImplementation((optionId, data, config) =>
|
.mockImplementation((optionId, data, config) =>
|
||||||
Promise.resolve({ shipping_option: { profile_id: optionId } })
|
Promise.resolve({ shipping_option: { profile_id: optionId } })
|
||||||
),
|
),
|
||||||
deleteShippingMethod: jest
|
deleteShippingMethods: jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementation(() => Promise.resolve({})),
|
.mockImplementation(() => Promise.resolve({})),
|
||||||
|
|
||||||
@@ -1276,7 +1276,7 @@ describe("OrderService", () => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(optionService.deleteShippingMethod).not.toHaveBeenCalled()
|
expect(optionService.deleteShippingMethods).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("successfully removes shipping method if same option profile", async () => {
|
it("successfully removes shipping method if same option profile", async () => {
|
||||||
@@ -1305,8 +1305,8 @@ describe("OrderService", () => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(optionService.deleteShippingMethod).toHaveBeenCalledTimes(1)
|
expect(optionService.deleteShippingMethods).toHaveBeenCalledTimes(1)
|
||||||
expect(optionService.deleteShippingMethod).toHaveBeenCalledWith({
|
expect(optionService.deleteShippingMethods).toHaveBeenCalledWith({
|
||||||
shipping_option: {
|
shipping_option: {
|
||||||
profile_id: IdMap.getId("method1"),
|
profile_id: IdMap.getId("method1"),
|
||||||
},
|
},
|
||||||
|
|||||||
+1063
-942
File diff suppressed because it is too large
Load Diff
@@ -873,7 +873,7 @@ class OrderService extends BaseService {
|
|||||||
) {
|
) {
|
||||||
await this.shippingOptionService_
|
await this.shippingOptionService_
|
||||||
.withTransaction(manager)
|
.withTransaction(manager)
|
||||||
.deleteShippingMethod(sm)
|
.deleteShippingMethods(sm)
|
||||||
} else {
|
} else {
|
||||||
methods.push(sm)
|
methods.push(sm)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,12 +208,16 @@ class ShippingOptionService extends BaseService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a given shipping method
|
* Removes a given shipping method
|
||||||
* @param {ShippingMethod} sm - the shipping method to remove
|
* @param {ShippingMethod | Array<ShippingMethod>} shippingMethods - the shipping method to remove
|
||||||
*/
|
*/
|
||||||
async deleteShippingMethod(sm) {
|
async deleteShippingMethods(shippingMethods) {
|
||||||
|
if (!Array.isArray(shippingMethods)) {
|
||||||
|
shippingMethods = [shippingMethods]
|
||||||
|
}
|
||||||
|
|
||||||
return this.atomicPhase_(async (manager) => {
|
return this.atomicPhase_(async (manager) => {
|
||||||
const methodRepo = manager.getCustomRepository(this.methodRepository_)
|
const methodRepo = manager.getCustomRepository(this.methodRepository_)
|
||||||
return methodRepo.remove(sm)
|
return methodRepo.remove(shippingMethods)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import { asFunction, asValue, AwilixContainer } from "awilix"
|
import { AwilixContainer } from "awilix"
|
||||||
import { Logger as _Logger } from "winston"
|
import { Logger as _Logger } from "winston"
|
||||||
|
|
||||||
export type ClassConstructor<T> = {
|
export type ClassConstructor<T> = {
|
||||||
new (...args: any[]): T;
|
new (...args: unknown[]): T
|
||||||
};
|
}
|
||||||
|
|
||||||
export type MedusaContainer = AwilixContainer & { registerAdd: <T>(name: string, registration: T ) => MedusaContainer }
|
export type MedusaContainer = AwilixContainer & {
|
||||||
|
registerAdd: <T>(name: string, registration: T) => MedusaContainer
|
||||||
|
}
|
||||||
|
|
||||||
export type Logger = _Logger & { progress: (activityId: string, msg: string) => void }
|
export type Logger = _Logger & {
|
||||||
|
progress: (activityId: string, msg: string) => void
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user