Merge pull request #15 from srindom/refactor/issue-14

Refactors retrieve functions in services
This commit is contained in:
Sebastian Rindom
2020-03-10 16:10:43 +01:00
committed by GitHub
6 changed files with 105 additions and 237 deletions

View File

@@ -150,11 +150,21 @@ class CartService extends BaseService {
* @param {string} cartId - the id of the cart to get.
* @return {Promise<Cart>} the cart document.
*/
retrieve(cartId) {
async retrieve(cartId) {
const validatedId = this.validateId_(cartId)
return this.cartModel_.findOne({ _id: validatedId }).catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
const cart = await this.cartModel_
.findOne({ _id: validatedId })
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
if (!cart) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Cart with ${cartId} was not found`
)
}
return cart
}
/**
@@ -172,16 +182,10 @@ class CartService extends BaseService {
}
const region = await this.regionService_.retrieve(region_id)
if (!region) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`A region with id: ${region_id} does not exist`
)
}
return this.cartModel_
.create({
region_id,
region_id: region._id,
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
@@ -211,12 +215,6 @@ class CartService extends BaseService {
const validatedLineItem = this.lineItemService_.validate(lineItem)
const cart = await this.retrieve(cartId)
if (!cart) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
"The cart was not found"
)
}
const currentItem = cart.items.find(line =>
_.isEqual(line.content, validatedLineItem.content)
@@ -285,12 +283,6 @@ class CartService extends BaseService {
*/
async updateEmail(cartId, email) {
const cart = await this.retrieve(cartId)
if (!cart) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
"The cart was not found"
)
}
const schema = Validator.string()
.email()
@@ -305,7 +297,7 @@ class CartService extends BaseService {
return this.cartModel_.updateOne(
{
_id: cartId,
_id: cart._id,
},
{
$set: { email: value },
@@ -321,12 +313,6 @@ class CartService extends BaseService {
*/
async updateBillingAddress(cartId, address) {
const cart = await this.retrieve(cartId)
if (!cart) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
"The cart was not found"
)
}
const { value, error } = Validator.address().validate(address)
if (error) {
@@ -338,7 +324,7 @@ class CartService extends BaseService {
return this.cartModel_.updateOne(
{
_id: cartId,
_id: cart._id,
},
{
$set: { billing_address: value },
@@ -354,12 +340,6 @@ class CartService extends BaseService {
*/
async updateShippingAddress(cartId, address) {
const cart = await this.retrieve(cartId)
if (!cart) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
"The cart was not found"
)
}
const { value, error } = Validator.address().validate(address)
if (error) {
@@ -394,20 +374,7 @@ class CartService extends BaseService {
*/
async setPaymentMethod(cartId, paymentMethod) {
const cart = await this.retrieve(cartId)
if (!cart) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
"The cart was not found"
)
}
const region = await this.regionService_.retrieve(cart.region_id)
if (!region) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`The cart does not have a region associated`
)
}
// The region must have the provider id in its providers array
if (
@@ -454,20 +421,7 @@ class CartService extends BaseService {
*/
async setRegion(cartId, regionId) {
const cart = await this.retrieve(cartId)
if (!cart) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
"The cart was not found"
)
}
const region = await this.regionService_.retrieve(regionId)
if (!region) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`The region: ${regionId} was not found`
)
}
let update = {
region_id: region._id,

View File

@@ -81,11 +81,21 @@ class CustomerService extends BaseService {
* @param {string} customerId - the id of the customer to get.
* @return {Promise<Customer>} the customer document.
*/
retrieve(customerId) {
async retrieve(customerId) {
const validatedId = this.validateId_(customerId)
return this.customerModel_.findOne({ _id: validatedId }).catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
const customer = await this.customerModel_
.findOne({ _id: validatedId })
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
if (!customer) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Customer with ${customerId} was not found`
)
}
return customer
}
/**
@@ -113,18 +123,11 @@ class CustomerService extends BaseService {
*/
async updateEmail(customerId, email) {
const customer = await this.retrieve(customerId)
if (!customer) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Customer with ${customerId} was not found`
)
}
this.validateEmail_(email)
return this.customerModel_.updateOne(
{
_id: customerId,
_id: customer._id,
},
{
$set: { email },
@@ -140,18 +143,12 @@ class CustomerService extends BaseService {
*/
async updateBillingAddress(customerId, address) {
const customer = await this.retrieve(customerId)
if (!customer) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Customer with ${customerId} was not found`
)
}
this.validateBillingAddress_(address)
return this.customerModel_.updateOne(
{
_id: customerId,
_id: customer._id,
},
{
$set: { billing_address: address },
@@ -170,12 +167,6 @@ class CustomerService extends BaseService {
*/
async update(customerId, update) {
const customer = await this.retrieve(customerId)
if (!customer) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Customer with ${customerId} was not found`
)
}
if (update.metadata) {
throw new MedusaError(
@@ -192,7 +183,11 @@ class CustomerService extends BaseService {
}
return this.customerModel_
.updateOne({ _id: customerId }, { $set: update }, { runValidators: true })
.updateOne(
{ _id: customer._id },
{ $set: update },
{ runValidators: true }
)
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
@@ -205,9 +200,11 @@ class CustomerService extends BaseService {
* @return {Promise} the result of the delete operation.
*/
async delete(customerId) {
const customer = await this.retrieve(customerId)
// Delete is idempotent, but we return a promise to allow then-chaining
if (!customer) {
let customer
try {
customer = await this.retrieve(customerId)
} catch (error) {
// Delete is idempotent, but we return a promise to allow then-chaining
return Promise.resolve()
}

View File

@@ -82,20 +82,7 @@ class LineItemService extends BaseService {
*/
async generate(variantId, regionId, quantity) {
const variant = await this.productVariantService_.retrieve(variantId)
if (!variant) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Variant: ${variantId} was not found`
)
}
const region = await await this.regionService_.retrieve(regionId)
if (!region) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Region: ${regionId} was not found`
)
}
const region = await this.regionService_.retrieve(regionId)
const products = await this.productService_.list({ variants: variantId })
// this should never fail, since a variant must have a product associated
@@ -109,8 +96,8 @@ class LineItemService extends BaseService {
const product = products[0]
const unit_price = await this.productVariantService_.getRegionPrice(
variantId,
regionId
variant._id,
region._id
)
return {

View File

@@ -52,13 +52,21 @@ class ProductVariantService extends BaseService {
* @param {string} variantId - the id of the product to get.
* @return {Promise<Product>} the product document.
*/
retrieve(variantId) {
async retrieve(variantId) {
const validatedId = this.validateId_(variantId)
return this.productVariantModel_
const variant = await this.productVariantModel_
.findOne({ _id: validatedId })
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
if (!variant) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Variant with ${variantId} was not found`
)
}
return variant
}
/**
@@ -136,12 +144,6 @@ class ProductVariantService extends BaseService {
*/
async setCurrencyPrice(variantId, currencyCode, amount) {
const variant = await this.retrieve(variantId)
if (!variant) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Variant: ${variantId} was not found`
)
}
// If prices already exist we need to update all prices with the same
// currency
@@ -207,23 +209,9 @@ class ProductVariantService extends BaseService {
*/
async getRegionPrice(variantId, regionId) {
const variant = await this.retrieve(variantId)
if (!variant) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Variant: ${variantId} was not found`
)
}
const region = await this.regionService_.retrieve(regionId)
if (!region) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Region: ${regionId} was not found`
)
}
let price
variant.prices.forEach(({ region_id, amount, currency_code }) => {
if (!price && !region_id && currency_code === region.currency_code) {
// If we haven't yet found a price and the current money amount is
@@ -258,20 +246,7 @@ class ProductVariantService extends BaseService {
*/
async setRegionPrice(variantId, regionId, amount) {
const variant = await this.retrieve(variantId)
if (!variant) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Variant: ${variantId} was not found`
)
}
const region = await this.regionService_.retrieve(regionId)
if (!region) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Region: ${regionId} was not found`
)
}
// If prices already exist we need to update all prices with the same currency
if (variant.prices.length) {
@@ -358,12 +333,6 @@ class ProductVariantService extends BaseService {
}
const variant = await this.retrieve(variantId)
if (!variant) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Variant with ${variantId} was not found`
)
}
if (typeof optionValue !== "string" && typeof optionValue !== "number") {
throw new MedusaError(
@@ -373,7 +342,7 @@ class ProductVariantService extends BaseService {
}
return this.productVariantModel_.updateOne(
{ _id: variantId },
{ _id: variant._id },
{ $push: { options: { option_id: optionId, value: `${optionValue}` } } }
)
}
@@ -421,12 +390,6 @@ class ProductVariantService extends BaseService {
*/
async canCoverQuantity(variantId, quantity) {
const variant = await this.retrieve(variantId)
if (!variant) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Variant with ${variantId} was not found`
)
}
const { inventory_quantity, allow_backorder, manage_inventory } = variant
return (
@@ -449,14 +412,16 @@ class ProductVariantService extends BaseService {
* @return {Promise} the result of the delete operation.
*/
async delete(variantId) {
const variant = await this.retrieve(variantId)
// Delete is idempotent, but we return a promise to allow then-chaining
if (!variant) {
let variant
try {
variant = await this.retrieve(variantId)
} catch (error) {
// Delete is idempotent, but we return a promise to allow then-chaining
return Promise.resolve()
}
return this.productVariantModel_
.deleteOne({ _id: variantId })
.deleteOne({ _id: variant._id })
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})

View File

@@ -50,14 +50,25 @@ class ProductService extends BaseService {
/**
* Gets a product by id.
* Throws in case of DB Error and if product was not found.
* @param {string} productId - the id of the product to get.
* @return {Promise<Product>} the product document.
*/
retrieve(productId) {
async retrieve(productId) {
const validatedId = this.validateId_(productId)
return this.productModel_.findOne({ _id: validatedId }).catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
const product = await this.productModel_
.findOne({ _id: validatedId })
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
if (!product) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Product with ${productId} was not found`
)
}
return product
}
/**
@@ -134,9 +145,11 @@ class ProductService extends BaseService {
* @return {Promise} the result of the delete operation.
*/
async delete(productId) {
const product = await this.retrieve(productId)
// Delete is idempotent, but we return a promise to allow then-chaining
if (!product) {
let product
try {
product = await this.retrieve(productId)
} catch (error) {
// Delete is idempotent, but we return a promise to allow then-chaining
return Promise.resolve()
}
@@ -160,20 +173,8 @@ class ProductService extends BaseService {
*/
async addVariant(productId, variantId) {
const product = await this.retrieve(productId)
if (!product) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Product with ${product._id} was not found`
)
}
const variant = await this.productVariantService_.retrieve(variantId)
if (!variant) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Variant with ${variantId} was not found`
)
}
if (product.options.length !== variant.options.length) {
throw new MedusaError(
@@ -227,12 +228,6 @@ class ProductService extends BaseService {
*/
async addOption(productId, optionTitle) {
const product = await this.retrieve(productId)
if (!product) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Product with ${product._id} was not found`
)
}
// Make sure that option doesn't already exist
if (product.options.find(o => o.title === optionTitle)) {
@@ -294,12 +289,6 @@ class ProductService extends BaseService {
async reorderVariants(productId, variantOrder) {
const product = await this.retrieve(productId)
if (!product) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Product with ${product._id} was not found`
)
}
if (product.variants.length !== variantOrder.length) {
throw new MedusaError(
@@ -341,12 +330,6 @@ class ProductService extends BaseService {
*/
async reorderOptions(productId, optionOrder) {
const product = await this.retrieve(productId)
if (!product) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Product with ${product._id} was not found`
)
}
if (product.options.length !== optionOrder.length) {
throw new MedusaError(
@@ -387,12 +370,6 @@ class ProductService extends BaseService {
*/
async updateOption(productId, optionId, data) {
const product = await this.retrieve(productId)
if (!product) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Product with ${product._id} was not found`
)
}
const option = product.options.find(o => o._id === optionId)
if (!option) {
@@ -436,12 +413,6 @@ class ProductService extends BaseService {
*/
async deleteOption(productId, optionId) {
const product = await this.retrieve(productId)
if (!product) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Product with ${product._id} was not found`
)
}
if (!product.options.find(o => o._id === optionId)) {
return Promise.resolve()
@@ -510,15 +481,9 @@ class ProductService extends BaseService {
*/
async removeVariant(productId, variantId) {
const product = await this.retrieve(productId)
if (!product) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Product with ${product._id} was not found`
)
}
return this.productModel_.updateOne(
{ _id: productId },
{ _id: product._id },
{
$pull: {
variants: variantId,

View File

@@ -68,16 +68,26 @@ class UserService extends BaseService {
/**
* Gets a user by id.
* Throws in case of DB Error and if user was not found.
* @param {string} userId - the id of the user to get.
* @return {Promise<User>} the user document.
*/
retrieve(userId) {
async retrieve(userId) {
const validatedId = this.validateId_(userId)
return this.userModel_.findOne({ _id: validatedId }).catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
const user = await this.userModel_
.findOne({ _id: validatedId })
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
if (!user) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`User with ${userId} was not found`
)
}
return user
}
/**
* Creates a user with username being validated.
* Fails if email is not a valid format.
@@ -99,9 +109,11 @@ class UserService extends BaseService {
* @return {Promise} the result of the delete operation.
*/
async delete(userId) {
const user = await this.retrieve(userId)
// Delete is idempotent, but we return a promise to allow then-chaining
if (!user) {
let user
try {
user = await this.retrieve(userId)
} catch (error) {
// delete is idempotent, but we return a promise to allow then-chaining
return Promise.resolve()
}
@@ -120,12 +132,6 @@ class UserService extends BaseService {
*/
async setPassword(userId, password) {
const user = await this.retrieve(userId)
if (!user) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`User with ${userId} was not found`
)
}
const hashedPassword = await bcrypt.hash(password, 10)
if (!hashedPassword) {
@@ -136,7 +142,7 @@ class UserService extends BaseService {
}
return this.userModel_.updateOne(
{ _id: userId },
{ _id: user._id },
{ $set: { password: hashedPassword } }
)
}
@@ -152,12 +158,6 @@ class UserService extends BaseService {
*/
async generateResetPasswordToken(userId) {
const user = await this.retrieve(userId)
if (!user) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`User with ${userId} was not found`
)
}
const secret = user.passwordHash
const expiry = Math.floor(Date.now() / 1000) + 60 * 15
const payload = { userId: user._id, exp: expiry }