297 lines
7.8 KiB
JavaScript
297 lines
7.8 KiB
JavaScript
import _ from "lodash"
|
|
import { BaseService } from "medusa-interfaces"
|
|
import { createClient } from "contentful-management"
|
|
import redis from "redis"
|
|
|
|
class ContentfulService extends BaseService {
|
|
constructor(
|
|
{ productService, productVariantService, eventBusService },
|
|
options
|
|
) {
|
|
super()
|
|
|
|
this.productService_ = productService
|
|
|
|
this.productVariantService_ = productVariantService
|
|
|
|
this.eventBus_ = eventBusService
|
|
|
|
this.options_ = options
|
|
|
|
this.contentful_ = createClient({
|
|
accessToken: options.access_token,
|
|
})
|
|
|
|
this.redis_ = redis.createClient()
|
|
}
|
|
|
|
async getIgnoreIds_(type) {
|
|
return new Promise((resolve, reject) => {
|
|
this.redis_.get(`${type}_ignore_ids`, (err, reply) => {
|
|
if (err) {
|
|
return reject(err)
|
|
}
|
|
|
|
return resolve(JSON.parse(reply))
|
|
})
|
|
})
|
|
}
|
|
|
|
async getContentfulEnvironment_() {
|
|
try {
|
|
const space = await this.contentful_.getSpace(this.options_.space_id)
|
|
const environment = await space.getEnvironment(this.options_.environment)
|
|
return environment
|
|
} catch (error) {
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async getVariantEntries_(productId) {
|
|
try {
|
|
const productVariants = await this.productService_.retrieveVariants(
|
|
productId
|
|
)
|
|
|
|
const contentfulVariants = await Promise.all(
|
|
productVariants.map((variant) =>
|
|
this.updateProductVariantInContentful(variant)
|
|
)
|
|
)
|
|
|
|
return contentfulVariants
|
|
} catch (error) {
|
|
console.log(error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
getVariantLinks_(variantEntries) {
|
|
return variantEntries.map((v) => ({
|
|
sys: {
|
|
type: "Link",
|
|
linkType: "Entry",
|
|
id: v.sys.id,
|
|
},
|
|
}))
|
|
}
|
|
|
|
async createProductInContentful(product) {
|
|
try {
|
|
const environment = await this.getContentfulEnvironment_()
|
|
const variantEntries = await this.getVariantEntries_(product._id)
|
|
const variantLinks = this.getVariantLinks_(variantEntries)
|
|
const result = await environment.createEntryWithId(
|
|
"product",
|
|
product._id,
|
|
{
|
|
fields: {
|
|
title: {
|
|
"en-US": product.title,
|
|
},
|
|
variants: {
|
|
"en-US": variantLinks,
|
|
},
|
|
objectId: {
|
|
"en-US": product._id,
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
const ignoreIds = (await this.getIgnoreIds_("product")) || []
|
|
ignoreIds.push(product._id)
|
|
this.redis_.set("product_ignore_ids", JSON.stringify(ignoreIds))
|
|
return result
|
|
} catch (error) {
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async createProductVariantInContentful(variant) {
|
|
try {
|
|
const environment = await this.getContentfulEnvironment_()
|
|
const result = await environment.createEntryWithId(
|
|
"productVariant",
|
|
variant._id,
|
|
{
|
|
fields: {
|
|
title: {
|
|
"en-US": variant.title,
|
|
},
|
|
sku: {
|
|
"en-US": variant.sku,
|
|
},
|
|
prices: {
|
|
"en-US": variant.prices,
|
|
},
|
|
objectId: {
|
|
"en-US": variant._id,
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
const ignoreIds = (await this.getIgnoreIds_("product_variant")) || []
|
|
ignoreIds.push(variant._id)
|
|
this.redis_.set("product_variant_ignore_ids", JSON.stringify(ignoreIds))
|
|
return result
|
|
} catch (error) {
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async updateProductInContentful(product) {
|
|
try {
|
|
const ignoreIds = (await this.getIgnoreIds_("product")) || []
|
|
|
|
if (ignoreIds.includes(product._id)) {
|
|
const newIgnoreIds = ignoreIds.filter((id) => id !== product._id)
|
|
this.redis_.set("product_ignore_ids", JSON.stringify(newIgnoreIds))
|
|
return
|
|
} else {
|
|
ignoreIds.push(product._id)
|
|
this.redis_.set("product_ignore_ids", JSON.stringify(ignoreIds))
|
|
}
|
|
|
|
const environment = await this.getContentfulEnvironment_()
|
|
// check if product exists
|
|
let productEntry = undefined
|
|
try {
|
|
productEntry = await environment.getEntry(product._id)
|
|
} catch (error) {
|
|
return this.createProductInContentful(product)
|
|
}
|
|
|
|
const variantEntries = await this.getVariantEntries_(product.variants)
|
|
const variantLinks = this.getVariantLinks_(variantEntries)
|
|
productEntry.fields = _.assignIn(productEntry.fields, {
|
|
title: {
|
|
"en-US": product.title,
|
|
},
|
|
variants: {
|
|
"en-US": variantLinks,
|
|
},
|
|
objectId: {
|
|
"en-US": product._id,
|
|
},
|
|
})
|
|
|
|
const updatedEntry = await productEntry.update()
|
|
const publishedEntry = await updatedEntry.publish()
|
|
|
|
return publishedEntry
|
|
} catch (error) {
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async updateProductVariantInContentful(variant) {
|
|
try {
|
|
const ignoreIds = (await this.getIgnoreIds_("product_variant")) || []
|
|
|
|
if (ignoreIds.includes(variant._id)) {
|
|
const newIgnoreIds = ignoreIds.filter((id) => id !== variant._id)
|
|
this.redis_.set(
|
|
"product_variant_ignore_ids",
|
|
JSON.stringify(newIgnoreIds)
|
|
)
|
|
return
|
|
} else {
|
|
ignoreIds.push(variant._id)
|
|
this.redis_.set("product_variant_ignore_ids", JSON.stringify(ignoreIds))
|
|
}
|
|
|
|
const environment = await this.getContentfulEnvironment_()
|
|
// check if product exists
|
|
let variantEntry = undefined
|
|
// if not, we create a new one
|
|
try {
|
|
variantEntry = await environment.getEntry(variant._id)
|
|
} catch (error) {
|
|
return this.createProductVariantInContentful(variant)
|
|
}
|
|
|
|
variantEntry.fields = _.assignIn(variantEntry.fields, {
|
|
title: {
|
|
"en-US": variant.title,
|
|
},
|
|
sku: {
|
|
"en-US": variant.sku,
|
|
},
|
|
prices: {
|
|
"en-US": variant.prices,
|
|
},
|
|
objectId: {
|
|
"en-US": variant._id,
|
|
},
|
|
})
|
|
|
|
const updatedEntry = await variantEntry.update()
|
|
const publishedEntry = await updatedEntry.publish()
|
|
|
|
return publishedEntry
|
|
} catch (error) {
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async sendContentfulProductToAdmin(productId) {
|
|
try {
|
|
const environment = await this.getContentfulEnvironment_()
|
|
const productEntry = await environment.getEntry(productId)
|
|
|
|
const ignoreIds = (await this.getIgnoreIds_("product")) || []
|
|
if (ignoreIds.includes(productId)) {
|
|
const newIgnoreIds = ignoreIds.filter((id) => id !== productId)
|
|
this.redis_.set("product_ignore_ids", JSON.stringify(newIgnoreIds))
|
|
return
|
|
} else {
|
|
ignoreIds.push(productId)
|
|
this.redis_.set("product_ignore_ids", JSON.stringify(ignoreIds))
|
|
}
|
|
|
|
const updatedProduct = await this.productService_.update(productId, {
|
|
title: productEntry.fields.title["en-US"],
|
|
})
|
|
|
|
return updatedProduct
|
|
} catch (error) {
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async sendContentfulProductVariantToAdmin(variantId) {
|
|
try {
|
|
const environment = await this.getContentfulEnvironment_()
|
|
const variantEntry = await environment.getEntry(variantId)
|
|
|
|
const ignoreIds = (await this.getIgnoreIds_("product_variant")) || []
|
|
if (ignoreIds.includes(variantId)) {
|
|
const newIgnoreIds = ignoreIds.filter((id) => id !== variantId)
|
|
this.redis_.set(
|
|
"product_variant_ignore_ids",
|
|
JSON.stringify(newIgnoreIds)
|
|
)
|
|
return
|
|
} else {
|
|
ignoreIds.push(variantId)
|
|
this.redis_.set("product_variant_ignore_ids", JSON.stringify(ignoreIds))
|
|
}
|
|
|
|
const updatedVariant = await this.productVariantService_.update(
|
|
variantId,
|
|
{
|
|
title: variantEntry.fields.title["en-US"],
|
|
}
|
|
)
|
|
|
|
return updatedVariant
|
|
} catch (error) {
|
|
throw error
|
|
}
|
|
}
|
|
}
|
|
|
|
export default ContentfulService
|