add: medusa-plugin-meilisearch + add deleted event in productService + tweak emitted event data in productVariantService

This commit is contained in:
zakariaelas committed 2021-09-09 17:56:10 +01:00
1 parent 4602cfc083
commit c56f37415d
24 files changed
+14041 -3

No files matched your search

@@ -0,0 +1,10 @@
import { Router } from "express"
import routes from "./routes/"
export default (container) => {
const app = Router()
routes(app)
return app
}
@@ -0,0 +1 @@
export default (fn) => (...args) => fn(...args).catch(args[2])
@@ -0,0 +1,5 @@
import { default as wrap } from "./await-middleware"
export default {
wrap,
}
@@ -0,0 +1,17 @@
import { Router } from "express"
import bodyParser from "body-parser"
import middlewares from "../middlewares"
const route = Router()
export default (app) => {
app.use("/meilisearch", route)
route.post(
"/search",
bodyParser.json(),
middlewares.wrap(require("./meilisearch").default)
)
return app
}
@@ -0,0 +1,27 @@
import { Validator, MedusaError } from "medusa-core-utils"
export default async (req, res) => {
const schema = Validator.object()
.keys({
q: Validator.string().required(),
})
.options({ allowUnknown: true })
const { value, error } = schema.validate(req.body)
if (error) {
console.log({ error })
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
}
try {
const { q, ...options } = value
const meiliSearchService = req.scope.resolve("meilisearchService")
const results = await meiliSearchService.search(q, options)
res.status(200).send(results)
} catch (error) {
throw error
}
}
@@ -0,0 +1,26 @@
import {
defaultProductFields,
defaultProductRelations,
flattenSkus,
} from "../utils"
export default async (container, options) => {
try {
const meilisearchService = container.resolve("meilisearchService")
const productService = container.resolve("productService")
const products = await productService.list(
{},
{
select: defaultProductFields,
relations: defaultProductRelations,
}
)
const productsWithSkus = products.map((product) => flattenSkus(product))
await meilisearchService.updateSettings()
await meilisearchService.addDocuments(productsWithSkus)
} catch (err) {
console.log(err)
}
}
@@ -0,0 +1,36 @@
import { BaseService } from "medusa-interfaces"
import { MeiliSearch } from "meilisearch"
class MeilisearchService extends BaseService {
constructor({ eventBusService }, options) {
super()
this.eventBus_ = eventBusService
this.options_ = options
this.client_ = new MeiliSearch(options.config).index("products")
}
deleteAllDocuments() {
return this.client_.deleteAllDocuments()
}
addDocuments(documents) {
return this.client_.addDocuments(documents)
}
deleteDocument(document_id) {
return this.client_.deleteDocument(document_id)
}
search(query, options) {
return this.client_.search(query, options)
}
updateSettings() {
return this.client_.updateSettings(this.options_.settings)
}
}
export default MeilisearchService
@@ -0,0 +1,71 @@
import {
defaultProductRelations,
defaultProductFields,
flattenSkus,
} from "../utils"
class MeilisearchSubscriber {
constructor(
{ eventBusService, meilisearchService, productService },
options
) {
this.eventBus_ = eventBusService
this.meilisearchService_ = meilisearchService
this.productService_ = productService
this.eventBus_.subscribe("product.created", this.handleProductCreation)
this.eventBus_.subscribe("product.updated", this.handleProductUpdate)
this.eventBus_.subscribe("product.deleted", this.handleProductDeletion)
this.eventBus_.subscribe(
"product-variant.created",
this.handleProductVariantChange
)
this.eventBus_.subscribe(
"product-variant.updated",
this.handleProductVariantChange
)
this.eventBus_.subscribe(
"product-variant.deleted",
this.handleProductVariantChange
)
}
handleProductCreation = async (data) => {
const product = await this.retrieveProduct_(data.id)
await this.meilisearchService_.addDocuments([product])
}
retrieveProduct_ = async (product_id) => {
const product = await this.productService_.retrieve(product_id, {
relations: defaultProductRelations,
select: defaultProductFields,
})
const flattenedProduct = flattenSkus(product)
return flattenedProduct
}
handleProductUpdate = async (data) => {
const product = await this.retrieveProduct_(data.id)
await this.meilisearchService_.addDocuments([product])
}
handleProductDeletion = async (data) => {
await this.meilisearchService_.deleteDocument(data.id)
}
handleProductVariantChange = async (data) => {
console.log({ change: data })
const product = await this.retrieveProduct_(data.product_id)
console.log(product.variants)
await this.meilisearchService_.addDocuments([product])
}
}
export default MeilisearchSubscriber
@@ -0,0 +1,29 @@
export const flattenSkus = (product) => {
const skus = product.variants.map((v) => v.sku).filter(Boolean)
product.sku = skus
return product
}
export const defaultProductFields = [
"id",
"title",
"subtitle",
"description",
"handle",
"is_giftcard",
"discountable",
"thumbnail",
"profile_id",
"collection_id",
"type_id",
"origin_country",
"created_at",
"updated_at",
]
export const defaultProductRelations = [
"variants",
"tags",
"type",
"collection",
]