feat: event aggregator (#6218)
What: - Event Aggregator Util - Preparation for normalizing event in a new format (backward compatible with the current format) - GQL Schema to joiner config and some Entities configured - Link modules emmiting events
This commit is contained in:
1 parent
73fd92a1af
commit
884428a1b5
66 files changed
+1407
-749
No files matched your search
@@ -12,6 +12,9 @@ export const ProductShippingProfile: ModuleJoinerConfig = {
|
||||
alias: [
|
||||
{
|
||||
name: "product_shipping_profile",
|
||||
args: {
|
||||
entity: "LinkProductShippingProfile",
|
||||
},
|
||||
},
|
||||
],
|
||||
primaryKeys: ["id", "product_id", "profile_id"],
|
||||
|
||||
@@ -17,10 +17,13 @@ export const ProductVariantInventoryItem: ModuleJoinerConfig = {
|
||||
},
|
||||
alias: [
|
||||
{
|
||||
name: "product_variant_inventory_item",
|
||||
},
|
||||
{
|
||||
name: "product_variant_inventory_items",
|
||||
name: [
|
||||
"product_variant_inventory_item",
|
||||
"product_variant_inventory_items",
|
||||
],
|
||||
args: {
|
||||
entity: "LinkProductVariantInventoryItem",
|
||||
},
|
||||
},
|
||||
],
|
||||
primaryKeys: ["id", "variant_id", "inventory_item_id"],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { LINKS } from "../links"
|
||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||
import { Modules } from "@medusajs/modules-sdk"
|
||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||
import { LINKS } from "../links"
|
||||
|
||||
export const ProductVariantPriceSet: ModuleJoinerConfig = {
|
||||
serviceName: LINKS.ProductVariantPriceSet,
|
||||
@@ -11,10 +11,10 @@ export const ProductVariantPriceSet: ModuleJoinerConfig = {
|
||||
},
|
||||
alias: [
|
||||
{
|
||||
name: "product_variant_price_set",
|
||||
},
|
||||
{
|
||||
name: "product_variant_price_sets",
|
||||
name: ["product_variant_price_set", "product_variant_price_sets"],
|
||||
args: {
|
||||
entity: "LinkProductVariantPriceSet",
|
||||
},
|
||||
},
|
||||
],
|
||||
primaryKeys: ["id", "variant_id", "price_set_id"],
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { InternalModuleDeclaration, MedusaModule } from "@medusajs/modules-sdk"
|
||||
import {
|
||||
InternalModuleDeclaration,
|
||||
MedusaModule,
|
||||
ModuleRegistrationName,
|
||||
} from "@medusajs/modules-sdk"
|
||||
import {
|
||||
ExternalModuleDeclaration,
|
||||
ILinkModule,
|
||||
@@ -15,11 +19,16 @@ import {
|
||||
ContainerRegistrationKeys,
|
||||
lowerCaseFirst,
|
||||
simpleHash,
|
||||
toPascalCase,
|
||||
} from "@medusajs/utils"
|
||||
import * as linkDefinitions from "../definitions"
|
||||
import { getMigration } from "../migration"
|
||||
import { InitializeModuleInjectableDependencies } from "../types"
|
||||
import { composeLinkName, generateGraphQLSchema } from "../utils"
|
||||
import {
|
||||
composeLinkName,
|
||||
composeTableName,
|
||||
generateGraphQLSchema,
|
||||
} from "../utils"
|
||||
import { getLinkModuleDefinition } from "./module-definition"
|
||||
|
||||
export const initialize = async (
|
||||
@@ -98,7 +107,28 @@ export const initialize = async (
|
||||
continue
|
||||
}
|
||||
|
||||
definition.schema = generateGraphQLSchema(definition, primary, foreign)
|
||||
const logger =
|
||||
injectedDependencies?.[ContainerRegistrationKeys.LOGGER] ?? console.log
|
||||
|
||||
definition.schema = generateGraphQLSchema(definition, primary, foreign, {
|
||||
logger,
|
||||
})
|
||||
|
||||
definition.alias ??= []
|
||||
for (const alias of definition.alias) {
|
||||
alias.args ??= {}
|
||||
|
||||
alias.args.entity = toPascalCase(
|
||||
"Link_" +
|
||||
(definition.databaseConfig?.tableName ??
|
||||
composeTableName(
|
||||
primary.serviceName,
|
||||
primary.foreignKey,
|
||||
foreign.serviceName,
|
||||
foreign.foreignKey
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
const moduleDefinition = getLinkModuleDefinition(
|
||||
definition,
|
||||
@@ -110,6 +140,7 @@ export const initialize = async (
|
||||
key: serviceKey,
|
||||
registrationName: serviceKey,
|
||||
label: serviceKey,
|
||||
dependencies: [ModuleRegistrationName.EVENT_BUS],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: injectedDependencies?.[
|
||||
|
||||
@@ -7,7 +7,9 @@ import {
|
||||
ModuleJoinerConfig,
|
||||
ModulesSdkTypes,
|
||||
} from "@medusajs/types"
|
||||
import { lowerCaseFirst, simpleHash, toPascalCase } from "@medusajs/utils"
|
||||
import { asClass, asValue } from "awilix"
|
||||
import { composeLinkName, composeTableName } from "../utils"
|
||||
|
||||
export function containerLoader(entity, joinerConfig: ModuleJoinerConfig) {
|
||||
return async (
|
||||
@@ -22,6 +24,29 @@ export function containerLoader(entity, joinerConfig: ModuleJoinerConfig) {
|
||||
): Promise<void> => {
|
||||
const [primary, foreign] = joinerConfig.relationships!
|
||||
|
||||
const serviceName = !joinerConfig.isReadOnlyLink
|
||||
? lowerCaseFirst(
|
||||
joinerConfig.serviceName ??
|
||||
composeLinkName(
|
||||
primary.serviceName,
|
||||
primary.foreignKey,
|
||||
foreign.serviceName,
|
||||
foreign.foreignKey
|
||||
)
|
||||
)
|
||||
: simpleHash(JSON.stringify(joinerConfig.extends))
|
||||
|
||||
const entityName = toPascalCase(
|
||||
"Link_" +
|
||||
(joinerConfig.databaseConfig?.tableName ??
|
||||
composeTableName(
|
||||
primary.serviceName,
|
||||
primary.foreignKey,
|
||||
foreign.serviceName,
|
||||
foreign.foreignKey
|
||||
))
|
||||
)
|
||||
|
||||
container.register({
|
||||
joinerConfig: asValue(joinerConfig),
|
||||
primaryKey: asValue(primary.foreignKey.split(",")),
|
||||
@@ -35,6 +60,8 @@ export function containerLoader(entity, joinerConfig: ModuleJoinerConfig) {
|
||||
|
||||
baseRepository: asClass(BaseRepository).singleton(),
|
||||
linkRepository: asClass(getLinkRepository(entity)).singleton(),
|
||||
entityName: asValue(entityName),
|
||||
serviceName: asValue(serviceName),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
Context,
|
||||
DAL,
|
||||
FindConfig,
|
||||
IEventBusModuleService,
|
||||
ILinkModule,
|
||||
InternalModuleDeclaration,
|
||||
ModuleJoinerConfig,
|
||||
@@ -9,6 +10,7 @@ import {
|
||||
SoftDeleteReturn,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
CommonEvents,
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
MapToConfig,
|
||||
@@ -24,14 +26,20 @@ import { shouldForceTransaction } from "../utils"
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
linkService: LinkService<any>
|
||||
eventBusModuleService?: IEventBusModuleService
|
||||
primaryKey: string | string[]
|
||||
foreignKey: string
|
||||
extraFields: string[]
|
||||
entityName: string
|
||||
serviceName: string
|
||||
}
|
||||
|
||||
export default class LinkModuleService<TLink> implements ILinkModule {
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
protected readonly linkService_: LinkService<TLink>
|
||||
protected readonly eventBusModuleService_?: IEventBusModuleService
|
||||
protected readonly entityName_: string
|
||||
protected readonly serviceName_: string
|
||||
protected primaryKey_: string[]
|
||||
protected foreignKey_: string
|
||||
protected extraFields_: string[]
|
||||
@@ -40,17 +48,23 @@ export default class LinkModuleService<TLink> implements ILinkModule {
|
||||
{
|
||||
baseRepository,
|
||||
linkService,
|
||||
eventBusModuleService,
|
||||
primaryKey,
|
||||
foreignKey,
|
||||
extraFields,
|
||||
entityName,
|
||||
serviceName,
|
||||
}: InjectedDependencies,
|
||||
readonly moduleDeclaration: InternalModuleDeclaration
|
||||
) {
|
||||
this.baseRepository_ = baseRepository
|
||||
this.linkService_ = linkService
|
||||
this.eventBusModuleService_ = eventBusModuleService
|
||||
this.primaryKey_ = !Array.isArray(primaryKey) ? [primaryKey] : primaryKey
|
||||
this.foreignKey_ = foreignKey
|
||||
this.extraFields_ = extraFields
|
||||
this.entityName_ = entityName
|
||||
this.serviceName_ = serviceName
|
||||
}
|
||||
|
||||
__joinerConfig(): ModuleJoinerConfig {
|
||||
@@ -188,6 +202,21 @@ export default class LinkModuleService<TLink> implements ILinkModule {
|
||||
|
||||
const links = await this.linkService_.create(data, sharedContext)
|
||||
|
||||
await this.eventBusModuleService_?.emit<Record<string, unknown>>(
|
||||
(data as { id: unknown }[]).map(({ id }) => ({
|
||||
eventName: this.entityName_ + "." + CommonEvents.ATTACHED,
|
||||
body: {
|
||||
metadata: {
|
||||
service: this.serviceName_,
|
||||
action: CommonEvents.ATTACHED,
|
||||
object: this.entityName_,
|
||||
eventGroupId: sharedContext.eventGroupId,
|
||||
},
|
||||
data: { id },
|
||||
},
|
||||
}))
|
||||
)
|
||||
|
||||
return await this.baseRepository_.serialize<object[]>(links)
|
||||
}
|
||||
|
||||
@@ -224,6 +253,22 @@ export default class LinkModuleService<TLink> implements ILinkModule {
|
||||
this.validateFields(data)
|
||||
|
||||
await this.linkService_.delete(data, sharedContext)
|
||||
|
||||
const allData = Array.isArray(data) ? data : [data]
|
||||
await this.eventBusModuleService_?.emit<Record<string, unknown>>(
|
||||
allData.map(({ id }) => ({
|
||||
eventName: this.entityName_ + "." + CommonEvents.DETACHED,
|
||||
body: {
|
||||
metadata: {
|
||||
service: this.serviceName_,
|
||||
action: CommonEvents.DETACHED,
|
||||
object: this.entityName_,
|
||||
eventGroupId: sharedContext.eventGroupId,
|
||||
},
|
||||
data: { id },
|
||||
},
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
async softDelete(
|
||||
@@ -233,7 +278,10 @@ export default class LinkModuleService<TLink> implements ILinkModule {
|
||||
): Promise<Record<string, unknown[]> | void> {
|
||||
this.validateFields(data)
|
||||
|
||||
let [, cascadedEntitiesMap] = await this.softDelete_(data, sharedContext)
|
||||
let [deletedEntities, cascadedEntitiesMap] = await this.softDelete_(
|
||||
data,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const pk = this.primaryKey_.join(",")
|
||||
const entityNameToLinkableKeysMap: MapToConfig = {
|
||||
@@ -256,6 +304,21 @@ export default class LinkModuleService<TLink> implements ILinkModule {
|
||||
)
|
||||
}
|
||||
|
||||
await this.eventBusModuleService_?.emit<Record<string, unknown>>(
|
||||
(deletedEntities as { id: string }[]).map(({ id }) => ({
|
||||
eventName: this.entityName_ + "." + CommonEvents.DETACHED,
|
||||
body: {
|
||||
metadata: {
|
||||
service: this.serviceName_,
|
||||
action: CommonEvents.DETACHED,
|
||||
object: this.entityName_,
|
||||
eventGroupId: sharedContext.eventGroupId,
|
||||
},
|
||||
data: { id },
|
||||
},
|
||||
}))
|
||||
)
|
||||
|
||||
return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0
|
||||
}
|
||||
|
||||
@@ -263,7 +326,7 @@ export default class LinkModuleService<TLink> implements ILinkModule {
|
||||
protected async softDelete_(
|
||||
data: any,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<[string[], Record<string, string[]>]> {
|
||||
): Promise<[object[], Record<string, string[]>]> {
|
||||
return await this.linkService_.softDelete(data, sharedContext)
|
||||
}
|
||||
|
||||
@@ -274,7 +337,10 @@ export default class LinkModuleService<TLink> implements ILinkModule {
|
||||
): Promise<Record<string, unknown[]> | void> {
|
||||
this.validateFields(data)
|
||||
|
||||
let [, cascadedEntitiesMap] = await this.restore_(data, sharedContext)
|
||||
let [restoredEntities, cascadedEntitiesMap] = await this.restore_(
|
||||
data,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const pk = this.primaryKey_.join(",")
|
||||
const entityNameToLinkableKeysMap: MapToConfig = {
|
||||
@@ -297,6 +363,21 @@ export default class LinkModuleService<TLink> implements ILinkModule {
|
||||
)
|
||||
}
|
||||
|
||||
await this.eventBusModuleService_?.emit<Record<string, unknown>>(
|
||||
(restoredEntities as { id: string }[]).map(({ id }) => ({
|
||||
eventName: this.entityName_ + "." + CommonEvents.ATTACHED,
|
||||
body: {
|
||||
metadata: {
|
||||
service: this.serviceName_,
|
||||
action: CommonEvents.ATTACHED,
|
||||
object: this.entityName_,
|
||||
eventGroupId: sharedContext.eventGroupId,
|
||||
},
|
||||
data: { id },
|
||||
},
|
||||
}))
|
||||
)
|
||||
|
||||
return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0
|
||||
}
|
||||
|
||||
@@ -304,7 +385,7 @@ export default class LinkModuleService<TLink> implements ILinkModule {
|
||||
async restore_(
|
||||
data: any,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<[string[], Record<string, string[]>]> {
|
||||
): Promise<[object[], Record<string, string[]>]> {
|
||||
return await this.linkService_.restore(data, sharedContext)
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ export default class LinkService<TEntity> {
|
||||
async softDelete(
|
||||
data: any,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<[string[], Record<string, string[]>]> {
|
||||
): Promise<[object[], Record<string, string[]>]> {
|
||||
const filter = {}
|
||||
for (const key in data) {
|
||||
filter[key] = { $in: Array.isArray(data[key]) ? data[key] : [data[key]] }
|
||||
@@ -104,7 +104,7 @@ export default class LinkService<TEntity> {
|
||||
async restore(
|
||||
data: any,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<[string[], Record<string, string[]>]> {
|
||||
): Promise<[object[], Record<string, string[]>]> {
|
||||
const filter = {}
|
||||
for (const key in data) {
|
||||
filter[key] = { $in: Array.isArray(data[key]) ? data[key] : [data[key]] }
|
||||
|
||||
Reference in new issue
Block a user