feat(medusa): Migrate NotificationService to TS + add NotificationInterface (#1922)
This commit is contained in:
@@ -7,6 +7,8 @@ import {
|
||||
defaultAdminNotificationsFields,
|
||||
defaultAdminNotificationsRelations,
|
||||
} from "./"
|
||||
import { Notification } from "../../../../models"
|
||||
import { FindConfig } from "../../../../types/common"
|
||||
|
||||
/**
|
||||
* @oas [get] /notifications
|
||||
@@ -91,20 +93,23 @@ export default async (req, res) => {
|
||||
}
|
||||
|
||||
const listConfig = {
|
||||
select: includeFields.length
|
||||
select: (includeFields.length
|
||||
? includeFields
|
||||
: defaultAdminNotificationsFields,
|
||||
: defaultAdminNotificationsFields) as (keyof Notification)[],
|
||||
relations: expandFields.length
|
||||
? expandFields
|
||||
: defaultAdminNotificationsRelations,
|
||||
skip: offset,
|
||||
take: limit,
|
||||
order: { created_at: "DESC" },
|
||||
}
|
||||
} as FindConfig<Notification>
|
||||
|
||||
const notifications = await notificationService.list(selector, listConfig)
|
||||
|
||||
const resultFields = [...listConfig.select, ...listConfig.relations]
|
||||
const resultFields = [
|
||||
...(listConfig.select ?? []),
|
||||
...(listConfig.relations ?? []),
|
||||
]
|
||||
const data = notifications.map((o) => pick(o, resultFields))
|
||||
|
||||
res.json({ notifications: data })
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
} from "."
|
||||
import { validator } from "../../../../utils/validator"
|
||||
import { NotificationService } from "../../../../services"
|
||||
import { Notification } from "../../../../models"
|
||||
|
||||
/**
|
||||
* @oas [post] /notifications/{id}/resend
|
||||
@@ -56,7 +57,7 @@ export default async (req, res) => {
|
||||
await notificationService.resend(id, config)
|
||||
|
||||
const notification = await notificationService.retrieve(id, {
|
||||
select: defaultAdminNotificationsFields,
|
||||
select: defaultAdminNotificationsFields as (keyof Notification)[],
|
||||
relations: defaultAdminNotificationsRelations,
|
||||
})
|
||||
|
||||
|
||||
@@ -4,5 +4,7 @@ export * from "./tax-service"
|
||||
export * from "./transaction-base-service"
|
||||
export * from "./batch-job-strategy"
|
||||
export * from "./file-service"
|
||||
export * from "./notification-service"
|
||||
export * from "./price-selection-strategy"
|
||||
export * from "./models/base-entity"
|
||||
export * from "./models/soft-deletable-entity"
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { TransactionBaseService } from "./transaction-base-service"
|
||||
import BaseNotificationService from "medusa-interfaces/dist/notification-service"
|
||||
|
||||
type ReturnedData = {
|
||||
to: string
|
||||
status: string
|
||||
data: Record<string, unknown>
|
||||
}
|
||||
|
||||
export interface INotificationService<T extends TransactionBaseService<never>>
|
||||
extends TransactionBaseService<T> {
|
||||
sendNotification(
|
||||
event: string,
|
||||
data: unknown,
|
||||
attachmentGenerator: unknown
|
||||
): Promise<ReturnedData>
|
||||
|
||||
resendNotification(
|
||||
notification: unknown,
|
||||
config: unknown,
|
||||
attachmentGenerator: unknown
|
||||
): Promise<ReturnedData>
|
||||
}
|
||||
|
||||
export abstract class AbstractNotificationService<
|
||||
T extends TransactionBaseService<never>
|
||||
>
|
||||
extends TransactionBaseService<T>
|
||||
implements INotificationService<T>
|
||||
{
|
||||
static identifier: string
|
||||
|
||||
getIdentifier(): string {
|
||||
return (this.constructor as any).identifier
|
||||
}
|
||||
|
||||
abstract sendNotification(
|
||||
event: string,
|
||||
data: unknown,
|
||||
attachmentGenerator: unknown
|
||||
): Promise<ReturnedData>
|
||||
|
||||
abstract resendNotification(
|
||||
notification: unknown,
|
||||
config: unknown,
|
||||
attachmentGenerator: unknown
|
||||
): Promise<ReturnedData>
|
||||
}
|
||||
|
||||
export const isNotificationService = (obj: unknown): boolean => {
|
||||
return (
|
||||
obj instanceof AbstractNotificationService ||
|
||||
obj instanceof BaseNotificationService
|
||||
)
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
BaseService as LegacyBaseService,
|
||||
PaymentService,
|
||||
FulfillmentService,
|
||||
NotificationService,
|
||||
FileService,
|
||||
OauthService,
|
||||
SearchService,
|
||||
@@ -21,6 +20,9 @@ import {
|
||||
isFileService,
|
||||
isTaxCalculationStrategy,
|
||||
TransactionBaseService as BaseService,
|
||||
isNotificationService,
|
||||
isBatchJobStrategy,
|
||||
isPriceSelectionStrategy,
|
||||
} from "../interfaces"
|
||||
import formatRegistrationName from "../utils/format-registration-name"
|
||||
import {
|
||||
@@ -30,8 +32,6 @@ import {
|
||||
MedusaContainer,
|
||||
} from "../types/global"
|
||||
import { MiddlewareService } from "../services"
|
||||
import { isBatchJobStrategy } from "../interfaces/batch-job-strategy"
|
||||
import { isPriceSelectionStrategy } from "../interfaces/price-selection-strategy"
|
||||
import logger from "./logger"
|
||||
|
||||
type Options = {
|
||||
@@ -392,7 +392,7 @@ export async function registerServices(
|
||||
).singleton(),
|
||||
[`fp_${loaded.identifier}`]: aliasTo(name),
|
||||
})
|
||||
} else if (loaded.prototype instanceof NotificationService) {
|
||||
} else if (isNotificationService(loaded.prototype)) {
|
||||
container.registerAdd(
|
||||
"notificationProviders",
|
||||
asFunction((cradle) => new loaded(cradle, pluginDetails.options))
|
||||
|
||||
@@ -29,7 +29,7 @@ export class Notification extends BaseEntity {
|
||||
|
||||
@Index()
|
||||
@Column({ nullable: true })
|
||||
customer_id: string
|
||||
customer_id: string | null
|
||||
|
||||
@ManyToOne(() => Customer)
|
||||
@JoinColumn({ name: "customer_id" })
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { BaseService } from "medusa-interfaces"
|
||||
|
||||
/**
|
||||
* Provides layer to manipulate orchestrate notifications.
|
||||
* @extends BaseService
|
||||
*/
|
||||
class NotificationService extends BaseService {
|
||||
constructor(container) {
|
||||
super()
|
||||
|
||||
const {
|
||||
manager,
|
||||
notificationProviderRepository,
|
||||
notificationRepository,
|
||||
logger,
|
||||
} = container
|
||||
|
||||
this.container_ = container
|
||||
|
||||
/** @private @const {EntityManager} */
|
||||
this.manager_ = manager
|
||||
this.logger_ = logger
|
||||
|
||||
/** @private @const {NotificationRepository} */
|
||||
this.notificationRepository_ = notificationRepository
|
||||
this.notificationProviderRepository_ = notificationProviderRepository
|
||||
|
||||
this.subscribers_ = {}
|
||||
this.attachmentGenerator_ = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an attachment generator to the service. The generator can be
|
||||
* used to generate on demand invoices or other documents.
|
||||
* @param {object} service
|
||||
*/
|
||||
registerAttachmentGenerator(service) {
|
||||
this.attachmentGenerator_ = service
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the service's manager to a given transaction manager.
|
||||
* @param {EntityManager} transactionManager - the manager to use
|
||||
* @return {NotificationService} a cloned notification service
|
||||
*/
|
||||
withTransaction(transactionManager) {
|
||||
if (!transactionManager) {
|
||||
return this
|
||||
}
|
||||
|
||||
const cloned = new NotificationService({
|
||||
manager: transactionManager,
|
||||
notificationProviderRepository: this.notificationProviderRepository_,
|
||||
notificationRepository: this.notificationRepository_,
|
||||
logger: this.logger_,
|
||||
})
|
||||
|
||||
cloned.transactionManager_ = transactionManager
|
||||
|
||||
return cloned
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a list of notification provider ids and persists them in the database.
|
||||
* @param {Array<string>} providers - a list of provider ids
|
||||
*/
|
||||
async registerInstalledProviders(providers) {
|
||||
const { manager, notificationProviderRepository } = this.container_
|
||||
const model = manager.getCustomRepository(notificationProviderRepository)
|
||||
model.update({}, { is_installed: false })
|
||||
for (const p of providers) {
|
||||
const n = model.create({ id: p, is_installed: true })
|
||||
await model.save(n)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of notifications.
|
||||
* @param {object} selector - the params to select the notifications by.
|
||||
* @param {object} config - the configuration to apply to the query
|
||||
* @return {Array<Notification>} the notifications that satisfy the query.
|
||||
*/
|
||||
async list(
|
||||
selector,
|
||||
config = { skip: 0, take: 50, order: { created_at: "DESC" } }
|
||||
) {
|
||||
const notiRepo = this.manager_.getCustomRepository(
|
||||
this.notificationRepository_
|
||||
)
|
||||
const query = this.buildQuery_(selector, config)
|
||||
return notiRepo.find(query)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a notification with a given id
|
||||
* @param {string} id - the id of the notification
|
||||
* @param {object} config - the configuration to apply to the query
|
||||
* @return {Notification} the notification
|
||||
*/
|
||||
async retrieve(id, config = {}) {
|
||||
const notiRepository = this.manager_.getCustomRepository(
|
||||
this.notificationRepository_
|
||||
)
|
||||
|
||||
const validatedId = this.validateId_(id)
|
||||
const query = this.buildQuery_({ id: validatedId }, config)
|
||||
|
||||
const notification = await notiRepository.findOne(query)
|
||||
|
||||
if (!notification) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`Notification with id: ${id} was not found.`
|
||||
)
|
||||
}
|
||||
|
||||
return notification
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes a given provider to an event.
|
||||
* @param {string} eventName - the event to subscribe to
|
||||
* @param {string} providerId - the provider that the event will be sent to
|
||||
*/
|
||||
subscribe(eventName, providerId) {
|
||||
if (typeof providerId !== "string") {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_ALLOWED,
|
||||
"providerId must be a string"
|
||||
)
|
||||
}
|
||||
|
||||
if (this.subscribers_[eventName]) {
|
||||
this.subscribers_[eventName].push(providerId)
|
||||
} else {
|
||||
this.subscribers_[eventName] = [providerId]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a provider with a given id. Will throw a NOT_FOUND error if the
|
||||
* resolution fails.
|
||||
* @param {string} id - the id of the provider
|
||||
* @return {NotificationProvider} the notification provider
|
||||
*/
|
||||
retrieveProvider_(id) {
|
||||
try {
|
||||
return this.container_[`noti_${id}`]
|
||||
} catch (err) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`Could not find a notification provider with id: ${id}.`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an event by relaying the event data to the subscribing providers.
|
||||
* The result of the notification send will be persisted in the database in
|
||||
* order to allow for resends. Will log any errors that are encountered.
|
||||
* @param {string} eventName - the event to handle
|
||||
* @param {object} data - the data the event was sent with
|
||||
* @return {Promise} - the result of notification subscribed
|
||||
*/
|
||||
handleEvent(eventName, data) {
|
||||
const subs = this.subscribers_[eventName]
|
||||
if (!subs) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
if (data["no_notification"] === true) {
|
||||
return
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
subs.map(async (providerId) => {
|
||||
return this.send(eventName, data, providerId).catch((err) => {
|
||||
console.log(err)
|
||||
this.logger_.warn(
|
||||
`An error occured while ${providerId} was processing a notification for ${eventName}: ${err.message}`
|
||||
)
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a notification, by calling the given provider's sendNotification
|
||||
* method. Persists the Notification in the database.
|
||||
* @param {string} event - the name of the event
|
||||
* @param {object} eventData - the data the event was sent with
|
||||
* @param {string} providerId - the provider that should hande the event.
|
||||
* @return {Notification} the created notification
|
||||
*/
|
||||
async send(event, eventData, providerId) {
|
||||
const provider = this.retrieveProvider_(providerId)
|
||||
const result = await provider.sendNotification(
|
||||
event,
|
||||
eventData,
|
||||
this.attachmentGenerator_
|
||||
)
|
||||
|
||||
if (!result) {
|
||||
return
|
||||
}
|
||||
|
||||
const { to, data } = result
|
||||
const notiRepo = this.manager_.getCustomRepository(
|
||||
this.notificationRepository_
|
||||
)
|
||||
|
||||
const [resource_type] = event.split(".")
|
||||
const resource_id = eventData.id
|
||||
const customer_id = eventData.customer_id || null
|
||||
|
||||
const created = notiRepo.create({
|
||||
resource_type,
|
||||
resource_id,
|
||||
customer_id,
|
||||
to,
|
||||
data,
|
||||
event_name: event,
|
||||
provider_id: providerId,
|
||||
})
|
||||
|
||||
return notiRepo.save(created)
|
||||
}
|
||||
|
||||
/**
|
||||
* Resends a notification by retrieving a prior notification and calling the
|
||||
* underlying provider's resendNotification method.
|
||||
* @param {string} id - the id of the notification
|
||||
* @param {object} config - any configuration that might override the previous
|
||||
* send
|
||||
* @return {Notification} the newly created notification
|
||||
*/
|
||||
async resend(id, config = {}) {
|
||||
const notification = await this.retrieve(id)
|
||||
|
||||
const provider = this.retrieveProvider_(notification.provider_id)
|
||||
const { to, data } = await provider.resendNotification(
|
||||
notification,
|
||||
config,
|
||||
this.attachmentGenerator_
|
||||
)
|
||||
|
||||
const notiRepo = this.manager_.getCustomRepository(
|
||||
this.notificationRepository_
|
||||
)
|
||||
const created = notiRepo.create({
|
||||
...notification,
|
||||
to,
|
||||
data,
|
||||
parent_id: id,
|
||||
})
|
||||
|
||||
return notiRepo.save(created)
|
||||
}
|
||||
}
|
||||
|
||||
export default NotificationService
|
||||
@@ -0,0 +1,282 @@
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import {
|
||||
AbstractNotificationService,
|
||||
TransactionBaseService,
|
||||
} from "../interfaces"
|
||||
import { EntityManager } from "typeorm"
|
||||
import { Logger } from "../types/global"
|
||||
import { NotificationRepository } from "../repositories/notification"
|
||||
import { NotificationProviderRepository } from "../repositories/notification-provider"
|
||||
import { FindConfig, Selector } from "../types/common"
|
||||
import { buildQuery } from "../utils"
|
||||
import { Notification } from "../models"
|
||||
|
||||
type InjectedDependencies = {
|
||||
manager: EntityManager
|
||||
logger: Logger
|
||||
notificationRepository: typeof NotificationRepository
|
||||
notificationProviderRepository: typeof NotificationProviderRepository
|
||||
}
|
||||
type NotificationProviderKey = `noti_${string}`
|
||||
|
||||
class NotificationService extends TransactionBaseService<NotificationService> {
|
||||
protected manager_: EntityManager
|
||||
protected transactionManager_: EntityManager | undefined
|
||||
|
||||
protected subscribers_ = {}
|
||||
protected attachmentGenerator_: unknown = null
|
||||
protected readonly container_: InjectedDependencies & {
|
||||
[key in `${NotificationProviderKey}`]: AbstractNotificationService<never>
|
||||
}
|
||||
protected readonly logger_: Logger
|
||||
protected readonly notificationRepository_: typeof NotificationRepository
|
||||
protected readonly notificationProviderRepository_: typeof NotificationProviderRepository
|
||||
|
||||
constructor(container: InjectedDependencies) {
|
||||
super(container)
|
||||
|
||||
const {
|
||||
manager,
|
||||
notificationProviderRepository,
|
||||
notificationRepository,
|
||||
logger,
|
||||
} = container
|
||||
|
||||
this.container_ = container
|
||||
|
||||
/** @private @const {EntityManager} */
|
||||
this.manager_ = manager
|
||||
this.logger_ = logger
|
||||
|
||||
/** @private @const {NotificationRepository} */
|
||||
this.notificationRepository_ = notificationRepository
|
||||
this.notificationProviderRepository_ = notificationProviderRepository
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an attachment generator to the service. The generator can be
|
||||
* used to generate on demand invoices or other documents.
|
||||
* @param service the service to assign to the attachmentGenerator
|
||||
*/
|
||||
registerAttachmentGenerator(service: unknown): void {
|
||||
this.attachmentGenerator_ = service
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a list of notification provider ids and persists them in the database.
|
||||
* @param providerIds - a list of provider ids
|
||||
*/
|
||||
async registerInstalledProviders(providerIds: string[]): Promise<void> {
|
||||
const { manager, notificationProviderRepository } = this.container_
|
||||
const model = manager.getCustomRepository(notificationProviderRepository)
|
||||
await model.update({}, { is_installed: false })
|
||||
for (const id of providerIds) {
|
||||
const n = model.create({ id, is_installed: true })
|
||||
await model.save(n)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of notifications.
|
||||
* @param selector - the params to select the notifications by.
|
||||
* @param config - the configuration to apply to the query
|
||||
* @return the notifications that satisfy the query.
|
||||
*/
|
||||
async list(
|
||||
selector: Selector<Notification>,
|
||||
config: FindConfig<Notification> = {
|
||||
skip: 0,
|
||||
take: 50,
|
||||
order: { created_at: "DESC" },
|
||||
}
|
||||
): Promise<Notification[]> {
|
||||
const notiRepo = this.manager_.getCustomRepository(
|
||||
this.notificationRepository_
|
||||
)
|
||||
const query = buildQuery(selector, config)
|
||||
return await notiRepo.find(query)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a notification with a given id
|
||||
* @param id - the id of the notification
|
||||
* @param config - the configuration to apply to the query
|
||||
* @return the notification
|
||||
*/
|
||||
async retrieve(
|
||||
id: string,
|
||||
config: FindConfig<Notification> = {}
|
||||
): Promise<Notification | never> {
|
||||
const notiRepository = this.manager_.getCustomRepository(
|
||||
this.notificationRepository_
|
||||
)
|
||||
|
||||
const query = buildQuery({ id }, config)
|
||||
|
||||
const notification = await notiRepository.findOne(query)
|
||||
|
||||
if (!notification) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`Notification with id: ${id} was not found.`
|
||||
)
|
||||
}
|
||||
|
||||
return notification
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes a given provider to an event.
|
||||
* @param eventName - the event to subscribe to
|
||||
* @param providerId - the provider that the event will be sent to
|
||||
*/
|
||||
subscribe(eventName: string, providerId: string): void {
|
||||
if (typeof providerId !== "string") {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_ALLOWED,
|
||||
"providerId must be a string"
|
||||
)
|
||||
}
|
||||
|
||||
if (this.subscribers_[eventName]) {
|
||||
this.subscribers_[eventName].push(providerId)
|
||||
} else {
|
||||
this.subscribers_[eventName] = [providerId]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a provider with a given id. Will throw a NOT_FOUND error if the
|
||||
* resolution fails.
|
||||
* @param id - the id of the provider
|
||||
* @return the notification provider
|
||||
*/
|
||||
protected retrieveProvider_(id: string): AbstractNotificationService<never> {
|
||||
try {
|
||||
return this.container_[`noti_${id}`]
|
||||
} catch (err) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`Could not find a notification provider with id: ${id}.`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an event by relaying the event data to the subscribing providers.
|
||||
* The result of the notification send will be persisted in the database in
|
||||
* order to allow for resends. Will log any errors that are encountered.
|
||||
* @param eventName - the event to handle
|
||||
* @param data - the data the event was sent with
|
||||
* @return the result of notification subscribed
|
||||
*/
|
||||
handleEvent(
|
||||
eventName: string,
|
||||
data: Record<string, unknown>
|
||||
): Promise<void | undefined | Notification[]> {
|
||||
const subs = this.subscribers_[eventName]
|
||||
if (!subs) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
if (data["no_notification"] === true) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
subs.map(async (providerId) => {
|
||||
return this.send(eventName, data, providerId).catch((err) => {
|
||||
console.log(err)
|
||||
this.logger_.warn(
|
||||
`An error occured while ${providerId} was processing a notification for ${eventName}: ${err.message}`
|
||||
)
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a notification, by calling the given provider's sendNotification
|
||||
* method. Persists the Notification in the database.
|
||||
* @param event - the name of the event
|
||||
* @param eventData - the data the event was sent with
|
||||
* @param providerId - the provider that should hande the event.
|
||||
* @return the created notification
|
||||
*/
|
||||
async send(
|
||||
event: string,
|
||||
eventData: Record<string, unknown>,
|
||||
providerId: string
|
||||
): Promise<Notification | undefined> {
|
||||
return await this.atomicPhase_(async (transactionManager) => {
|
||||
const provider = this.retrieveProvider_(providerId)
|
||||
const result = await provider.sendNotification(
|
||||
event,
|
||||
eventData,
|
||||
this.attachmentGenerator_
|
||||
)
|
||||
|
||||
if (!result) {
|
||||
return
|
||||
}
|
||||
|
||||
const { to, data } = result
|
||||
const notiRepo = transactionManager.getCustomRepository(
|
||||
this.notificationRepository_
|
||||
)
|
||||
|
||||
const [resource_type] = event.split(".") as string[]
|
||||
const resource_id = eventData.id as string
|
||||
const customer_id = (eventData.customer_id as string) || null
|
||||
|
||||
const created = notiRepo.create({
|
||||
resource_type,
|
||||
resource_id,
|
||||
customer_id,
|
||||
to,
|
||||
data,
|
||||
event_name: event,
|
||||
provider_id: providerId,
|
||||
})
|
||||
|
||||
return await notiRepo.save(created)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Resends a notification by retrieving a prior notification and calling the
|
||||
* underlying provider's resendNotification method.
|
||||
* @param {string} id - the id of the notification
|
||||
* @param {object} config - any configuration that might override the previous
|
||||
* send
|
||||
* @return {Notification} the newly created notification
|
||||
*/
|
||||
async resend(
|
||||
id: string,
|
||||
config: FindConfig<Notification> = {}
|
||||
): Promise<Notification> {
|
||||
return await this.atomicPhase_(async (transactionManager) => {
|
||||
const notification = await this.retrieve(id)
|
||||
|
||||
const provider = this.retrieveProvider_(notification.provider_id)
|
||||
const { to, data } = await provider.resendNotification(
|
||||
notification,
|
||||
config,
|
||||
this.attachmentGenerator_
|
||||
)
|
||||
|
||||
const notiRepo = transactionManager.getCustomRepository(
|
||||
this.notificationRepository_
|
||||
)
|
||||
const created = notiRepo.create({
|
||||
...notification,
|
||||
to,
|
||||
data,
|
||||
parent_id: id,
|
||||
})
|
||||
|
||||
return notiRepo.save(created)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default NotificationService
|
||||
Reference in New Issue
Block a user