feat(medusa): cart context (#201)

- Adds a context field to Cart
- context is automatically populated with ip + user agent
- context can be updated via POST /store/cart/:id or set when creating via POST /store/cart
This commit is contained in:
Sebastian Rindom
2021-03-12 11:48:51 +01:00
committed by GitHub
parent a031f1f338
commit dd7b306333
20 changed files with 3499 additions and 657 deletions
+1 -2
View File
@@ -44,7 +44,7 @@
},
"peerDependencies": {
"medusa-interfaces": "1.x",
"mongoose": "5.x"
"typeorm": "0.2.x"
},
"dependencies": {
"@babel/plugin-transform-classes": "^7.9.5",
@@ -82,7 +82,6 @@
"request-ip": "^2.1.3",
"resolve-cwd": "^3.0.0",
"scrypt-kdf": "^2.0.1",
"typeorm": "^0.2.29",
"ulid": "^2.3.0",
"uuid": "^8.3.1",
"winston": "^3.2.1"
@@ -11,6 +11,9 @@ describe("POST /store/carts", () => {
subject = await request("POST", `/store/carts`, {
payload: {
region_id: IdMap.getId("testRegion"),
context: {
clientId: "test",
},
},
})
})
@@ -23,6 +26,11 @@ describe("POST /store/carts", () => {
expect(CartServiceMock.create).toHaveBeenCalledTimes(1)
expect(CartServiceMock.create).toHaveBeenCalledWith({
region_id: IdMap.getId("testRegion"),
context: {
ip: "::ffff:127.0.0.1",
user_agent: "node-superagent/3.8.3",
clientId: "test",
},
})
})
@@ -1,3 +1,4 @@
import reqIp from "request-ip"
import { Validator, MedusaError } from "medusa-core-utils"
import { defaultFields, defaultRelations } from "./"
@@ -31,6 +32,9 @@ import { defaultFields, defaultRelations } from "./"
* quantity:
* description: The quantity of the Product Variant to add
* type: integer
* context:
* description: "An optional object to provide context to the Cart. The `context` field is automatically populated with `ip` and `user_agent`"
* type: object
* tags:
* - Cart
* responses:
@@ -53,6 +57,7 @@ export default async (req, res) => {
quantity: Validator.number().required(),
})
.optional(),
context: Validator.object().optional(),
})
const { value, error } = schema.validate(req.body)
@@ -60,6 +65,11 @@ export default async (req, res) => {
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
}
const reqContext = {
ip: reqIp.getClientIp(req),
user_agent: req.get("user-agent"),
}
try {
const lineItemService = req.scope.resolve("lineItemService")
const cartService = req.scope.resolve("cartService")
@@ -77,6 +87,10 @@ export default async (req, res) => {
const toCreate = {
region_id: regionId,
context: {
...reqContext,
...value.context,
},
}
if (req.user && req.user.customer_id) {
@@ -51,6 +51,9 @@ import { defaultFields, defaultRelations } from "./"
* customer_id:
* description: "The id of the Customer to associate the Cart with."
* type: string
* context:
* description: "An optional object to provide context to the Cart."
* type: object
* tags:
* - Cart
* responses:
@@ -85,6 +88,7 @@ export default async (req, res) => {
})
.optional(),
customer_id: Validator.string().optional(),
context: Validator.object().optional(),
})
const { value, error } = schema.validate(req.body)
@@ -0,0 +1,13 @@
import { MigrationInterface, QueryRunner } from "typeorm"
export class cartContext1614684597235 implements MigrationInterface {
name = "cartContext1614684597235"
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "cart" ADD "context" jsonb`)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "cart" DROP COLUMN "context"`)
}
}
+3
View File
@@ -243,6 +243,9 @@ export class Cart {
@Column({ nullable: true })
idempotency_key: string
@Column({ type: "jsonb", nullable: true })
context: any
// Total fields
shipping_total: number
discount_total: number
+8
View File
@@ -641,6 +641,14 @@ class CartService extends BaseService {
}
}
if ("context" in update) {
const prevContext = cart.context || {}
cart.context = {
...prevContext,
...update.context,
}
}
const result = await cartRepo.save(cart)
if ("email" in update || "customer_id" in update) {