Feat:contentful plugin archive on delete
* extend plugin with methods for archival in contentful * add events to services * rename entities * eventbusservice to delete * Update packages/medusa-plugin-contentful/src/services/contentful.js Co-authored-by: Sebastian Rindom <skrindom@gmail.com> * Update packages/medusa-plugin-contentful/src/services/contentful.js Co-authored-by: Sebastian Rindom <skrindom@gmail.com> * Update packages/medusa-plugin-contentful/src/services/contentful.js Co-authored-by: Sebastian Rindom <skrindom@gmail.com> * testing * adjust options * Update packages/medusa-plugin-contentful/src/services/contentful.js Co-authored-by: Sebastian Rindom <skrindom@gmail.com> * adjust options * Update packages/medusa-plugin-contentful/src/services/contentful.js Co-authored-by: Sebastian Rindom <skrindom@gmail.com> * Update packages/medusa-plugin-contentful/src/services/contentful.js Co-authored-by: Sebastian Rindom <skrindom@gmail.com> Co-authored-by: Sebastian Rindom <skrindom@gmail.com>
This commit is contained in:
1 parent
62fda1043e
commit
ba2de6906a
9 files changed
+319
-4
No files matched your search
@@ -0,0 +1,10 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.ContentfulMock = void 0;
|
||||||
|
var ContentfulMock = {
|
||||||
|
createClient: jest.fn()
|
||||||
|
};
|
||||||
|
exports.ContentfulMock = ContentfulMock;
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export const createClient = jest.fn()
|
||||||
|
const mock = jest.fn().mockImplementation(() => {
|
||||||
|
return { createClient }
|
||||||
|
})
|
||||||
|
|
||||||
|
export default mock
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
import ContentfulService from "../contentful"
|
||||||
|
|
||||||
|
describe("ContentfulService", () => {
|
||||||
|
describe("delete in medusa", () => {
|
||||||
|
const regionService = {
|
||||||
|
retrieve: jest.fn((id) => {
|
||||||
|
if (id === "exists") {
|
||||||
|
return Promise.resolve({ id: "exists" })
|
||||||
|
}
|
||||||
|
return Promise.resolve(undefined)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
const productService = {
|
||||||
|
retrieve: jest.fn((id) => {
|
||||||
|
if (id === "exists") {
|
||||||
|
return Promise.resolve({ id: "exists" })
|
||||||
|
}
|
||||||
|
return Promise.resolve(undefined)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
const redisClient = {
|
||||||
|
get: async (id) => {
|
||||||
|
// const key = `${id}_ignore_${side}`
|
||||||
|
if (id === `ignored_ignore_contentful`) {
|
||||||
|
return { id }
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
},
|
||||||
|
set: async (id) => {
|
||||||
|
return undefined
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const productVariantService = {
|
||||||
|
retrieve: jest.fn((id) => {
|
||||||
|
if (id === "exists") {
|
||||||
|
return Promise.resolve({ id: "exists" })
|
||||||
|
}
|
||||||
|
return Promise.resolve(undefined)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
const eventBusService = {}
|
||||||
|
|
||||||
|
const service = new ContentfulService(
|
||||||
|
{
|
||||||
|
regionService,
|
||||||
|
productService,
|
||||||
|
redisClient,
|
||||||
|
productVariantService,
|
||||||
|
eventBusService,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
space_id: "test_id",
|
||||||
|
environment: "master",
|
||||||
|
access_token: "test_token",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const entry = {
|
||||||
|
unpublish: jest.fn(async () => {
|
||||||
|
return {
|
||||||
|
id: "id",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
archive: jest.fn(async () => {
|
||||||
|
return {
|
||||||
|
id: "id",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
service.contentful_ = {
|
||||||
|
getSpace: async (space_id) => {
|
||||||
|
return {
|
||||||
|
getEnvironment: async (env) => {
|
||||||
|
return {
|
||||||
|
getEntry: async (id) => {
|
||||||
|
if (id === "onlyMedusa") {
|
||||||
|
throw new Error("doesn't exist")
|
||||||
|
}
|
||||||
|
return entry
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("archiveProductInContentful", () => {
|
||||||
|
it("Calls entry.unpublish and entry.archive", async () => {
|
||||||
|
await service.archiveProductInContentful({ id: "test" })
|
||||||
|
|
||||||
|
expect(entry.unpublish).toHaveBeenCalledTimes(1)
|
||||||
|
expect(entry.archive).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Doesn't call entry.unpublish and entry.archive if the product still exists in medusa", async () => {
|
||||||
|
await service.archiveProductInContentful({ id: "exists" })
|
||||||
|
|
||||||
|
expect(entry.unpublish).toHaveBeenCalledTimes(0)
|
||||||
|
expect(entry.archive).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Doesn't call productService if request should be ignored", async () => {
|
||||||
|
await service.archiveProductInContentful({ id: "ignored" })
|
||||||
|
|
||||||
|
expect(productService.retrieve).toHaveBeenCalledTimes(0)
|
||||||
|
expect(entry.unpublish).toHaveBeenCalledTimes(0)
|
||||||
|
expect(entry.archive).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("archiveProductVariantInContentful", () => {
|
||||||
|
it("Calls entry.unpublish and entry.archive", async () => {
|
||||||
|
await service.archiveProductVariantInContentful({ id: "test" })
|
||||||
|
|
||||||
|
expect(entry.unpublish).toHaveBeenCalledTimes(1)
|
||||||
|
expect(entry.archive).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Doesn't call entry.unpublish and entry.archive if the variant still exists in medusa", async () => {
|
||||||
|
await service.archiveProductVariantInContentful({ id: "exists" })
|
||||||
|
|
||||||
|
expect(entry.unpublish).toHaveBeenCalledTimes(0)
|
||||||
|
expect(entry.archive).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Doesn't call productVariantService if request should be ignored", async () => {
|
||||||
|
await service.archiveProductVariantInContentful({ id: "ignored" })
|
||||||
|
|
||||||
|
expect(productVariantService.retrieve).toHaveBeenCalledTimes(0)
|
||||||
|
expect(entry.unpublish).toHaveBeenCalledTimes(0)
|
||||||
|
expect(entry.archive).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("archiveRegionInContentful", () => {
|
||||||
|
it("Calls entry.unpublish and entry.archive", async () => {
|
||||||
|
await service.archiveRegionInContentful({ id: "test" })
|
||||||
|
|
||||||
|
expect(entry.unpublish).toHaveBeenCalledTimes(1)
|
||||||
|
expect(entry.archive).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Doesn't call entry.unpublish and entry.archive if the region still exists in medusa", async () => {
|
||||||
|
await service.archiveRegionInContentful({ id: "exists" })
|
||||||
|
|
||||||
|
expect(entry.unpublish).toHaveBeenCalledTimes(0)
|
||||||
|
expect(entry.archive).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Doesn't call RegionService if request should be ignored", async () => {
|
||||||
|
await service.archiveRegionInContentful({ id: "ignored" })
|
||||||
|
|
||||||
|
expect(regionService.retrieve).toHaveBeenCalledTimes(0)
|
||||||
|
expect(entry.unpublish).toHaveBeenCalledTimes(0)
|
||||||
|
expect(entry.archive).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("archiveEntryWidthId", () => {
|
||||||
|
it("Calls archive if entry exists", async () => {
|
||||||
|
await service.archiveEntryWidthId("exists")
|
||||||
|
|
||||||
|
expect(entry.unpublish).toHaveBeenCalledTimes(1)
|
||||||
|
expect(entry.archive).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
it("Doesnt call archive if entry doesn't exists", async () => {
|
||||||
|
await service.archiveEntryWidthId("onlyMedusa")
|
||||||
|
|
||||||
|
expect(entry.unpublish).toHaveBeenCalledTimes(0)
|
||||||
|
expect(entry.archive).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -91,7 +91,7 @@ class ContentfulService extends BaseService {
|
|||||||
async createImageAssets(product) {
|
async createImageAssets(product) {
|
||||||
const environment = await this.getContentfulEnvironment_()
|
const environment = await this.getContentfulEnvironment_()
|
||||||
|
|
||||||
let assets = []
|
const assets = []
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
product.images
|
product.images
|
||||||
.filter((image) => image.url !== product.thumbnail)
|
.filter((image) => image.url !== product.thumbnail)
|
||||||
@@ -646,6 +646,92 @@ class ContentfulService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async archiveProductVariantInContentful(variant) {
|
||||||
|
let variantEntity
|
||||||
|
try {
|
||||||
|
const ignore = await this.shouldIgnore_(variant.id, "contentful")
|
||||||
|
if (ignore) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
variantEntity = await this.productVariantService_.retrieve(variant.id)
|
||||||
|
} catch (err) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
if (variantEntity) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.archiveEntryWidthId(variant.id)
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async archiveProductInContentful(product) {
|
||||||
|
let productEntity
|
||||||
|
try {
|
||||||
|
const ignore = await this.shouldIgnore_(product.id, "contentful")
|
||||||
|
if (ignore) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
productEntity = await this.productService_.retrieve(product.id)
|
||||||
|
} catch (err) {}
|
||||||
|
|
||||||
|
if (productEntity) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.archiveEntryWidthId(product.id)
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async archiveRegionInContentful(region) {
|
||||||
|
let regionEntity
|
||||||
|
try {
|
||||||
|
const ignore = await this.shouldIgnore_(region.id, "contentful")
|
||||||
|
if (ignore) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
regionEntity = await this.regionService_.retrieve(region.id)
|
||||||
|
} catch (err) {}
|
||||||
|
|
||||||
|
if (regionEntity) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.archiveEntryWidthId(region.id)
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async archiveEntryWidthId(id) {
|
||||||
|
const environment = await this.getContentfulEnvironment_()
|
||||||
|
// check if product exists
|
||||||
|
let entry = undefined
|
||||||
|
try {
|
||||||
|
entry = await environment.getEntry(id)
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
const unpublishEntry = await entry.unpublish()
|
||||||
|
const archivedEntry = await entry.archive()
|
||||||
|
|
||||||
|
await this.addIgnore_(id, "medusa")
|
||||||
|
|
||||||
|
return archivedEntry
|
||||||
|
}
|
||||||
|
|
||||||
async sendContentfulProductToAdmin(productId) {
|
async sendContentfulProductToAdmin(productId) {
|
||||||
const ignore = await this.shouldIgnore_(productId, "medusa")
|
const ignore = await this.shouldIgnore_(productId, "medusa")
|
||||||
if (ignore) {
|
if (ignore) {
|
||||||
@@ -658,7 +744,7 @@ class ContentfulService extends BaseService {
|
|||||||
|
|
||||||
const product = await this.productService_.retrieve(productId)
|
const product = await this.productService_.retrieve(productId)
|
||||||
|
|
||||||
let update = {}
|
const update = {}
|
||||||
|
|
||||||
const title =
|
const title =
|
||||||
productEntry.fields[this.getCustomField("title", "product")]["en-US"]
|
productEntry.fields[this.getCustomField("title", "product")]["en-US"]
|
||||||
@@ -741,9 +827,9 @@ class ContentfulService extends BaseService {
|
|||||||
isArray = false
|
isArray = false
|
||||||
}
|
}
|
||||||
|
|
||||||
let output = []
|
const output = []
|
||||||
for (const obj of input) {
|
for (const obj of input) {
|
||||||
let transformed = Object.assign({}, obj)
|
const transformed = Object.assign({}, obj)
|
||||||
transformed.medusaId = obj.id
|
transformed.medusaId = obj.id
|
||||||
output.push(transformed)
|
output.push(transformed)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,18 @@ class ContentfulSubscriber {
|
|||||||
await this.contentfulService_.updateRegionInContentful(data)
|
await this.contentfulService_.updateRegionInContentful(data)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.eventBus_.subscribe("region.deleted", async (data) => {
|
||||||
|
await this.contentfulService_.updateRegionInContentful(data)
|
||||||
|
})
|
||||||
|
|
||||||
this.eventBus_.subscribe("product-variant.updated", async (data) => {
|
this.eventBus_.subscribe("product-variant.updated", async (data) => {
|
||||||
await this.contentfulService_.updateProductVariantInContentful(data)
|
await this.contentfulService_.updateProductVariantInContentful(data)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.eventBus_.subscribe("product-variant.deleted", async (data) => {
|
||||||
|
await this.contentfulService_.archiveProductVariantInContentful(data)
|
||||||
|
})
|
||||||
|
|
||||||
this.eventBus_.subscribe("product.updated", async (data) => {
|
this.eventBus_.subscribe("product.updated", async (data) => {
|
||||||
await this.contentfulService_.updateProductInContentful(data)
|
await this.contentfulService_.updateProductInContentful(data)
|
||||||
})
|
})
|
||||||
@@ -29,6 +37,10 @@ class ContentfulSubscriber {
|
|||||||
this.eventBus_.subscribe("product.created", async (data) => {
|
this.eventBus_.subscribe("product.created", async (data) => {
|
||||||
await this.contentfulService_.createProductInContentful(data)
|
await this.contentfulService_.createProductInContentful(data)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.eventBus_.subscribe("product.deleted", async (data) => {
|
||||||
|
await this.contentfulService_.archiveProductInContentful(data)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -415,6 +415,7 @@ describe("ProductService", () => {
|
|||||||
|
|
||||||
const productService = new ProductService({
|
const productService = new ProductService({
|
||||||
manager: MockManager,
|
manager: MockManager,
|
||||||
|
eventBusService,
|
||||||
productRepository,
|
productRepository,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class ProductVariantService extends BaseService {
|
|||||||
static Events = {
|
static Events = {
|
||||||
UPDATED: "product-variant.updated",
|
UPDATED: "product-variant.updated",
|
||||||
CREATED: "product-variant.created",
|
CREATED: "product-variant.created",
|
||||||
|
DELETED: "product-variant.deleted",
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param { productVariantModel: (ProductVariantModel) } */
|
/** @param { productVariantModel: (ProductVariantModel) } */
|
||||||
@@ -588,6 +589,12 @@ class ProductVariantService extends BaseService {
|
|||||||
|
|
||||||
await variantRepo.softRemove(variant)
|
await variantRepo.softRemove(variant)
|
||||||
|
|
||||||
|
await this.eventBus_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.emit(ProductVariantService.Events.DELETED, {
|
||||||
|
id: variantId,
|
||||||
|
})
|
||||||
|
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class ProductService extends BaseService {
|
|||||||
static Events = {
|
static Events = {
|
||||||
UPDATED: "product.updated",
|
UPDATED: "product.updated",
|
||||||
CREATED: "product.created",
|
CREATED: "product.created",
|
||||||
|
DELETED: "product.deleted",
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
@@ -475,6 +476,12 @@ class ProductService extends BaseService {
|
|||||||
|
|
||||||
await productRepo.softRemove(product)
|
await productRepo.softRemove(product)
|
||||||
|
|
||||||
|
await this.eventBus_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.emit(ProductService.Events.DELETED, {
|
||||||
|
id: productId,
|
||||||
|
})
|
||||||
|
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ class RegionService extends BaseService {
|
|||||||
static Events = {
|
static Events = {
|
||||||
UPDATED: "region.updated",
|
UPDATED: "region.updated",
|
||||||
CREATED: "region.created",
|
CREATED: "region.created",
|
||||||
|
DELETED: "region.deleted",
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
@@ -389,6 +390,12 @@ class RegionService extends BaseService {
|
|||||||
|
|
||||||
await regionRepo.softRemove(region)
|
await regionRepo.softRemove(region)
|
||||||
|
|
||||||
|
await this.eventBus_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.emit(RegionService.Events.DELETED, {
|
||||||
|
id: regionId,
|
||||||
|
})
|
||||||
|
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user