Files
medusa-store/packages/modules/notification/src/services/notification-provider.ts
2025-07-22 10:44:17 +02:00

107 lines
3.4 KiB
TypeScript

import {
DAL,
InferEntityType,
Logger,
NotificationTypes,
} from "@medusajs/framework/types"
import { ModulesSdkUtils } from "@medusajs/framework/utils"
import { NotificationProvider } from "@models"
import { NotificationProviderRegistrationPrefix } from "@types"
type InjectedDependencies = {
logger?: Logger
notificationProviderRepository: DAL.RepositoryService<
InferEntityType<typeof NotificationProvider>
>
[
key: `${typeof NotificationProviderRegistrationPrefix}${string}`
]: NotificationTypes.INotificationProvider
}
type Provider = InferEntityType<typeof NotificationProvider>
export default class NotificationProviderService extends ModulesSdkUtils.MedusaInternalService<
InjectedDependencies,
typeof NotificationProvider
>(NotificationProvider) {
protected readonly notificationProviderRepository_: DAL.RepositoryService<
InferEntityType<typeof NotificationProvider>
>
// We can store the providers in a memory since they can only be registered on startup and not changed during runtime
#logger: Logger
protected providersCache: Map<
string,
InferEntityType<typeof NotificationProvider>
>
constructor(container: InjectedDependencies) {
super(container)
this.notificationProviderRepository_ =
container.notificationProviderRepository
this.#logger = container["logger"]
? container.logger
: (console as unknown as Logger)
}
protected retrieveProviderRegistration(
providerId: string
): NotificationTypes.INotificationProvider {
try {
return this.__container__[
`${NotificationProviderRegistrationPrefix}${providerId}`
]
} catch (err) {
if (err.name === "AwilixResolutionError") {
const errMessage = `
Unable to retrieve the notification provider with id: ${providerId}
Please make sure that the provider is registered in the container and it is configured correctly in your project configuration file.`
// Log full error for debugging
this.#logger.error(`AwilixResolutionError: ${err.message}`, err)
throw new Error(errMessage)
}
const errMessage = `Unable to retrieve the notification provider with id: ${providerId}, the following error occurred: ${err.message}`
this.#logger.error(errMessage)
throw new Error(errMessage)
}
}
async getProviderForChannels<
TChannel = string | string[],
TOutput = TChannel extends string[] ? Provider[] : Provider | undefined
>(channels: TChannel): Promise<TOutput> {
if (!this.providersCache) {
const providers = await this.notificationProviderRepository_.find({
where: { is_enabled: true },
})
this.providersCache = new Map(
providers.flatMap((provider) =>
provider.channels.map((c) => [c, provider])
)
)
}
const normalizedChannels = Array.isArray(channels) ? channels : [channels]
const results = normalizedChannels
.map((channel) => this.providersCache.get(channel))
.filter(Boolean)
return (Array.isArray(channels) ? results : results[0]) as TOutput
}
async send(
provider: InferEntityType<typeof NotificationProvider>,
notification: NotificationTypes.ProviderSendNotificationDTO
): Promise<NotificationTypes.ProviderSendNotificationResultsDTO> {
const providerHandler = this.retrieveProviderRegistration(provider.id)
return await providerHandler.send(notification)
}
}