feat(medusa): Convert CollectionService to TypeScript (#1976)
This commit is contained in:
5
.changeset/fresh-snakes-judge.md
Normal file
5
.changeset/fresh-snakes-judge.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@medusajs/medusa": patch
|
||||
---
|
||||
|
||||
Convert CollectionService to TypeScript
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ArrayNotEmpty, IsString } from "class-validator"
|
||||
import { Request, Response } from "express"
|
||||
import { EntityManager } from "typeorm";
|
||||
import { EntityManager } from "typeorm"
|
||||
|
||||
import ProductCollectionService from "../../../../services/product-collection"
|
||||
|
||||
@@ -39,7 +39,9 @@ import ProductCollectionService from "../../../../services/product-collection"
|
||||
*/
|
||||
export default async (req: Request, res: Response) => {
|
||||
const { id } = req.params
|
||||
const { validatedBody } = req as { validatedBody: AdminPostProductsToCollectionReq }
|
||||
const { validatedBody } = req as {
|
||||
validatedBody: AdminPostProductsToCollectionReq
|
||||
}
|
||||
|
||||
const productCollectionService: ProductCollectionService = req.scope.resolve(
|
||||
"productCollectionService"
|
||||
@@ -47,10 +49,9 @@ export default async (req: Request, res: Response) => {
|
||||
|
||||
const manager: EntityManager = req.scope.resolve("manager")
|
||||
const collection = await manager.transaction(async (transactionManager) => {
|
||||
return await productCollectionService.withTransaction(transactionManager).addProducts(
|
||||
id,
|
||||
validatedBody.product_ids
|
||||
)
|
||||
return await productCollectionService
|
||||
.withTransaction(transactionManager)
|
||||
.addProducts(id, validatedBody.product_ids)
|
||||
})
|
||||
|
||||
res.status(200).json({ collection })
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { IsNotEmpty, IsObject, IsOptional, IsString } from "class-validator"
|
||||
import ProductCollectionService from "../../../../services/product-collection"
|
||||
import { Request, Response } from "express"
|
||||
import { EntityManager } from "typeorm";
|
||||
import { EntityManager } from "typeorm"
|
||||
|
||||
/**
|
||||
* @oas [post] /collections
|
||||
@@ -38,7 +38,7 @@ import { EntityManager } from "typeorm";
|
||||
* $ref: "#/components/schemas/product_collection"
|
||||
*/
|
||||
export default async (req: Request, res: Response) => {
|
||||
const { validatedBody } = req
|
||||
const { validatedBody } = req as { validatedBody: AdminPostCollectionsReq }
|
||||
|
||||
const productCollectionService: ProductCollectionService = req.scope.resolve(
|
||||
"productCollectionService"
|
||||
@@ -46,7 +46,9 @@ export default async (req: Request, res: Response) => {
|
||||
|
||||
const manager: EntityManager = req.scope.resolve("manager")
|
||||
const created = await manager.transaction(async (transactionManager) => {
|
||||
return await productCollectionService.withTransaction(transactionManager).create(validatedBody)
|
||||
return await productCollectionService
|
||||
.withTransaction(transactionManager)
|
||||
.create(validatedBody)
|
||||
})
|
||||
|
||||
const collection = await productCollectionService.retrieve(created.id)
|
||||
@@ -65,5 +67,5 @@ export class AdminPostCollectionsReq {
|
||||
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
metadata?: object
|
||||
metadata?: Record<string, unknown>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { IsObject, IsOptional, IsString } from "class-validator"
|
||||
import { Request, Response } from "express"
|
||||
|
||||
import { EntityManager } from "typeorm";
|
||||
import ProductCollectionService from "../../../../services/product-collection"
|
||||
|
||||
@@ -40,7 +39,9 @@ import ProductCollectionService from "../../../../services/product-collection"
|
||||
*/
|
||||
export default async (req: Request, res: Response) => {
|
||||
const { id } = req.params
|
||||
const { validatedBody } = req
|
||||
const { validatedBody } = req as {
|
||||
validatedBody: AdminPostCollectionsCollectionReq
|
||||
}
|
||||
|
||||
const productCollectionService: ProductCollectionService = req.scope.resolve(
|
||||
"productCollectionService"
|
||||
@@ -48,7 +49,9 @@ export default async (req: Request, res: Response) => {
|
||||
|
||||
const manager: EntityManager = req.scope.resolve("manager")
|
||||
const updated = await manager.transaction(async (transactionManager) => {
|
||||
return await productCollectionService.withTransaction(transactionManager).update(id, validatedBody)
|
||||
return await productCollectionService
|
||||
.withTransaction(transactionManager)
|
||||
.update(id, validatedBody)
|
||||
})
|
||||
|
||||
const collection = await productCollectionService.retrieve(updated.id)
|
||||
@@ -67,5 +70,5 @@ export class AdminPostCollectionsCollectionReq {
|
||||
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
metadata?: object
|
||||
metadata?: Record<string, unknown>
|
||||
}
|
||||
|
||||
@@ -1,65 +1,71 @@
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { BaseService } from "medusa-interfaces"
|
||||
import { Brackets, ILike } from "typeorm"
|
||||
import { Brackets, EntityManager, ILike } from "typeorm"
|
||||
import { TransactionBaseService } from "../interfaces"
|
||||
import { ProductCollection } from "../models"
|
||||
import { ProductRepository } from "../repositories/product"
|
||||
import { ProductCollectionRepository } from "../repositories/product-collection"
|
||||
import { ExtendedFindConfig, FindConfig, QuerySelector } from "../types/common"
|
||||
import {
|
||||
CreateProductCollection,
|
||||
UpdateProductCollection
|
||||
} from "../types/product-collection"
|
||||
import { buildQuery, setMetadata } from "../utils"
|
||||
import { formatException } from "../utils/exception-formatter"
|
||||
import EventBusService from "./event-bus"
|
||||
|
||||
type InjectedDependencies = {
|
||||
manager: EntityManager
|
||||
eventBusService: EventBusService
|
||||
productRepository: typeof ProductRepository
|
||||
productCollectionRepository: typeof ProductCollectionRepository
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides layer to manipulate product collections.
|
||||
* @extends BaseService
|
||||
*/
|
||||
class ProductCollectionService extends BaseService {
|
||||
class ProductCollectionService extends TransactionBaseService<ProductCollectionService> {
|
||||
protected manager_: EntityManager
|
||||
protected transactionManager_: EntityManager | undefined
|
||||
|
||||
protected readonly eventBus_: EventBusService
|
||||
|
||||
protected readonly productCollectionRepository_: typeof ProductCollectionRepository
|
||||
protected readonly productRepository_: typeof ProductRepository
|
||||
|
||||
constructor({
|
||||
manager,
|
||||
productCollectionRepository,
|
||||
productRepository,
|
||||
eventBusService,
|
||||
}) {
|
||||
super()
|
||||
|
||||
/** @private @const {EntityManager} */
|
||||
}: InjectedDependencies) {
|
||||
super({
|
||||
manager,
|
||||
productCollectionRepository,
|
||||
productRepository,
|
||||
eventBusService,
|
||||
})
|
||||
this.manager_ = manager
|
||||
|
||||
/** @private @const {ProductCollectionRepository} */
|
||||
this.productCollectionRepository_ = productCollectionRepository
|
||||
|
||||
/** @private @const {ProductRepository} */
|
||||
this.productRepository_ = productRepository
|
||||
|
||||
/** @private @const {EventBus} */
|
||||
this.eventBus_ = eventBusService
|
||||
}
|
||||
|
||||
withTransaction(transactionManager) {
|
||||
if (!transactionManager) {
|
||||
return this
|
||||
}
|
||||
|
||||
const cloned = new ProductCollectionService({
|
||||
manager: transactionManager,
|
||||
productCollectionRepository: this.productCollectionRepository_,
|
||||
productRepository: this.productRepository_,
|
||||
eventBusService: this.eventBus_,
|
||||
})
|
||||
|
||||
cloned.transactionManager_ = transactionManager
|
||||
|
||||
return cloned
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a product collection by id.
|
||||
* @param {string} collectionId - the id of the collection to retrieve.
|
||||
* @param {Object} config - the config of the collection to retrieve.
|
||||
* @return {Promise<ProductCollection>} the collection.
|
||||
* @param collectionId - the id of the collection to retrieve.
|
||||
* @param config - the config of the collection to retrieve.
|
||||
* @return the collection.
|
||||
*/
|
||||
async retrieve(collectionId, config = {}) {
|
||||
async retrieve(
|
||||
collectionId: string,
|
||||
config: FindConfig<ProductCollection> = {}
|
||||
): Promise<ProductCollection> {
|
||||
const collectionRepo = this.manager_.getCustomRepository(
|
||||
this.productCollectionRepository_
|
||||
)
|
||||
|
||||
const validatedId = this.validateId_(collectionId)
|
||||
|
||||
const query = this.buildQuery_({ id: validatedId }, config)
|
||||
const query = buildQuery({ id: collectionId }, config)
|
||||
const collection = await collectionRepo.findOne(query)
|
||||
|
||||
if (!collection) {
|
||||
@@ -74,16 +80,19 @@ class ProductCollectionService extends BaseService {
|
||||
|
||||
/**
|
||||
* Retrieves a product collection by id.
|
||||
* @param {string} collectionHandle - the handle of the collection to retrieve.
|
||||
* @param {object} config - query config for request
|
||||
* @return {Promise<ProductCollection>} the collection.
|
||||
* @param collectionHandle - the handle of the collection to retrieve.
|
||||
* @param config - query config for request
|
||||
* @return the collection.
|
||||
*/
|
||||
async retrieveByHandle(collectionHandle, config = {}) {
|
||||
async retrieveByHandle(
|
||||
collectionHandle: string,
|
||||
config: FindConfig<ProductCollection> = {}
|
||||
): Promise<ProductCollection> {
|
||||
const collectionRepo = this.manager_.getCustomRepository(
|
||||
this.productCollectionRepository_
|
||||
)
|
||||
|
||||
const query = this.buildQuery_({ handle: collectionHandle }, config)
|
||||
const query = buildQuery({ handle: collectionHandle }, config)
|
||||
const collection = await collectionRepo.findOne(query)
|
||||
|
||||
if (!collection) {
|
||||
@@ -98,11 +107,13 @@ class ProductCollectionService extends BaseService {
|
||||
|
||||
/**
|
||||
* Creates a product collection
|
||||
* @param {object} collection - the collection to create
|
||||
* @return {Promise<ProductCollection>} created collection
|
||||
* @param collection - the collection to create
|
||||
* @return created collection
|
||||
*/
|
||||
async create(collection) {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
async create(
|
||||
collection: CreateProductCollection
|
||||
): Promise<ProductCollection> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const collectionRepo = manager.getCustomRepository(
|
||||
this.productCollectionRepository_
|
||||
)
|
||||
@@ -118,12 +129,15 @@ class ProductCollectionService extends BaseService {
|
||||
|
||||
/**
|
||||
* Updates a product collection
|
||||
* @param {string} collectionId - id of collection to update
|
||||
* @param {object} update - update object
|
||||
* @return {Promise<ProductCollection>} update collection
|
||||
* @param collectionId - id of collection to update
|
||||
* @param update - update object
|
||||
* @return update collection
|
||||
*/
|
||||
async update(collectionId, update) {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
async update(
|
||||
collectionId: string,
|
||||
update: UpdateProductCollection
|
||||
): Promise<ProductCollection> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const collectionRepo = manager.getCustomRepository(
|
||||
this.productCollectionRepository_
|
||||
)
|
||||
@@ -133,7 +147,7 @@ class ProductCollectionService extends BaseService {
|
||||
const { metadata, ...rest } = update
|
||||
|
||||
if (metadata) {
|
||||
collection.metadata = this.setMetadata_(collection, metadata)
|
||||
collection.metadata = setMetadata(collection, metadata)
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(rest)) {
|
||||
@@ -146,11 +160,11 @@ class ProductCollectionService extends BaseService {
|
||||
|
||||
/**
|
||||
* Deletes a product collection idempotently
|
||||
* @param {string} collectionId - id of collection to delete
|
||||
* @return {Promise} empty promise
|
||||
* @param collectionId - id of collection to delete
|
||||
* @return empty promise
|
||||
*/
|
||||
async delete(collectionId) {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
async delete(collectionId: string): Promise<void> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const productCollectionRepo = manager.getCustomRepository(
|
||||
this.productCollectionRepository_
|
||||
)
|
||||
@@ -167,8 +181,11 @@ class ProductCollectionService extends BaseService {
|
||||
})
|
||||
}
|
||||
|
||||
async addProducts(collectionId, productIds) {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
async addProducts(
|
||||
collectionId: string,
|
||||
productIds: string[]
|
||||
): Promise<ProductCollection> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const productRepo = manager.getCustomRepository(this.productRepository_)
|
||||
|
||||
try {
|
||||
@@ -185,8 +202,11 @@ class ProductCollectionService extends BaseService {
|
||||
})
|
||||
}
|
||||
|
||||
async removeProducts(collectionId, productIds) {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
async removeProducts(
|
||||
collectionId: string,
|
||||
productIds: string[]
|
||||
): Promise<void> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const productRepo = manager.getCustomRepository(this.productRepository_)
|
||||
|
||||
const { id } = await this.retrieve(collectionId, { select: ["id"] })
|
||||
@@ -199,26 +219,32 @@ class ProductCollectionService extends BaseService {
|
||||
|
||||
/**
|
||||
* Lists product collections
|
||||
* @param {Object} selector - the query object for find
|
||||
* @param {Object} config - the config to be used for find
|
||||
* @return {Promise} the result of the find operation
|
||||
* @param selector - the query object for find
|
||||
* @param config - the config to be used for find
|
||||
* @return the result of the find operation
|
||||
*/
|
||||
async list(selector = {}, config = { skip: 0, take: 20 }) {
|
||||
async list(
|
||||
selector = {},
|
||||
config = { skip: 0, take: 20 }
|
||||
): Promise<ProductCollection[]> {
|
||||
const productCollectionRepo = this.manager_.getCustomRepository(
|
||||
this.productCollectionRepository_
|
||||
)
|
||||
|
||||
const query = this.buildQuery_(selector, config)
|
||||
const query = buildQuery(selector, config)
|
||||
return await productCollectionRepo.find(query)
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists product collections and add count.
|
||||
* @param {Object} selector - the query object for find
|
||||
* @param {Object} config - the config to be used for find
|
||||
* @return {Promise} the result of the find operation
|
||||
* @param selector - the query object for find
|
||||
* @param config - the config to be used for find
|
||||
* @return the result of the find operation
|
||||
*/
|
||||
async listAndCount(selector = {}, config = { skip: 0, take: 20 }) {
|
||||
async listAndCount(
|
||||
selector: QuerySelector<ProductCollection> = {},
|
||||
config: FindConfig<ProductCollection> = { skip: 0, take: 20 }
|
||||
): Promise<[ProductCollection[], number]> {
|
||||
const productCollectionRepo = this.manager_.getCustomRepository(
|
||||
this.productCollectionRepository_
|
||||
)
|
||||
@@ -229,7 +255,12 @@ class ProductCollectionService extends BaseService {
|
||||
delete selector.q
|
||||
}
|
||||
|
||||
const query = this.buildQuery_(selector, config)
|
||||
const query = buildQuery(
|
||||
selector,
|
||||
config
|
||||
) as ExtendedFindConfig<ProductCollection> & {
|
||||
where: (qb: any) => void
|
||||
}
|
||||
|
||||
if (q) {
|
||||
const where = query.where
|
||||
@@ -239,7 +270,7 @@ class ProductCollectionService extends BaseService {
|
||||
delete where.created_at
|
||||
delete where.updated_at
|
||||
|
||||
query.where = (qb) => {
|
||||
query.where = (qb): void => {
|
||||
qb.where(where)
|
||||
|
||||
qb.andWhere(
|
||||
11
packages/medusa/src/types/product-collection.ts
Normal file
11
packages/medusa/src/types/product-collection.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export type CreateProductCollection = {
|
||||
title: string
|
||||
handle?: string
|
||||
metadata?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export type UpdateProductCollection = {
|
||||
title?: string
|
||||
handle?: string
|
||||
metadata?: Record<string, unknown>
|
||||
}
|
||||
Reference in New Issue
Block a user