From 1b81105ff6218fe8d705db51fc5483fed908fc2b Mon Sep 17 00:00:00 2001 From: Gustavo Garcia Date: Tue, 11 Nov 2025 10:46:02 -0300 Subject: [PATCH] feat: add sellers to Algolia --- .../src/types/algolia/algolia-seller.ts | 11 +++++ .../framework/src/types/algolia/events.ts | 3 +- .../src/types/algolia/index-types.ts | 3 +- packages/framework/src/types/algolia/index.ts | 1 + packages/framework/src/types/seller/events.ts | 4 +- .../algolia/src/api/admin/algolia/route.ts | 3 +- .../subscribers/algolia-sellers-changed.ts | 34 +++++++++++++ .../src/subscribers/utils/algolia-sellers.ts | 49 +++++++++++++++++++ .../algolia/src/subscribers/utils/index.ts | 1 + .../src/subscribers/algolia-seller-created.ts | 21 ++++++++ .../src/subscribers/algolia-seller-updated.ts | 21 ++++++++ .../seller/workflows/create-seller.ts | 12 ++++- .../seller/workflows/update-seller.ts | 25 ++++++++-- 13 files changed, 179 insertions(+), 9 deletions(-) create mode 100644 packages/framework/src/types/algolia/algolia-seller.ts create mode 100644 packages/modules/algolia/src/subscribers/algolia-sellers-changed.ts create mode 100644 packages/modules/algolia/src/subscribers/utils/algolia-sellers.ts create mode 100644 packages/modules/b2c-core/src/subscribers/algolia-seller-created.ts create mode 100644 packages/modules/b2c-core/src/subscribers/algolia-seller-updated.ts diff --git a/packages/framework/src/types/algolia/algolia-seller.ts b/packages/framework/src/types/algolia/algolia-seller.ts new file mode 100644 index 000000000..2a6642f97 --- /dev/null +++ b/packages/framework/src/types/algolia/algolia-seller.ts @@ -0,0 +1,11 @@ +import { z } from 'zod' + +export type AlgoliaSeller = z.infer +export const AlgoliaSellerValidator = z.object({ + id: z.string(), + store_status: z.string(), + name: z.string(), + handle: z.string(), + description: z.string().nullable(), + photo: z.string().nullable() +}) diff --git a/packages/framework/src/types/algolia/events.ts b/packages/framework/src/types/algolia/events.ts index 0c67cf339..5b5dedb81 100644 --- a/packages/framework/src/types/algolia/events.ts +++ b/packages/framework/src/types/algolia/events.ts @@ -1,7 +1,8 @@ export enum AlgoliaEvents { PRODUCTS_CHANGED = 'algolia.products.changed', PRODUCTS_DELETED = 'algolia.products.deleted', - REVIEW_CHANGED = 'algolia.reviews.changed' + REVIEW_CHANGED = 'algolia.reviews.changed', + SELLERS_CHANGED = 'algolia.sellers.changed' } export enum IntermediateEvents { diff --git a/packages/framework/src/types/algolia/index-types.ts b/packages/framework/src/types/algolia/index-types.ts index 2259e10e5..0b16bbb5f 100644 --- a/packages/framework/src/types/algolia/index-types.ts +++ b/packages/framework/src/types/algolia/index-types.ts @@ -1,4 +1,5 @@ export enum IndexType { PRODUCT = 'products', - REVIEW = 'reviews' + REVIEW = 'reviews', + SELLER = 'sellers' } diff --git a/packages/framework/src/types/algolia/index.ts b/packages/framework/src/types/algolia/index.ts index e09cf05b3..dc7e39a94 100644 --- a/packages/framework/src/types/algolia/index.ts +++ b/packages/framework/src/types/algolia/index.ts @@ -2,4 +2,5 @@ export * from './index-types' export * from './algolia-entity' export * from './algolia-product' export * from './algolia-review' +export * from './algolia-seller' export * from './events' diff --git a/packages/framework/src/types/seller/events.ts b/packages/framework/src/types/seller/events.ts index 710d2081b..7c7967d2f 100644 --- a/packages/framework/src/types/seller/events.ts +++ b/packages/framework/src/types/seller/events.ts @@ -1,3 +1,5 @@ export enum SellerEvents { - STORE_STATUS_CHANGED = 'seller.store_status_changed' + STORE_STATUS_CHANGED = 'seller.store_status_changed', + SELLER_CREATED = 'seller.created', + SELLER_UPDATED = 'seller.updated' } diff --git a/packages/modules/algolia/src/api/admin/algolia/route.ts b/packages/modules/algolia/src/api/admin/algolia/route.ts index 8eac439f1..58c07052f 100644 --- a/packages/modules/algolia/src/api/admin/algolia/route.ts +++ b/packages/modules/algolia/src/api/admin/algolia/route.ts @@ -77,5 +77,6 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => { const appId = algoliaService.getAppId(); const productIndex = await algoliaService.checkIndex(IndexType.PRODUCT); - res.status(200).json({ appId, productIndex }); + const sellerIndex = await algoliaService.checkIndex(IndexType.SELLER); + res.status(200).json({ appId, productIndex, sellerIndex }); }; diff --git a/packages/modules/algolia/src/subscribers/algolia-sellers-changed.ts b/packages/modules/algolia/src/subscribers/algolia-sellers-changed.ts new file mode 100644 index 000000000..3f50a5762 --- /dev/null +++ b/packages/modules/algolia/src/subscribers/algolia-sellers-changed.ts @@ -0,0 +1,34 @@ +import { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"; + +import { ALGOLIA_MODULE, AlgoliaModuleService } from "../modules/algolia"; +import { AlgoliaEvents, IndexType } from "@mercurjs/framework"; + +import { + filterSellersByStatus, + findAndTransformAlgoliaSellers, +} from "./utils"; + +export default async function algoliaSellersChangedHandler({ + event, + container, +}: SubscriberArgs<{ ids: string[] }>) { + const algolia = container.resolve(ALGOLIA_MODULE); + + const { actives, other } = await filterSellersByStatus( + container, + event.data.ids + ); + + const sellersToInsert = actives.length + ? await findAndTransformAlgoliaSellers(container, actives) + : []; + + await algolia.batch(IndexType.SELLER, sellersToInsert, other); +} + +export const config: SubscriberConfig = { + event: AlgoliaEvents.SELLERS_CHANGED, + context: { + subscriberId: "algolia-sellers-changed-handler", + }, +}; diff --git a/packages/modules/algolia/src/subscribers/utils/algolia-sellers.ts b/packages/modules/algolia/src/subscribers/utils/algolia-sellers.ts new file mode 100644 index 000000000..e05f03fd9 --- /dev/null +++ b/packages/modules/algolia/src/subscribers/utils/algolia-sellers.ts @@ -0,0 +1,49 @@ +import { z } from 'zod' + +import { MedusaContainer } from "@medusajs/framework"; + +import { + ContainerRegistrationKeys, + arrayDifference, +} from "@medusajs/framework/utils"; + +import { AlgoliaSellerValidator, StoreStatus } from '@mercurjs/framework' + +export async function filterSellersByStatus( + container: MedusaContainer, + ids: string[] = [] +) { + const query = container.resolve(ContainerRegistrationKeys.QUERY); + + const { data: sellers } = await query.graph({ + entity: "seller", + fields: ["id", "store_status"], + filters: { + id: ids, + }, + }); + + const actives = sellers.filter((s) => s.store_status === StoreStatus.ACTIVE); + const other = arrayDifference(sellers, actives); + + return { + actives: sellers.map((p) => p.id), + other: other.map((p) => p.id), + }; +} + +export async function findAndTransformAlgoliaSellers( + container: MedusaContainer, + ids: string[] = [] +) { + const query = container.resolve(ContainerRegistrationKeys.QUERY) + const { data: sellers } = await query.graph({ + entity: 'seller', + fields: ['id', 'name', 'handle', 'description', 'photo'], + filters: { + id: ids + } + }) + + return z.array(AlgoliaSellerValidator).parse(sellers) +} diff --git a/packages/modules/algolia/src/subscribers/utils/index.ts b/packages/modules/algolia/src/subscribers/utils/index.ts index 3114904f2..00cb996d3 100644 --- a/packages/modules/algolia/src/subscribers/utils/index.ts +++ b/packages/modules/algolia/src/subscribers/utils/index.ts @@ -1,2 +1,3 @@ export * from './algolia-product' export * from './algolia-reviews' +export * from './algolia-sellers' diff --git a/packages/modules/b2c-core/src/subscribers/algolia-seller-created.ts b/packages/modules/b2c-core/src/subscribers/algolia-seller-created.ts new file mode 100644 index 000000000..138abaeb6 --- /dev/null +++ b/packages/modules/b2c-core/src/subscribers/algolia-seller-created.ts @@ -0,0 +1,21 @@ +import { SubscriberArgs, SubscriberConfig } from '@medusajs/framework' +import { AlgoliaEvents, Modules, SellerEvents } from '@mercurjs/framework' + +export default async function sellerCreatedHandler({ + event, + container +}: SubscriberArgs<{ ids: string[] }>) { + const eventBus = container.resolve(Modules.EVENT_BUS) + + await eventBus.emit({ + name: AlgoliaEvents.SELLERS_CHANGED, + data: { ids: event.data.ids } + }) +} + +export const config: SubscriberConfig = { + event: SellerEvents.SELLER_CREATED, + context: { + subscriberId: 'seller-created-handler' + } +} \ No newline at end of file diff --git a/packages/modules/b2c-core/src/subscribers/algolia-seller-updated.ts b/packages/modules/b2c-core/src/subscribers/algolia-seller-updated.ts new file mode 100644 index 000000000..7169acd01 --- /dev/null +++ b/packages/modules/b2c-core/src/subscribers/algolia-seller-updated.ts @@ -0,0 +1,21 @@ +import { SubscriberArgs, SubscriberConfig } from '@medusajs/framework' +import { AlgoliaEvents, Modules, SellerEvents } from '@mercurjs/framework' + +export default async function sellerUpdatedHandler({ + event, + container +}: SubscriberArgs<{ ids: string[] }>) { + const eventBus = container.resolve(Modules.EVENT_BUS) + + await eventBus.emit({ + name: AlgoliaEvents.SELLERS_CHANGED, + data: { ids: event.data.ids } + }) +} + +export const config: SubscriberConfig = { + event: SellerEvents.SELLER_UPDATED, + context: { + subscriberId: 'seller-updated-handler' + } +} \ No newline at end of file diff --git a/packages/modules/b2c-core/src/workflows/seller/workflows/create-seller.ts b/packages/modules/b2c-core/src/workflows/seller/workflows/create-seller.ts index 3fca0a222..d4ef79cdb 100644 --- a/packages/modules/b2c-core/src/workflows/seller/workflows/create-seller.ts +++ b/packages/modules/b2c-core/src/workflows/seller/workflows/create-seller.ts @@ -1,12 +1,12 @@ import { transform } from "@medusajs/framework/workflows-sdk"; -import { setAuthAppMetadataStep } from "@medusajs/medusa/core-flows"; +import { emitEventStep, setAuthAppMetadataStep } from "@medusajs/medusa/core-flows"; import { WorkflowResponse, createHook, createWorkflow, } from "@medusajs/workflows-sdk"; -import { CreateMemberDTO, CreateSellerDTO } from "@mercurjs/framework"; +import { CreateMemberDTO, CreateSellerDTO, SellerEvents } from "@mercurjs/framework"; import { createMemberStep, @@ -47,6 +47,14 @@ export const createSellerWorkflow = createWorkflow( const sellerCreatedHook = createHook("sellerCreated", { sellerId: seller.id, }); + + emitEventStep({ + eventName: SellerEvents.SELLER_CREATED, + data: { + ids: [seller.id], + } + }); + return new WorkflowResponse(seller, { hooks: [sellerCreatedHook] }); } ); diff --git a/packages/modules/b2c-core/src/workflows/seller/workflows/update-seller.ts b/packages/modules/b2c-core/src/workflows/seller/workflows/update-seller.ts index 9431f9a9f..6df6d501e 100644 --- a/packages/modules/b2c-core/src/workflows/seller/workflows/update-seller.ts +++ b/packages/modules/b2c-core/src/workflows/seller/workflows/update-seller.ts @@ -1,12 +1,31 @@ -import { WorkflowResponse, createWorkflow } from '@medusajs/workflows-sdk' +import { + WorkflowResponse, + createHook, createWorkflow +} from '@medusajs/workflows-sdk' -import { UpdateSellerDTO } from '@mercurjs/framework' +import { SellerEvents, UpdateSellerDTO } from '@mercurjs/framework' import { updateSellerStep } from '../steps' +import { emitEventStep } from '@medusajs/medusa/core-flows' export const updateSellerWorkflow = createWorkflow( 'update-seller', function (input: UpdateSellerDTO) { - return new WorkflowResponse(updateSellerStep(input)) + const seller = updateSellerStep(input) + + const sellerUpdatedHook = createHook("sellerUpdated", { + sellerId: seller.id, + }); + + emitEventStep({ + eventName: SellerEvents.SELLER_UPDATED, + data: { + ids: [seller.id], + } + }) + + return new WorkflowResponse(seller, { + hooks: [sellerUpdatedHook], + }); } )