feat(medusa): Adds set and delete metadata endpoints for region and orders (#131)

This commit is contained in:
Oliver Windall Juhl
2020-11-04 11:38:04 +01:00
committed by GitHub
parent b8d1bbb204
commit d67b6e6ebe
10 changed files with 244 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
import { IdMap } from "medusa-test-utils"
import { request } from "../../../../../helpers/test-request"
import { OrderServiceMock } from "../../../../../services/__mocks__/order"
describe("DELETE /admin/orders/:id/metadata/key", () => {
describe("successfully deletes metadata on order", () => {
let subject
beforeAll(async () => {
subject = await request(
"DELETE",
`/admin/orders/${IdMap.getId("test-order")}/metadata/test-key`,
{
adminSession: {
jwt: {
userId: IdMap.getId("admin_user"),
},
},
}
)
})
it("returns 200", () => {
expect(subject.status).toEqual(200)
})
it("calls OrderService deleteMetadata", () => {
expect(OrderServiceMock.deleteMetadata).toHaveBeenCalledTimes(1)
expect(OrderServiceMock.deleteMetadata).toHaveBeenCalledWith(
IdMap.getId("test-order"),
"test-key"
)
})
})
})

View File

@@ -0,0 +1,40 @@
import { IdMap } from "medusa-test-utils"
import { request } from "../../../../../helpers/test-request"
import { OrderServiceMock } from "../../../../../services/__mocks__/order"
describe("POST /admin/orders/:id/metadata", () => {
describe("successfully sets metadata on order", () => {
let subject
beforeAll(async () => {
subject = await request(
"POST",
`/admin/orders/${IdMap.getId("test-order")}/metadata`,
{
payload: {
key: "Test key",
value: "Test value",
},
adminSession: {
jwt: {
userId: IdMap.getId("admin_user"),
},
},
}
)
})
it("returns 200", () => {
expect(subject.status).toEqual(200)
})
it("calls OrderService setMetadata", () => {
expect(OrderServiceMock.setMetadata).toHaveBeenCalledTimes(1)
expect(OrderServiceMock.setMetadata).toHaveBeenCalledWith(
IdMap.getId("test-order"),
"Test key",
"Test value"
)
})
})
})

View File

@@ -0,0 +1,13 @@
export default async (req, res) => {
const { id, key } = req.params
try {
const orderService = req.scope.resolve("orderService")
let order = await orderService.deleteMetadata(id, key)
order = await orderService.decorate(order, [], ["region"])
res.status(200).json({ order })
} catch (err) {
throw err
}
}

View File

@@ -95,5 +95,21 @@ export default app => {
middlewares.wrap(require("./archive-order").default)
)
/**
* Set metadata key / value pair.
*/
route.post(
"/:id/metadata",
middlewares.wrap(require("./set-metadata").default)
)
/**
* Delete metadata key / value pair.
*/
route.delete(
"/:id/metadata/:key",
middlewares.wrap(require("./delete-metadata").default)
)
return app
}

View File

@@ -0,0 +1,25 @@
import { MedusaError, Validator } from "medusa-core-utils"
export default async (req, res) => {
const { id } = req.params
const schema = Validator.object().keys({
key: Validator.string().required(),
value: Validator.string().required(),
})
const { value, error } = schema.validate(req.body)
if (error) {
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
}
try {
const orderService = req.scope.resolve("orderService")
let order = await orderService.setMetadata(id, value.key, value.value)
order = await orderService.decorate(order, [], ["region"])
res.status(200).json({ order })
} catch (err) {
throw err
}
}

View File

@@ -0,0 +1,12 @@
export default async (req, res) => {
const { id, key } = req.params
try {
const regionService = req.scope.resolve("regionService")
const region = await regionService.deleteMetadata(id, key)
res.status(200).json({ region })
} catch (err) {
throw err
}
}

View File

@@ -52,5 +52,21 @@ export default app => {
middlewares.wrap(require("./remove-fulfillment-provider").default)
)
/**
* Set metadata key / value pair.
*/
route.post(
"/:id/metadata",
middlewares.wrap(require("./set-metadata").default)
)
/**
* Delete metadata key / value pair.
*/
route.delete(
"/:id/metadata/:key",
middlewares.wrap(require("./delete-metadata").default)
)
return app
}

View File

@@ -0,0 +1,24 @@
import { MedusaError, Validator } from "medusa-core-utils"
export default async (req, res) => {
const { id } = req.params
const schema = Validator.object().keys({
key: Validator.string().required(),
value: Validator.string().required(),
})
const { value, error } = schema.validate(req.body)
if (error) {
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
}
try {
const regionService = req.scope.resolve("regionService")
const region = await regionService.setMetadata(id, value.key, value.value)
res.status(200).json({ region })
} catch (err) {
throw err
}
}

View File

@@ -137,6 +137,18 @@ export const OrderServiceMock = {
}
return Promise.resolve(undefined)
}),
setMetadata: jest.fn().mockImplementation((id, key, value) => {
if (id === IdMap.getId("test-order")) {
return Promise.resolve(orders.testOrder)
}
return Promise.resolve(undefined)
}),
deleteMetadata: jest.fn().mockImplementation((id, key, value) => {
if (id === IdMap.getId("test-order")) {
return Promise.resolve(orders.testOrder)
}
return Promise.resolve(undefined)
}),
retrieve: jest.fn().mockImplementation(orderId => {
if (orderId === IdMap.getId("test-order")) {
return Promise.resolve(orders.testOrder)

View File

@@ -370,6 +370,57 @@ class RegionService extends BaseService {
const final = await this.runDecorators_(decorated)
return final
}
/**
* Dedicated method to set metadata for a region.
* To ensure that plugins does not overwrite each
* others metadata fields, setMetadata is provided.
* @param {string} regionId - the region to decorate.
* @param {string} key - key for metadata field
* @param {string} value - value for metadata field.
* @return {Promise} resolves to the updated result.
*/
async setMetadata(regionId, key, value) {
const validatedId = this.validateId_(regionId)
if (typeof key !== "string") {
throw new MedusaError(
MedusaError.Types.INVALID_ARGUMENT,
"Key type is invalid. Metadata keys must be strings"
)
}
const keyPath = `metadata.${key}`
return this.regionModel_
.updateOne({ _id: validatedId }, { $set: { [keyPath]: value } })
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
/**
* Dedicated method to delete metadata for an region.
* @param {string} regionId - the region to delete metadata from.
* @param {string} key - key for metadata field
* @return {Promise} resolves to the updated result.
*/
async deleteMetadata(regionId, key) {
const validatedId = this.validateId_(regionId)
if (typeof key !== "string") {
throw new MedusaError(
MedusaError.Types.INVALID_ARGUMENT,
"Key type is invalid. Metadata keys must be strings"
)
}
const keyPath = `metadata.${key}`
return this.regionModel_
.updateOne({ _id: validatedId }, { $unset: { [keyPath]: "" } })
.catch(err => {
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
})
}
}
export default RegionService