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

This commit is contained in:
Philip Korsholm
2022-08-07 17:06:36 +07:00
committed by GitHub
parent b3b69d7117
commit 42ed209518
6 changed files with 138 additions and 85 deletions

View File

@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---
Convert CollectionService to TypeScript

View File

@@ -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 })

View File

@@ -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>
}

View File

@@ -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>
}

View File

@@ -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(

View 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>
}