Refactors retrieve function in services

This commit is contained in:
olivermrbl
2020-03-10 11:36:14 +01:00
parent 8d51a3f716
commit 9014d2bd1b
6 changed files with 106 additions and 238 deletions
+17 -63
View File
@@ -150,11 +150,21 @@ class CartService extends BaseService {
* @param {string} cartId - the id of the cart to get. * @param {string} cartId - the id of the cart to get.
* @return {Promise<Cart>} the cart document. * @return {Promise<Cart>} the cart document.
*/ */
retrieve(cartId) { async retrieve(cartId) {
const validatedId = this.validateId_(cartId) const validatedId = this.validateId_(cartId)
return this.cartModel_.findOne({ _id: validatedId }).catch(err => { const cart = await this.cartModel_
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message) .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) 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_ return this.cartModel_
.create({ .create({
region_id, region_id: region._id,
}) })
.catch(err => { .catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message) throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
@@ -211,12 +215,6 @@ class CartService extends BaseService {
const validatedLineItem = this.lineItemService_.validate(lineItem) const validatedLineItem = this.lineItemService_.validate(lineItem)
const cart = await this.retrieve(cartId) 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 => const currentItem = cart.items.find(line =>
_.isEqual(line.content, validatedLineItem.content) _.isEqual(line.content, validatedLineItem.content)
@@ -285,12 +283,6 @@ class CartService extends BaseService {
*/ */
async updateEmail(cartId, email) { async updateEmail(cartId, email) {
const cart = await this.retrieve(cartId) const cart = await this.retrieve(cartId)
if (!cart) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
"The cart was not found"
)
}
const schema = Validator.string() const schema = Validator.string()
.email() .email()
@@ -305,7 +297,7 @@ class CartService extends BaseService {
return this.cartModel_.updateOne( return this.cartModel_.updateOne(
{ {
_id: cartId, _id: cart._id,
}, },
{ {
$set: { email: value }, $set: { email: value },
@@ -321,12 +313,6 @@ class CartService extends BaseService {
*/ */
async updateBillingAddress(cartId, address) { async updateBillingAddress(cartId, address) {
const cart = await this.retrieve(cartId) 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) const { value, error } = Validator.address().validate(address)
if (error) { if (error) {
@@ -338,7 +324,7 @@ class CartService extends BaseService {
return this.cartModel_.updateOne( return this.cartModel_.updateOne(
{ {
_id: cartId, _id: cart._id,
}, },
{ {
$set: { billing_address: value }, $set: { billing_address: value },
@@ -354,12 +340,6 @@ class CartService extends BaseService {
*/ */
async updateShippingAddress(cartId, address) { async updateShippingAddress(cartId, address) {
const cart = await this.retrieve(cartId) 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) const { value, error } = Validator.address().validate(address)
if (error) { if (error) {
@@ -394,20 +374,7 @@ class CartService extends BaseService {
*/ */
async setPaymentMethod(cartId, paymentMethod) { async setPaymentMethod(cartId, paymentMethod) {
const cart = await this.retrieve(cartId) 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) 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 // The region must have the provider id in its providers array
if ( if (
@@ -454,20 +421,7 @@ class CartService extends BaseService {
*/ */
async setRegion(cartId, regionId) { async setRegion(cartId, regionId) {
const cart = await this.retrieve(cartId) 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) const region = await this.regionService_.retrieve(regionId)
if (!region) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`The region: ${regionId} was not found`
)
}
let update = { let update = {
region_id: region._id, region_id: region._id,
+26 -29
View File
@@ -81,11 +81,21 @@ class CustomerService extends BaseService {
* @param {string} customerId - the id of the customer to get. * @param {string} customerId - the id of the customer to get.
* @return {Promise<Customer>} the customer document. * @return {Promise<Customer>} the customer document.
*/ */
retrieve(customerId) { async retrieve(customerId) {
const validatedId = this.validateId_(customerId) const validatedId = this.validateId_(customerId)
return this.customerModel_.findOne({ _id: validatedId }).catch(err => { const customer = await this.customerModel_
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message) .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) { async updateEmail(customerId, email) {
const customer = await this.retrieve(customerId) const customer = await this.retrieve(customerId)
if (!customer) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Customer with ${customerId} was not found`
)
}
this.validateEmail_(email) this.validateEmail_(email)
return this.customerModel_.updateOne( return this.customerModel_.updateOne(
{ {
_id: customerId, _id: customer._id,
}, },
{ {
$set: { email }, $set: { email },
@@ -140,18 +143,12 @@ class CustomerService extends BaseService {
*/ */
async updateBillingAddress(customerId, address) { async updateBillingAddress(customerId, address) {
const customer = await this.retrieve(customerId) const customer = await this.retrieve(customerId)
if (!customer) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Customer with ${customerId} was not found`
)
}
this.validateBillingAddress_(address) this.validateBillingAddress_(address)
return this.customerModel_.updateOne( return this.customerModel_.updateOne(
{ {
_id: customerId, _id: customer._id,
}, },
{ {
$set: { billing_address: address }, $set: { billing_address: address },
@@ -170,12 +167,6 @@ class CustomerService extends BaseService {
*/ */
async update(customerId, update) { async update(customerId, update) {
const customer = await this.retrieve(customerId) const customer = await this.retrieve(customerId)
if (!customer) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Customer with ${customerId} was not found`
)
}
if (update.metadata) { if (update.metadata) {
throw new MedusaError( throw new MedusaError(
@@ -192,7 +183,11 @@ class CustomerService extends BaseService {
} }
return this.customerModel_ return this.customerModel_
.updateOne({ _id: customerId }, { $set: update }, { runValidators: true }) .updateOne(
{ _id: customer._id },
{ $set: update },
{ runValidators: true }
)
.catch(err => { .catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message) 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. * @return {Promise} the result of the delete operation.
*/ */
async delete(customerId) { async delete(customerId) {
const customer = await this.retrieve(customerId) let customer
// Delete is idempotent, but we return a promise to allow then-chaining try {
if (!customer) { customer = await this.retrieve(customerId)
} catch (error) {
// Delete is idempotent, but we return a promise to allow then-chaining
return Promise.resolve() return Promise.resolve()
} }
+3 -16
View File
@@ -82,20 +82,7 @@ class LineItemService extends BaseService {
*/ */
async generate(variantId, regionId, quantity) { async generate(variantId, regionId, quantity) {
const variant = await this.productVariantService_.retrieve(variantId) const variant = await this.productVariantService_.retrieve(variantId)
if (!variant) { const region = await this.regionService_.retrieve(regionId)
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 products = await this.productService_.list({ variants: variantId }) const products = await this.productService_.list({ variants: variantId })
// this should never fail, since a variant must have a product associated // 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 product = products[0]
const unit_price = await this.productVariantService_.getRegionPrice( const unit_price = await this.productVariantService_.getRegionPrice(
variantId, variant._id,
regionId region._id
) )
return { return {
+18 -53
View File
@@ -52,13 +52,21 @@ class ProductVariantService extends BaseService {
* @param {string} variantId - the id of the product to get. * @param {string} variantId - the id of the product to get.
* @return {Promise<Product>} the product document. * @return {Promise<Product>} the product document.
*/ */
retrieve(variantId) { async retrieve(variantId) {
const validatedId = this.validateId_(variantId) const validatedId = this.validateId_(variantId)
return this.productVariantModel_ const variant = await this.productVariantModel_
.findOne({ _id: validatedId }) .findOne({ _id: validatedId })
.catch(err => { .catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message) 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) { async setCurrencyPrice(variantId, currencyCode, amount) {
const variant = await this.retrieve(variantId) 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 // If prices already exist we need to update all prices with the same
// currency // currency
@@ -207,23 +209,9 @@ class ProductVariantService extends BaseService {
*/ */
async getRegionPrice(variantId, regionId) { async getRegionPrice(variantId, regionId) {
const variant = await this.retrieve(variantId) 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) const region = await this.regionService_.retrieve(regionId)
if (!region) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Region: ${regionId} was not found`
)
}
let price let price
variant.prices.forEach(({ region_id, amount, currency_code }) => { variant.prices.forEach(({ region_id, amount, currency_code }) => {
if (!price && !region_id && currency_code === region.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 // If we haven't yet found a price and the current money amount is
@@ -258,23 +246,10 @@ class ProductVariantService extends BaseService {
*/ */
async setRegionPrice(variantId, regionId, amount) { async setRegionPrice(variantId, regionId, amount) {
const variant = await this.retrieve(variantId) 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) 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 prices already exist we need to update all prices with the same currency
if (variant.prices.length) { if (varint.prices.length) {
let foundRegion = false let foundRegion = false
const newPrices = variant.prices.map(moneyAmount => { const newPrices = variant.prices.map(moneyAmount => {
if (moneyAmount.region_id === region._id) { if (moneyAmount.region_id === region._id) {
@@ -358,12 +333,6 @@ class ProductVariantService extends BaseService {
} }
const variant = await this.retrieve(variantId) 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") { if (typeof optionValue !== "string" && typeof optionValue !== "number") {
throw new MedusaError( throw new MedusaError(
@@ -373,7 +342,7 @@ class ProductVariantService extends BaseService {
} }
return this.productVariantModel_.updateOne( return this.productVariantModel_.updateOne(
{ _id: variantId }, { _id: variant._id },
{ $push: { options: { option_id: optionId, value: `${optionValue}` } } } { $push: { options: { option_id: optionId, value: `${optionValue}` } } }
) )
} }
@@ -421,12 +390,6 @@ class ProductVariantService extends BaseService {
*/ */
async canCoverQuantity(variantId, quantity) { async canCoverQuantity(variantId, quantity) {
const variant = await this.retrieve(variantId) 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 const { inventory_quantity, allow_backorder, manage_inventory } = variant
return ( return (
@@ -449,14 +412,16 @@ class ProductVariantService extends BaseService {
* @return {Promise} the result of the delete operation. * @return {Promise} the result of the delete operation.
*/ */
async delete(variantId) { async delete(variantId) {
const variant = await this.retrieve(variantId) let variant
// Delete is idempotent, but we return a promise to allow then-chaining try {
if (!variant) { variant = await this.retrieve(variantId)
} catch (error) {
// Delete is idempotent, but we return a promise to allow then-chaining
return Promise.resolve() return Promise.resolve()
} }
return this.productVariantModel_ return this.productVariantModel_
.deleteOne({ _id: variantId }) .deleteOne({ _id: variant._id })
.catch(err => { .catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message) throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
}) })
+21 -56
View File
@@ -50,14 +50,25 @@ class ProductService extends BaseService {
/** /**
* Gets a product by id. * 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. * @param {string} productId - the id of the product to get.
* @return {Promise<Product>} the product document. * @return {Promise<Product>} the product document.
*/ */
retrieve(productId) { async retrieve(productId) {
const validatedId = this.validateId_(productId) const validatedId = this.validateId_(productId)
return this.productModel_.findOne({ _id: validatedId }).catch(err => { const product = await this.productModel_
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message) .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. * @return {Promise} the result of the delete operation.
*/ */
async delete(productId) { async delete(productId) {
const product = await this.retrieve(productId) let product
// Delete is idempotent, but we return a promise to allow then-chaining try {
if (!product) { product = await this.retrieve(productId)
} catch (error) {
// Delete is idempotent, but we return a promise to allow then-chaining
return Promise.resolve() return Promise.resolve()
} }
@@ -160,20 +173,8 @@ class ProductService extends BaseService {
*/ */
async addVariant(productId, variantId) { async addVariant(productId, variantId) {
const product = await this.retrieve(productId) 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) 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) { if (product.options.length !== variant.options.length) {
throw new MedusaError( throw new MedusaError(
@@ -227,12 +228,6 @@ class ProductService extends BaseService {
*/ */
async addOption(productId, optionTitle) { async addOption(productId, optionTitle) {
const product = await this.retrieve(productId) 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 // Make sure that option doesn't already exist
if (product.options.find(o => o.title === optionTitle)) { if (product.options.find(o => o.title === optionTitle)) {
@@ -294,12 +289,6 @@ class ProductService extends BaseService {
async reorderVariants(productId, variantOrder) { async reorderVariants(productId, variantOrder) {
const product = await this.retrieve(productId) 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) { if (product.variants.length !== variantOrder.length) {
throw new MedusaError( throw new MedusaError(
@@ -341,12 +330,6 @@ class ProductService extends BaseService {
*/ */
async reorderOptions(productId, optionOrder) { async reorderOptions(productId, optionOrder) {
const product = await this.retrieve(productId) 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) { if (product.options.length !== optionOrder.length) {
throw new MedusaError( throw new MedusaError(
@@ -387,12 +370,6 @@ class ProductService extends BaseService {
*/ */
async updateOption(productId, optionId, data) { async updateOption(productId, optionId, data) {
const product = await this.retrieve(productId) 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) const option = product.options.find(o => o._id === optionId)
if (!option) { if (!option) {
@@ -436,12 +413,6 @@ class ProductService extends BaseService {
*/ */
async deleteOption(productId, optionId) { async deleteOption(productId, optionId) {
const product = await this.retrieve(productId) 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)) { if (!product.options.find(o => o._id === optionId)) {
return Promise.resolve() return Promise.resolve()
@@ -510,15 +481,9 @@ class ProductService extends BaseService {
*/ */
async removeVariant(productId, variantId) { async removeVariant(productId, variantId) {
const product = await this.retrieve(productId) 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( return this.productModel_.updateOne(
{ _id: productId }, { _id: product._id },
{ {
$pull: { $pull: {
variants: variantId, variants: variantId,
+21 -21
View File
@@ -68,16 +68,26 @@ class UserService extends BaseService {
/** /**
* Gets a user by id. * 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. * @param {string} userId - the id of the user to get.
* @return {Promise<User>} the user document. * @return {Promise<User>} the user document.
*/ */
retrieve(userId) { async retrieve(userId) {
const validatedId = this.validateId_(userId) const validatedId = this.validateId_(userId)
return this.userModel_.findOne({ _id: validatedId }).catch(err => { const user = await this.userModel_
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message) .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. * Creates a user with username being validated.
* Fails if email is not a valid format. * Fails if email is not a valid format.
@@ -99,9 +109,11 @@ class UserService extends BaseService {
* @return {Promise} the result of the delete operation. * @return {Promise} the result of the delete operation.
*/ */
async delete(userId) { async delete(userId) {
const user = await this.retrieve(userId) let user
// Delete is idempotent, but we return a promise to allow then-chaining try {
if (!user) { user = await this.retrieve(userId)
} catch (error) {
// delete is idempotent, but we return a promise to allow then-chaining
return Promise.resolve() return Promise.resolve()
} }
@@ -120,12 +132,6 @@ class UserService extends BaseService {
*/ */
async setPassword(userId, password) { async setPassword(userId, password) {
const user = await this.retrieve(userId) 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) const hashedPassword = await bcrypt.hash(password, 10)
if (!hashedPassword) { if (!hashedPassword) {
@@ -136,7 +142,7 @@ class UserService extends BaseService {
} }
return this.userModel_.updateOne( return this.userModel_.updateOne(
{ _id: userId }, { _id: user._id },
{ $set: { password: hashedPassword } } { $set: { password: hashedPassword } }
) )
} }
@@ -152,12 +158,6 @@ class UserService extends BaseService {
*/ */
async generateResetPasswordToken(userId) { async generateResetPasswordToken(userId) {
const user = await this.retrieve(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 secret = user.passwordHash
const expiry = Math.floor(Date.now() / 1000) + 60 * 15 const expiry = Math.floor(Date.now() / 1000) + 60 * 15
const payload = { userId: user._id, exp: expiry } const payload = { userId: user._id, exp: expiry }