feat(medusa): Convert CollectionService to TypeScript (#1976)

This commit is contained in:
Philip Korsholm authored and GitHub committed 2022-08-07 12:06:36 +02:00
1 parent b3b69d7117
commit 42ed209518
6 files changed
+138 -85

No files matched your search

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