Merge branch 'integration/dummy-project' of github.com:medusajs/medusa into integration/dummy-project

This commit is contained in:
Sebastian Rindom committed 2020-07-04 12:16:37 +02:00
commit e9c80e80a4
67 files changed
+13988 -178

No files matched your search

+1 -1
View File
@@ -72,4 +72,4 @@
"winston": "^3.2.1"
},
"gitHead": "35e0930650d5f4aedf2610749cd131ae8b7e17cc"
}
}
@@ -43,6 +43,8 @@ export default async (req, res) => {
delete value.variants
const productService = req.scope.resolve("productService")
const shippingProfileService = req.scope.resolve("shippingProfileService")
let newProduct = await productService.createDraft(value)
if (variants) {
@@ -64,6 +66,10 @@ export default async (req, res) => {
)
}
// Add to default shipping profile
const { _id } = await shippingProfileService.retrieveDefault()
await shippingProfileService.addProduct(_id, newProduct._id)
newProduct = await productService.decorate(newProduct, [
"title",
"description",
@@ -12,6 +12,8 @@ describe("POST /admin/shipping-options", () => {
name: "Test option",
region_id: "testregion",
provider_id: "test_provider",
data: { id: "test" },
profile_id: "test",
price: {
type: "flat_rate",
amount: 100,
@@ -32,6 +34,7 @@ describe("POST /admin/shipping-options", () => {
})
it("returns 200", () => {
console.log(subject)
expect(subject.status).toEqual(200)
})
@@ -41,6 +44,8 @@ describe("POST /admin/shipping-options", () => {
name: "Test option",
region_id: "testregion",
provider_id: "test_provider",
data: { id: "test" },
profile_id: "test",
price: {
type: "flat_rate",
amount: 100,
@@ -5,11 +5,14 @@ export default async (req, res) => {
name: Validator.string().required(),
region_id: Validator.string().required(),
provider_id: Validator.string().required(),
data: Validator.object(),
price: Validator.object().keys({
type: Validator.string().required(),
amount: Validator.number().optional(),
}),
profile_id: Validator.string().required(),
data: Validator.object().required(),
price: Validator.object()
.keys({
type: Validator.string().required(),
amount: Validator.number().optional(),
})
.required(),
requirements: Validator.array()
.items(
Validator.object({
@@ -27,10 +30,17 @@ export default async (req, res) => {
try {
const optionService = req.scope.resolve("shippingOptionService")
const shippingProfileService = req.scope.resolve("shippingProfileService")
const data = await optionService.create(value)
// Add to default shipping profile
const { _id } = await shippingProfileService.retrieveDefault()
await shippingProfileService.addShippingOption(_id, data._id)
res.status(200).json({ shipping_option: data })
} catch (err) {
console.log(err)
throw err
}
}
@@ -12,6 +12,7 @@ export default async (req, res) => {
discounts: Validator.array().items({
code: Validator.string(),
}),
customer_id: Validator.string(),
})
const { value, error } = schema.validate(req.body)
@@ -27,6 +28,10 @@ export default async (req, res) => {
}
try {
if (value.customer_id) {
await cartService.updateCustomerId(id, value.customer_id)
}
if (value.region_id) {
await cartService.setRegion(id, value.region_id)
}
@@ -17,7 +17,7 @@ export default async (req, res) => {
try {
const customerService = req.scope.resolve("customerService")
const customer = await customerService.create(value)
const data = await customerService.decorate(customer)
const data = await customerService.decorate(customer, ["_id", "email"])
res.status(201).json({ customer: data })
} catch (err) {
throw err
+7
View File
@@ -0,0 +1,7 @@
export default async ({ container }) => {
const storeService = container.resolve("storeService")
const profileService = container.resolve("shippingProfileService")
await storeService.create()
await profileService.createDefault()
}
+3 -3
View File
@@ -6,7 +6,7 @@ import modelsLoader from "./models"
import servicesLoader from "./services"
import passportLoader from "./passport"
import pluginsLoader from "./plugins"
import storeLoader from "./store"
import defaultsLoader from "./defaults"
import Logger from "./logger"
export default async ({ directory: rootDirectory, expressApp }) => {
@@ -58,8 +58,8 @@ export default async ({ directory: rootDirectory, expressApp }) => {
await apiLoader({ container, rootDirectory, app: expressApp })
Logger.info("API initialized")
await storeLoader({ container })
Logger.info("Store initialized")
await defaultsLoader({ container })
Logger.info("Defaults initialized")
return { container, dbConnection, app: expressApp }
}
-7
View File
@@ -1,7 +0,0 @@
/**
* Registers all services in the services directory
*/
export default ({ container }) => {
const storeService = container.resolve("storeService")
return storeService.create()
}
@@ -13,6 +13,8 @@ class ProductVariantModel extends BaseModel {
static schema = {
title: { type: String, required: true },
prices: { type: [MoneyAmountSchema], default: [], required: true },
sku: { type: String, default: "" },
barcode: { type: String, default: "" },
options: { type: [OptionValueSchema], default: [] },
sku: { type: String, unique: true, sparse: true },
ean: { type: String, unique: true, sparse: true },
@@ -31,6 +31,9 @@ export const ShippingProfileServiceMock = {
}
return Promise.resolve()
}),
retrieveDefault: jest.fn().mockImplementation(data => {
return Promise.resolve({ _id: IdMap.getId("default_shipping_profile") })
}),
list: jest.fn().mockImplementation(selector => {
if (!selector) {
return Promise.resolve([])
@@ -5,11 +5,13 @@ import { PaymentProviderServiceMock } from "../__mocks__/payment-provider"
import { FulfillmentProviderServiceMock } from "../__mocks__/fulfillment-provider"
import { ShippingProfileServiceMock } from "../__mocks__/shipping-profile"
import { TotalsServiceMock } from "../__mocks__/totals"
import { EventBusServiceMock } from "../__mocks__/event-bus"
describe("OrderService", () => {
describe("create", () => {
const orderService = new OrderService({
orderModel: OrderModelMock,
eventBusService: EventBusServiceMock,
})
beforeEach(async () => {
@@ -54,6 +56,7 @@ describe("OrderService", () => {
describe("update", () => {
const orderService = new OrderService({
orderModel: OrderModelMock,
eventBusService: EventBusServiceMock,
})
beforeEach(async () => {
@@ -182,6 +185,7 @@ describe("OrderService", () => {
describe("cancel", () => {
const orderService = new OrderService({
orderModel: OrderModelMock,
eventBusService: EventBusServiceMock,
})
beforeEach(async () => {
@@ -252,6 +256,7 @@ describe("OrderService", () => {
paymentProviderService: PaymentProviderServiceMock,
fulfillmentProviderService: FulfillmentProviderServiceMock,
shippingProfileService: ShippingProfileServiceMock,
eventBusService: EventBusServiceMock,
})
beforeEach(async () => {
@@ -4,6 +4,7 @@ import ProductVariantService from "../product-variant"
import { ProductVariantModelMock } from "../../models/__mocks__/product-variant"
import { ProductServiceMock } from "../__mocks__/product"
import { RegionServiceMock } from "../__mocks__/region"
import { EventBusServiceMock } from "../__mocks__/event-bus"
describe("ProductVariantService", () => {
describe("retrieve", () => {
@@ -12,6 +13,7 @@ describe("ProductVariantService", () => {
beforeAll(async () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
eventBusService: EventBusServiceMock,
})
res = await productVariantService.retrieve(IdMap.getId("validId"))
@@ -38,6 +40,7 @@ describe("ProductVariantService", () => {
beforeAll(async () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
eventBusService: EventBusServiceMock,
})
await productVariantService
@@ -69,6 +72,7 @@ describe("ProductVariantService", () => {
jest.clearAllMocks()
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
eventBusService: EventBusServiceMock,
})
productVariantService.createDraft({
@@ -106,6 +110,7 @@ describe("ProductVariantService", () => {
jest.clearAllMocks()
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
eventBusService: EventBusServiceMock,
})
productVariantService.publish(IdMap.getId("variantId"))
@@ -124,6 +129,7 @@ describe("ProductVariantService", () => {
describe("update", () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -168,6 +174,7 @@ describe("ProductVariantService", () => {
describe("decorate", () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
eventBusService: EventBusServiceMock,
})
const fakeVariant = {
@@ -216,6 +223,7 @@ describe("ProductVariantService", () => {
describe("setMetadata", () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -264,6 +272,7 @@ describe("ProductVariantService", () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
productService: ProductServiceMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -331,6 +340,7 @@ describe("ProductVariantService", () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
productService: ProductServiceMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -354,6 +364,7 @@ describe("ProductVariantService", () => {
describe("delete", () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -373,6 +384,7 @@ describe("ProductVariantService", () => {
describe("canCoverQuantity", () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -419,6 +431,7 @@ describe("ProductVariantService", () => {
describe("setCurrencyPrice", () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -519,6 +532,7 @@ describe("ProductVariantService", () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
regionService: RegionServiceMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -619,6 +633,7 @@ describe("ProductVariantService", () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
regionService: RegionServiceMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -6,6 +6,7 @@ import {
ProductVariantServiceMock,
variants,
} from "../__mocks__/product-variant"
import { EventBusServiceMock } from "../__mocks__/event-bus"
describe("ProductService", () => {
describe("retrieve", () => {
@@ -14,6 +15,7 @@ describe("ProductService", () => {
beforeAll(async () => {
const productService = new ProductService({
productModel: ProductModelMock,
eventBusService: EventBusServiceMock,
})
res = await productService.retrieve(IdMap.getId("validId"))
@@ -40,6 +42,7 @@ describe("ProductService", () => {
beforeAll(async () => {
const productService = new ProductService({
productModel: ProductModelMock,
eventBusService: EventBusServiceMock,
})
await productService.retrieve(IdMap.getId("failId")).catch(err => {
@@ -70,6 +73,7 @@ describe("ProductService", () => {
jest.clearAllMocks()
const productService = new ProductService({
productModel: ProductModelMock,
eventBusService: EventBusServiceMock,
})
productService.createDraft({
@@ -108,6 +112,7 @@ describe("ProductService", () => {
const productService = new ProductService({
productModel: ProductModelMock,
productVariantService: ProductVariantServiceMock,
eventBusService: EventBusServiceMock,
})
productService.publish(IdMap.getId("productId"))
@@ -127,6 +132,7 @@ describe("ProductService", () => {
const productService = new ProductService({
productModel: ProductModelMock,
productVariantService: ProductVariantServiceMock,
eventBusService: EventBusServiceMock,
})
const fakeProduct = {
@@ -193,6 +199,7 @@ describe("ProductService", () => {
describe("setMetadata", () => {
const productService = new ProductService({
productModel: ProductModelMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -236,6 +243,7 @@ describe("ProductService", () => {
describe("update", () => {
const productService = new ProductService({
productModel: ProductModelMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -290,6 +298,7 @@ describe("ProductService", () => {
const productService = new ProductService({
productModel: ProductModelMock,
productVariantService: ProductVariantServiceMock,
eventBusService: EventBusServiceMock,
})
beforeEach(() => {
@@ -314,6 +323,7 @@ describe("ProductService", () => {
const productService = new ProductService({
productModel: ProductModelMock,
productVariantService: ProductVariantServiceMock,
eventBusService: EventBusServiceMock,
})
afterEach(() => {
@@ -479,6 +489,7 @@ describe("ProductService", () => {
const productService = new ProductService({
productModel: ProductModelMock,
productVariantService: ProductVariantServiceMock,
eventBusService: EventBusServiceMock,
})
afterEach(() => {
@@ -571,6 +582,7 @@ describe("ProductService", () => {
const productService = new ProductService({
productModel: ProductModelMock,
productVariantService: ProductVariantServiceMock,
eventBusService: EventBusServiceMock,
})
afterEach(() => {
@@ -632,6 +644,7 @@ describe("ProductService", () => {
const productService = new ProductService({
productModel: ProductModelMock,
productVariantService: ProductVariantServiceMock,
eventBusService: EventBusServiceMock,
})
afterEach(() => {
@@ -659,6 +672,7 @@ describe("ProductService", () => {
const productService = new ProductService({
productModel: ProductModelMock,
productVariantService: ProductVariantServiceMock,
eventBusService: EventBusServiceMock,
})
afterEach(() => {
@@ -719,6 +733,7 @@ describe("ProductService", () => {
const productService = new ProductService({
productModel: ProductModelMock,
productVariantService: ProductVariantServiceMock,
eventBusService: EventBusServiceMock,
})
afterEach(() => {
@@ -788,6 +803,7 @@ describe("ProductService", () => {
const productService = new ProductService({
productModel: ProductModelMock,
productVariantService: ProductVariantServiceMock,
eventBusService: EventBusServiceMock,
})
afterEach(() => {
@@ -843,6 +859,7 @@ describe("ProductService", () => {
const productService = new ProductService({
productModel: ProductModelMock,
productVariantService: ProductVariantServiceMock,
eventBusService: EventBusServiceMock,
})
afterEach(() => {
+34
View File
@@ -370,6 +370,40 @@ class CartService extends BaseService {
return result
})
}
/**
* Sets the customer id of a cart
* @param {string} cartId - the id of the cart to add email to
* @param {string} customerId - the customer to add to cart
* @return {Promise} the result of the update operation
*/
async updateCustomerId(cartId, customerId) {
const cart = await this.retrieve(cartId)
const schema = Validator.string()
.objectId()
.required()
const { value, error } = schema.validate(customerId)
if (error) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"The customerId is not valid"
)
}
return this.cartModel_
.updateOne(
{
_id: cart._id,
},
{
$set: { customer_id: value },
}
)
.then(result => {
// Notify subscribers
this.eventBus_.emit(CartService.Events.UPDATED, result)
return result
})
}
/**
* Sets the email of a cart
+10 -5
View File
@@ -9,6 +9,10 @@ import { BaseService } from "medusa-interfaces"
* @implements BaseService
*/
class CustomerService extends BaseService {
static Events = {
PASSWORD_RESET: "customer.password_reset",
}
constructor({ customerModel, eventBusService }) {
super()
@@ -26,7 +30,7 @@ class CustomerService extends BaseService {
*/
validateId_(rawId) {
const schema = Validator.objectId()
const { value, error } = schema.validate(rawId)
const { value, error } = schema.validate(rawId.toString())
if (error) {
throw new MedusaError(
MedusaError.Types.INVALID_ARGUMENT,
@@ -92,10 +96,11 @@ class CustomerService extends BaseService {
const expiry = Math.floor(Date.now() / 1000) + 60 * 15 // 15 minutes ahead
const payload = { customer_id: customer._id, exp: expiry }
const token = jwt.sign(payload, secret)
// TODO: Call event layer to ensure that there is an email service that
// sends the token.
// Notify subscribers
this.eventBus_.emit(CustomerService.Events.PASSWORD_RESET, {
email: customer.email,
token,
})
return token
}
+1 -1
View File
@@ -35,7 +35,7 @@ class DiscountService extends BaseService {
*/
validateId_(rawId) {
const schema = Validator.objectId()
const { value, error } = schema.validate(rawId)
const { value, error } = schema.validate(rawId.toString())
if (error) {
throw new MedusaError(
MedusaError.Types.INVALID_ARGUMENT,
@@ -14,7 +14,7 @@ class FulfillmentProviderService {
*/
retrieveProvider(provider_id) {
try {
return this.container_.resolve(`fp_${provider_id}`)
return this.container_[`fp_${provider_id}`]
} catch (err) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
+64 -20
View File
@@ -3,6 +3,12 @@ import { Validator, MedusaError } from "medusa-core-utils"
import { BaseService } from "medusa-interfaces"
class OrderService extends BaseService {
static Events = {
PLACED: "order.placed",
UPDATED: "order.updated",
CANCELLED: "order.cancelled",
}
constructor({
orderModel,
paymentProviderService,
@@ -43,7 +49,7 @@ class OrderService extends BaseService {
*/
validateId_(rawId) {
const schema = Validator.objectId()
const { value, error } = schema.validate(rawId)
const { value, error } = schema.validate(rawId.toString())
if (error) {
throw new MedusaError(
MedusaError.Types.INVALID_ARGUMENT,
@@ -139,15 +145,30 @@ class OrderService extends BaseService {
return order
}
/**
* @param {Object} selector - the query object for find
* @return {Promise} the result of the find operation
*/
list(selector) {
return this.orderModel_.find(selector)
}
/**
* Creates an order
* @param {object} order - the order to create
* @return {Promise} resolves to the creation result.
*/
async create(order) {
return this.orderModel_.create(order).catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
return this.orderModel_
.create(order)
.then(result => {
// Notify subscribers
this.eventBus_.emit(OrderService.Events.PLACED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
@@ -217,6 +238,11 @@ class OrderService extends BaseService {
{ $set: updateFields },
{ runValidators: true }
)
.then(result => {
// Notify subscribers
this.eventBus_.emit(OrderService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
@@ -248,14 +274,23 @@ class OrderService extends BaseService {
// TODO: cancel payment method
return this.orderModel_.updateOne(
{
_id: orderId,
},
{
$set: { status: "cancelled" },
}
)
return this.orderModel_
.updateOne(
{
_id: orderId,
},
{
$set: { status: "cancelled" },
}
)
.then(result => {
// Notify subscribers
this.eventBus_.emit(OrderService.Events.CANCELLED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
@@ -336,14 +371,23 @@ class OrderService extends BaseService {
})
)
return this.orderModel_.updateOne(
{
_id: orderId,
},
{
$set: updateFields,
}
)
return this.orderModel_
.updateOne(
{
_id: orderId,
},
{
$set: updateFields,
}
)
.then(result => {
// Notify subscribers
this.eventBus_.emit(OrderService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
+131 -58
View File
@@ -7,6 +7,11 @@ import { Validator, MedusaError } from "medusa-core-utils"
* @implements BaseService
*/
class ProductVariantService extends BaseService {
static Events = {
UPDATED: "product-variant.updated",
CREATED: "product-variant.created",
}
/** @param { productVariantModel: (ProductVariantModel) } */
constructor({ productVariantModel, eventBusService, regionService }) {
super()
@@ -73,6 +78,10 @@ class ProductVariantService extends BaseService {
...productVariant,
published: false,
})
.then(result => {
this.eventBus_.emit(ProductVariantService.Events.CREATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
@@ -83,9 +92,13 @@ class ProductVariantService extends BaseService {
* @param {string} variantId - ID of the variant to publish.
* @return {Promise} resolves to the creation result.
*/
publish(variantId) {
async publish(variantId) {
return this.productVariantModel_
.updateOne({ _id: variantId }, { $set: { published: true } })
.then(result => {
this.eventBus_.emit(ProductVariantService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
@@ -123,6 +136,10 @@ class ProductVariantService extends BaseService {
{ $set: update },
{ runValidators: true }
)
.then(result => {
this.eventBus_.emit(ProductVariantService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
@@ -163,33 +180,49 @@ class ProductVariantService extends BaseService {
})
}
return this.productVariantModel_.updateOne(
return this.productVariantModel_
.updateOne(
{
_id: variant._id,
},
{
$set: {
prices: newPrices,
},
}
)
.then(result => {
this.eventBus_.emit(ProductVariantService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
return this.productVariantModel_
.updateOne(
{
_id: variant._id,
},
{
$set: {
prices: newPrices,
prices: [
{
currency_code: currencyCode,
amount,
},
],
},
}
)
}
return this.productVariantModel_.updateOne(
{
_id: variant._id,
},
{
$set: {
prices: [
{
currency_code: currencyCode,
amount,
},
],
},
}
)
.then(result => {
this.eventBus_.emit(ProductVariantService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
@@ -262,39 +295,55 @@ class ProductVariantService extends BaseService {
})
}
return this.productVariantModel_.updateOne(
return this.productVariantModel_
.updateOne(
{
_id: variant._id,
},
{
$set: {
prices: newPrices,
},
}
)
.then(result => {
this.eventBus_.emit(ProductVariantService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
// Set the price both for default currency price and for the region
return this.productVariantModel_
.updateOne(
{
_id: variant._id,
},
{
$set: {
prices: newPrices,
prices: [
{
region_id: region._id,
currency_code: region.currency_code,
amount,
},
{
currency_code: region.currency_code,
amount,
},
],
},
}
)
}
// Set the price both for default currency price and for the region
return this.productVariantModel_.updateOne(
{
_id: variant._id,
},
{
$set: {
prices: [
{
region_id: region._id,
currency_code: region.currency_code,
amount,
},
{
currency_code: region.currency_code,
amount,
},
],
},
}
)
.then(result => {
this.eventBus_.emit(ProductVariantService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
@@ -313,10 +362,18 @@ class ProductVariantService extends BaseService {
)
}
return this.productVariantModel_.updateOne(
{ _id: variantId, "options.option_id": optionId },
{ $set: { "options.$.value": `${optionValue}` } }
)
return this.productVariantModel_
.updateOne(
{ _id: variantId, "options.option_id": optionId },
{ $set: { "options.$.value": `${optionValue}` } }
)
.then(result => {
this.eventBus_.emit(ProductVariantService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
@@ -340,10 +397,18 @@ class ProductVariantService extends BaseService {
)
}
return this.productVariantModel_.updateOne(
{ _id: variant._id },
{ $push: { options: { option_id: optionId, value: `${optionValue}` } } }
)
return this.productVariantModel_
.updateOne(
{ _id: variant._id },
{ $push: { options: { option_id: optionId, value: `${optionValue}` } } }
)
.then(result => {
this.eventBus_.emit(ProductVariantService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
@@ -357,10 +422,18 @@ class ProductVariantService extends BaseService {
* @return {Promise} the result of the update operation.
*/
async deleteOptionValue(variantId, optionId) {
return this.productVariantModel_.updateOne(
{ _id: variantId },
{ $pull: { options: { option_id: optionId } } }
)
return this.productVariantModel_
.updateOne(
{ _id: variantId },
{ $pull: { options: { option_id: optionId } } }
)
.then(result => {
this.eventBus_.emit(ProductVariantService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
@@ -384,7 +457,7 @@ class ProductVariantService extends BaseService {
* @param {Object} selector - the query object for find
* @return {Promise} the result of the find operation
*/
list(selector) {
async list(selector) {
return this.productVariantModel_.find(selector)
}
+119 -50
View File
@@ -8,6 +8,11 @@ import { BaseService } from "medusa-interfaces"
* @implements BaseService
*/
class ProductService extends BaseService {
static Events = {
UPDATED: "product.updated",
CREATED: "product.created",
}
/** @param { productModel: (ProductModel) } */
constructor({ productModel, eventBusService, productVariantService }) {
super()
@@ -86,12 +91,16 @@ class ProductService extends BaseService {
* @param {object} product - the product to create
* @return {Promise} resolves to the creation result.
*/
createDraft(product) {
async createDraft(product) {
return this.productModel_
.create({
...product,
published: false,
})
.then(result => {
this.eventBus_.emit(ProductService.Events.CREATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
@@ -102,9 +111,13 @@ class ProductService extends BaseService {
* @param {string} productId - ID of the product to publish.
* @return {Promise} resolves to the creation result.
*/
publish(productId) {
async publish(productId) {
return this.productModel_
.updateOne({ _id: productId }, { $set: { published: true } })
.then(result => {
this.eventBus_.emit(ProductService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
@@ -183,6 +196,10 @@ class ProductService extends BaseService {
{ $set: update },
{ runValidators: true }
)
.then(result => {
this.eventBus_.emit(ProductService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
@@ -266,10 +283,15 @@ class ProductService extends BaseService {
const newVariant = await this.productVariantService_.createDraft(variant)
return this.productModel_.updateOne(
{ _id: product._id },
{ $push: { variants: newVariant._id } }
)
return this.productModel_
.updateOne({ _id: product._id }, { $push: { variants: newVariant._id } })
.then(result => {
this.eventBus_.emit(ProductService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
@@ -303,7 +325,7 @@ class ProductService extends BaseService {
"Default Value"
)
)
).catch(err => {
).catch(async err => {
// If any of the variants failed to add the new option value we clean up
return Promise.all(
product.variants.map(async variantId =>
@@ -329,7 +351,11 @@ class ProductService extends BaseService {
},
}
)
.catch(err => {
.then(result => {
this.eventBus_.emit(ProductService.Events.UPDATED, result)
return result
})
.catch(async err => {
// If we failed to update the product clean up its variants
return Promise.all(
product.variants.map(async variantId =>
@@ -363,14 +389,22 @@ class ProductService extends BaseService {
return variant
})
return this.productModel_.updateOne(
{
_id: productId,
},
{
$set: { variants: newOrder },
}
)
return this.productModel_
.updateOne(
{
_id: productId,
},
{
$set: { variants: newOrder },
}
)
.then(result => {
this.eventBus_.emit(ProductService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
@@ -404,14 +438,22 @@ class ProductService extends BaseService {
return option
})
return this.productModel_.updateOne(
{
_id: productId,
},
{
$set: { options: newOrder },
}
)
return this.productModel_
.updateOne(
{
_id: productId,
},
{
$set: { options: newOrder },
}
)
.then(result => {
this.eventBus_.emit(ProductService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
@@ -448,15 +490,23 @@ class ProductService extends BaseService {
const update = {}
update["options.$.title"] = title
return this.productModel_.updateOne(
{
_id: productId,
"options._id": optionId,
},
{
$set: update,
}
)
return this.productModel_
.updateOne(
{
_id: productId,
"options._id": optionId,
},
{
$set: update,
}
)
.then(result => {
this.eventBus_.emit(ProductService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
@@ -504,16 +554,23 @@ class ProductService extends BaseService {
}
}
const result = await this.productModel_.updateOne(
{ _id: productId },
{
$pull: {
options: {
_id: optionId,
const result = await this.productModel_
.updateOne(
{ _id: productId },
{
$pull: {
options: {
_id: optionId,
},
},
},
}
)
}
)
.then(result => {
this.eventBus_.emit(ProductService.Events.UPDATED, result)
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
// If we reached this point, we can delete option value from variants
if (product.variants) {
@@ -538,14 +595,22 @@ class ProductService extends BaseService {
await this.productVariantService_.delete(variantId)
return this.productModel_.updateOne(
{ _id: product._id },
{
$pull: {
variants: variantId,
},
}
)
return this.productModel_
.updateOne(
{ _id: product._id },
{
$pull: {
variants: variantId,
},
}
)
.then(result => {
this.eventBus_.emit(ProductService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
async updateOptionValue(productId, variantId, optionId, value) {
@@ -638,6 +703,10 @@ class ProductService extends BaseService {
const keyPath = `metadata.${key}`
return this.productModel_
.updateOne({ _id: validatedId }, { $set: { [keyPath]: value } })
.then(result => {
this.eventBus_.emit(ProductService.Events.UPDATED, result)
return result
})
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
@@ -37,7 +37,7 @@ class ShippingOptionService extends BaseService {
*/
validateId_(rawId) {
const schema = Validator.objectId()
const { value, error } = schema.validate(rawId)
const { value, error } = schema.validate(rawId.toString())
if (error) {
throw new MedusaError(
MedusaError.Types.INVALID_ARGUMENT,
@@ -246,10 +246,10 @@ class ShippingOptionService extends BaseService {
}
}
if (price.type === "flat_rate" && (!price.amount || price.amount < 0)) {
if (price.type === "flat_rate" && (!price.amount || price.amount <= 0)) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"Flat rate prices must have a postive amount field."
"Flat rate prices must have be zero or have a postive amount field."
)
}
@@ -33,7 +33,7 @@ class ShippingProfileService extends BaseService {
*/
validateId_(rawId) {
const schema = Validator.objectId()
const { value, error } = schema.validate(rawId)
const { value, error } = schema.validate(rawId.toString())
if (error) {
throw new MedusaError(
MedusaError.Types.INVALID_ARGUMENT,
@@ -76,6 +76,27 @@ class ShippingProfileService extends BaseService {
return profile
}
async retrieveDefault() {
return await this.profileModel_
.findOne({ name: "default_shipping_profile" })
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
* Creates a default shipping profile, if this does not already exist.
* @return {Promise<ShippingProfile>} the shipping profile
*/
async createDefault() {
const profile = await this.retrieveDefault()
if (!profile) {
return this.profileModel_.create({ name: "default_shipping_profile" })
}
return profile
}
/**
* Creates a new shipping profile.
* @param {ShippingProfile} profile - the shipping profile to create from
+1 -1
View File
@@ -28,7 +28,7 @@ class StoreService extends BaseService {
*/
validateId_(rawId) {
const schema = Validator.objectId()
const { value, error } = schema.validate(rawId)
const { value, error } = schema.validate(rawId.toString())
if (error) {
throw new MedusaError(
MedusaError.Types.INVALID_ARGUMENT,
+9
View File
@@ -9,6 +9,10 @@ import { BaseService } from "medusa-interfaces"
* @implements BaseService
*/
class UserService extends BaseService {
static Events = {
PASSWORD_RESET: "user.password_reset",
}
constructor({ userModel, eventBusService }) {
super()
@@ -245,6 +249,11 @@ class UserService extends BaseService {
const expiry = Math.floor(Date.now() / 1000) + 60 * 15
const payload = { user_id: user._id, exp: expiry }
const token = jwt.sign(payload, secret)
// Notify subscribers
this.eventBus_.emit(UserService.Events.PASSWORD_RESET, {
email: user.email,
token,
})
return token
}
+15
View File
@@ -4522,6 +4522,14 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
medusa-core-utils@^0.3.0:
version "0.1.39"
resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-0.1.39.tgz#d57816c9bd43f9a92883650c1e66add1665291df"
integrity sha512-R8+U1ile7if+nR6Cjh5exunx0ETV0OfkWUUBUpz1KmHSDv0V0CcvQqU9lcZesPFDEbu3Y2iEjsCqidVA4nG2nQ==
dependencies:
"@hapi/joi" "^16.1.8"
joi-objectid "^3.0.1"
medusa-interfaces@^0.1.27:
version "0.1.27"
resolved "https://registry.yarnpkg.com/medusa-interfaces/-/medusa-interfaces-0.1.27.tgz#e77f9a9f82a7118eac8b35c1498ef8a5cec78898"
@@ -4529,6 +4537,13 @@ medusa-interfaces@^0.1.27:
dependencies:
mongoose "^5.8.0"
medusa-test-utils@^0.3.0:
version "0.1.39"
resolved "https://registry.yarnpkg.com/medusa-test-utils/-/medusa-test-utils-0.1.39.tgz#b7c166006a2fa4f02e52ab3bfafc19a3ae787f3e"
integrity sha512-M/Br8/HYvl7x2oLnme4NxdQwoyV0XUyOWiCyvPp7q1HUTB684lhJf1MikZVrcSjsh2L1rpyi3GRbKdf4cpJWvw==
dependencies:
mongoose "^5.8.0"
memory-pager@^1.0.2:
version "1.5.0"
resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5"