@comasoft/nestjs 0.2.26 → 0.2.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,4 +7,3 @@ export * from './category.entity';
7
7
  export * from './role.entity';
8
8
  export * from './comment.entity';
9
9
  export * from './notification.entity';
10
- export * from './notification-recipient.entity';
@@ -1 +1 @@
1
- var e=this&&this.__createBinding||(Object.create?function(e,t,r,i){void 0===i&&(i=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,o)}:function(e,t,r,i){void 0===i&&(i=r),e[i]=t[r]}),t=this&&this.__exportStar||function(t,r){for(var i in t)"default"===i||Object.prototype.hasOwnProperty.call(r,i)||e(r,t,i)};Object.defineProperty(exports,"__esModule",{value:!0}),t(require("./logs-audit.entity"),exports),t(require("./logs-event.entity"),exports),t(require("./file.entity"),exports),t(require("./config.entity"),exports),t(require("./like.entity"),exports),t(require("./category.entity"),exports),t(require("./role.entity"),exports),t(require("./comment.entity"),exports),t(require("./notification.entity"),exports),t(require("./notification-recipient.entity"),exports);
1
+ var e=this&&this.__createBinding||(Object.create?function(e,t,r,i){void 0===i&&(i=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,o)}:function(e,t,r,i){void 0===i&&(i=r),e[i]=t[r]}),t=this&&this.__exportStar||function(t,r){for(var i in t)"default"===i||Object.prototype.hasOwnProperty.call(r,i)||e(r,t,i)};Object.defineProperty(exports,"__esModule",{value:!0}),t(require("./logs-audit.entity"),exports),t(require("./logs-event.entity"),exports),t(require("./file.entity"),exports),t(require("./config.entity"),exports),t(require("./like.entity"),exports),t(require("./category.entity"),exports),t(require("./role.entity"),exports),t(require("./comment.entity"),exports),t(require("./notification.entity"),exports);
@@ -1,22 +1,25 @@
1
- import { NOTIFICATION_STATUS } from '../../enums.common';
2
- import { NotificationRecipient } from './notification-recipient.entity';
3
- declare class Relations {
4
- recipients: NotificationRecipient[];
5
- }
6
- export declare class Notification extends Relations {
1
+ import { NOTIFICATION_STATUS, NOTIFICATION_TYPE } from '../../enums.common';
2
+ export declare class Notification {
7
3
  id: number;
8
- type: string;
9
4
  batch_id: string;
10
- template_key: string;
11
5
  status: NOTIFICATION_STATUS;
12
- sender: string;
6
+ type: NOTIFICATION_TYPE;
7
+ user_id: number;
8
+ recipient: string;
9
+ template_key: string;
10
+ event_type: string;
11
+ event_id: number;
13
12
  title: string;
14
13
  content: string;
14
+ sender: string;
15
+ variables: Record<string, any>;
15
16
  meta: Record<string, any>;
16
17
  scheduled_at: Date;
17
18
  sent_at: Date;
19
+ read_at: Date;
20
+ failed_at: Date;
21
+ reason_failed: string;
18
22
  created_at: Date;
19
23
  updated_at: Date;
20
24
  deleted_at: Date;
21
25
  }
22
- export {};
@@ -1 +1 @@
1
- var t=this&&this.__decorate||function(t,e,o,i){var n,a=arguments.length,r=a<3?e:null===i?i=Object.getOwnPropertyDescriptor(e,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(t,e,o,i);else for(var p=t.length-1;p>=0;p--)(n=t[p])&&(r=(a<3?n(r):a>3?n(e,o,r):n(e,o))||r);return a>3&&r&&Object.defineProperty(e,o,r),r},e=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(exports,"__esModule",{value:!0}),exports.Notification=void 0;const o=require("typeorm"),i=require("../../enums.common"),n=require("./notification-recipient.entity");class Relations{}t([(0,o.OneToMany)(()=>n.NotificationRecipient,t=>t.notification),e("design:type",Array)],Relations.prototype,"recipients",void 0);let a=class Notification extends Relations{};exports.Notification=a,t([(0,o.PrimaryGeneratedColumn)({name:"id",primaryKeyConstraintName:"PK_notifications"}),e("design:type",Number)],a.prototype,"id",void 0),t([(0,o.Column)("varchar",{length:25}),e("design:type",String)],a.prototype,"type",void 0),t([(0,o.Column)("varchar",{length:50,nullable:!0}),e("design:type",String)],a.prototype,"batch_id",void 0),t([(0,o.Column)("varchar",{length:50}),e("design:type",String)],a.prototype,"template_key",void 0),t([(0,o.Column)("enum",{enum:i.NOTIFICATION_STATUS}),e("design:type",String)],a.prototype,"status",void 0),t([(0,o.Column)("varchar",{length:50,nullable:!0}),e("design:type",String)],a.prototype,"sender",void 0),t([(0,o.Column)("varchar",{length:100,nullable:!0}),e("design:type",String)],a.prototype,"title",void 0),t([(0,o.Column)("text",{nullable:!0}),e("design:type",String)],a.prototype,"content",void 0),t([(0,o.Column)("jsonb",{nullable:!0}),e("design:type",Object)],a.prototype,"meta",void 0),t([(0,o.Column)("timestamptz",{nullable:!0}),e("design:type",Date)],a.prototype,"scheduled_at",void 0),t([(0,o.Column)("timestamptz",{nullable:!0}),e("design:type",Date)],a.prototype,"sent_at",void 0),t([(0,o.CreateDateColumn)({type:"timestamptz"}),e("design:type",Date)],a.prototype,"created_at",void 0),t([(0,o.UpdateDateColumn)({type:"timestamptz"}),e("design:type",Date)],a.prototype,"updated_at",void 0),t([(0,o.DeleteDateColumn)({type:"timestamptz"}),e("design:type",Date)],a.prototype,"deleted_at",void 0),exports.Notification=a=t([(0,o.Entity)("notifications"),(0,o.Index)("IDX_notifications",["id"],{where:"deleted_at IS NULL"}),(0,o.Index)("IDX_notifications_status",["status"])],a);
1
+ var e=this&&this.__decorate||function(e,t,n,o){var i,a=arguments.length,l=a<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,n):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,n,o);else for(var p=e.length-1;p>=0;p--)(i=e[p])&&(l=(a<3?i(l):a>3?i(t,n,l):i(t,n))||l);return a>3&&l&&Object.defineProperty(t,n,l),l},t=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)};Object.defineProperty(exports,"__esModule",{value:!0}),exports.Notification=void 0;const n=require("typeorm"),o=require("../../enums.common");let i=class Notification{};exports.Notification=i,e([(0,n.PrimaryGeneratedColumn)({name:"id",primaryKeyConstraintName:"PK_notifications"}),t("design:type",Number)],i.prototype,"id",void 0),e([(0,n.Column)("varchar",{length:50,nullable:!0,comment:"배치 ID (1:N 발송 시 동일한 ID, null = 1:1 발송)"}),t("design:type",String)],i.prototype,"batch_id",void 0),e([(0,n.Column)("enum",{enum:o.NOTIFICATION_STATUS}),t("design:type",String)],i.prototype,"status",void 0),e([(0,n.Column)("varchar",{length:25,comment:Object.values(o.NOTIFICATION_TYPE).join(" | ")}),t("design:type",String)],i.prototype,"type",void 0),e([(0,n.Column)("int",{nullable:!0,comment:"사용자 ID (null = 배치 마스터)"}),t("design:type",Number)],i.prototype,"user_id",void 0),e([(0,n.Column)("varchar",{length:100,nullable:!0,comment:"수신자 주소 (email, phone 등)"}),t("design:type",String)],i.prototype,"recipient",void 0),e([(0,n.Column)("varchar",{length:50,comment:"템플릿 키"}),t("design:type",String)],i.prototype,"template_key",void 0),e([(0,n.Column)("varchar",{length:50,nullable:!0,comment:"이벤트 타입 (comment, pairing, notice 등)"}),t("design:type",String)],i.prototype,"event_type",void 0),e([(0,n.Column)("int",{nullable:!0,comment:"이벤트 대상 ID (post_id, schedule_id 등)"}),t("design:type",Number)],i.prototype,"event_id",void 0),e([(0,n.Column)("varchar",{length:100,nullable:!0,comment:"제목 (in_app, email에서 사용)"}),t("design:type",String)],i.prototype,"title",void 0),e([(0,n.Column)("text",{nullable:!0,comment:"내용"}),t("design:type",String)],i.prototype,"content",void 0),e([(0,n.Column)("varchar",{length:50,nullable:!0,comment:"발신자 (email: noreply@example.com, sms: 1234)"}),t("design:type",String)],i.prototype,"sender",void 0),e([(0,n.Column)("jsonb",{nullable:!0,comment:"템플릿 변수"}),t("design:type",Object)],i.prototype,"variables",void 0),e([(0,n.Column)("jsonb",{nullable:!0,comment:"추가 메타데이터 (url, image_url, 배치 정보 등)"}),t("design:type",Object)],i.prototype,"meta",void 0),e([(0,n.Column)("timestamptz",{nullable:!0,comment:"예약 발송 시각"}),t("design:type",Date)],i.prototype,"scheduled_at",void 0),e([(0,n.Column)("timestamptz",{nullable:!0,comment:"실제 발송 시각"}),t("design:type",Date)],i.prototype,"sent_at",void 0),e([(0,n.Column)("timestamptz",{nullable:!0,comment:"읽은 시각 (in_app만 사용)"}),t("design:type",Date)],i.prototype,"read_at",void 0),e([(0,n.Column)("timestamptz",{nullable:!0,comment:"발송 실패 시각"}),t("design:type",Date)],i.prototype,"failed_at",void 0),e([(0,n.Column)("varchar",{length:255,nullable:!0,comment:"실패 사유"}),t("design:type",String)],i.prototype,"reason_failed",void 0),e([(0,n.CreateDateColumn)({type:"timestamptz"}),t("design:type",Date)],i.prototype,"created_at",void 0),e([(0,n.UpdateDateColumn)({type:"timestamptz"}),t("design:type",Date)],i.prototype,"updated_at",void 0),e([(0,n.DeleteDateColumn)({type:"timestamptz"}),t("design:type",Date)],i.prototype,"deleted_at",void 0),exports.Notification=i=e([(0,n.Entity)("notifications"),(0,n.Index)("IDX_notifications",["id"],{where:"deleted_at IS NULL"}),(0,n.Index)("IDX_notifications_status",["status"]),(0,n.Index)("IDX_notifications_user_type",["user_id","type","created_at"]),(0,n.Index)("IDX_notifications_user_id",["user_id"],{where:"user_id IS NOT NULL"}),(0,n.Index)("IDX_notifications_batch",["batch_id"],{where:"batch_id IS NOT NULL"}),(0,n.Index)("IDX_notifications_event",["event_type","event_id"],{where:"event_type IS NOT NULL AND event_id IS NOT NULL"})],i);
@@ -54,6 +54,15 @@ export declare enum NOTIFICATION_STATUS {
54
54
  READ = "read",
55
55
  FAILED = "failed"
56
56
  }
57
+ export declare enum NOTIFICATION_TYPE {
58
+ IN_APP = "in_app",
59
+ WEB_PUSH = "web_push",
60
+ MOBILE_PUSH = "mobile_push",
61
+ EMAIL = "email",
62
+ SMS = "sms",
63
+ KAKAO = "kakao",
64
+ SLACK = "slack"
65
+ }
57
66
  export declare enum LIKE_TYPE {
58
67
  LIKE = "like",
59
68
  DISLIKE = "dislike",
@@ -1 +1 @@
1
- var e,o,t,E,n,p,T,i;Object.defineProperty(exports,"__esModule",{value:!0}),exports.LIKE_TYPE=exports.NOTIFICATION_STATUS=exports.FILE_STORAGE_TYPE=exports.FILE_STATUS=exports.AUDIT_ACTION=exports.DEVICE_TYPE=exports.MIME_TYPE=exports.FILE_TYPE=void 0,function(e){e.IMAGE="IMAGE",e.VIDEO="VIDEO",e.DOCUMENT="DOCUMENT",e.AUDIO="AUDIO",e.OTHER="OTHER"}(e||(exports.FILE_TYPE=e={})),function(e){e.JPEG="image/jpeg",e.PNG="image/png",e.GIF="image/gif",e.PDF="application/pdf",e.DOC="application/msword",e.DOCX="application/vnd.openxmlformats-officedocument.wordprocessingml.document",e.XLS="application/vnd.ms-excel",e.XLSX="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",e.PPT="application/vnd.ms-powerpoint",e.PPTX="application/vnd.openxmlformats-officedocument.presentationml.presentation",e.TXT="text/plain",e.HTML="text/html",e.CSV="text/csv"}(o||(exports.MIME_TYPE=o={})),function(e){e.ANDROID="android",e.IOS="ios",e.PC="pc",e.MAC="mac",e.OTHER="other"}(t||(exports.DEVICE_TYPE=t={})),function(e){e.CREATE="create",e.READ="read",e.UPDATE="update",e.DELETE="delete",e.DOWNLOAD="download"}(E||(exports.AUDIT_ACTION=E={})),function(e){e.PENDING="pending",e.COMPLETED="completed",e.FAILED="failed",e.DELETED="deleted"}(n||(exports.FILE_STATUS=n={})),function(e){e.AWS="aws",e.AWS_LEGACY="aws_legacy",e.NCP="ncp",e.REMOTE="remote",e.LOCAL="local",e.OTHER="other"}(p||(exports.FILE_STORAGE_TYPE=p={})),function(e){e.PENDING="pending",e.SENT="sent",e.READ="read",e.FAILED="failed"}(T||(exports.NOTIFICATION_STATUS=T={})),function(e){e.LIKE="like",e.DISLIKE="dislike",e.NONE="none"}(i||(exports.LIKE_TYPE=i={}));
1
+ var e,o,t,E,n,p,T,i,I;Object.defineProperty(exports,"__esModule",{value:!0}),exports.LIKE_TYPE=exports.NOTIFICATION_TYPE=exports.NOTIFICATION_STATUS=exports.FILE_STORAGE_TYPE=exports.FILE_STATUS=exports.AUDIT_ACTION=exports.DEVICE_TYPE=exports.MIME_TYPE=exports.FILE_TYPE=void 0,function(e){e.IMAGE="IMAGE",e.VIDEO="VIDEO",e.DOCUMENT="DOCUMENT",e.AUDIO="AUDIO",e.OTHER="OTHER"}(e||(exports.FILE_TYPE=e={})),function(e){e.JPEG="image/jpeg",e.PNG="image/png",e.GIF="image/gif",e.PDF="application/pdf",e.DOC="application/msword",e.DOCX="application/vnd.openxmlformats-officedocument.wordprocessingml.document",e.XLS="application/vnd.ms-excel",e.XLSX="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",e.PPT="application/vnd.ms-powerpoint",e.PPTX="application/vnd.openxmlformats-officedocument.presentationml.presentation",e.TXT="text/plain",e.HTML="text/html",e.CSV="text/csv"}(o||(exports.MIME_TYPE=o={})),function(e){e.ANDROID="android",e.IOS="ios",e.PC="pc",e.MAC="mac",e.OTHER="other"}(t||(exports.DEVICE_TYPE=t={})),function(e){e.CREATE="create",e.READ="read",e.UPDATE="update",e.DELETE="delete",e.DOWNLOAD="download"}(E||(exports.AUDIT_ACTION=E={})),function(e){e.PENDING="pending",e.COMPLETED="completed",e.FAILED="failed",e.DELETED="deleted"}(n||(exports.FILE_STATUS=n={})),function(e){e.AWS="aws",e.AWS_LEGACY="aws_legacy",e.NCP="ncp",e.REMOTE="remote",e.LOCAL="local",e.OTHER="other"}(p||(exports.FILE_STORAGE_TYPE=p={})),function(e){e.PENDING="pending",e.SENT="sent",e.READ="read",e.FAILED="failed"}(T||(exports.NOTIFICATION_STATUS=T={})),function(e){e.IN_APP="in_app",e.WEB_PUSH="web_push",e.MOBILE_PUSH="mobile_push",e.EMAIL="email",e.SMS="sms",e.KAKAO="kakao",e.SLACK="slack"}(i||(exports.NOTIFICATION_TYPE=i={})),function(e){e.LIKE="like",e.DISLIKE="dislike",e.NONE="none"}(I||(exports.LIKE_TYPE=I={}));
@@ -1,7 +1,9 @@
1
- import { NotificationOptions, NotificationSendService, NotificationService } from '../../notifications';
1
+ import { NotificationOptions, NotificationSendService } from '../../notifications';
2
2
  export declare class EventNotificationService {
3
- private readonly notificationService;
4
3
  private readonly notificationSendService;
5
- constructor(notificationService: NotificationService, notificationSendService: NotificationSendService);
6
- send(notification: NotificationOptions): Promise<void>;
4
+ constructor(notificationSendService: NotificationSendService);
5
+ send(notification: NotificationOptions): Promise<{
6
+ batch_id: string;
7
+ }>;
8
+ private generateBatchId;
7
9
  }
@@ -1 +1 @@
1
- var e=this&&this.__decorate||function(e,t,i,a){var n,c=arguments.length,s=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,i):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,i,a);else for(var l=e.length-1;l>=0;l--)(n=e[l])&&(s=(c<3?n(s):c>3?n(t,i,s):n(t,i))||s);return c>3&&s&&Object.defineProperty(t,i,s),s},t=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)},i=this&&this.__awaiter||function(e,t,i,a){return new(i||(i=Promise))(function(n,c){function fulfilled(e){try{step(a.next(e))}catch(e){c(e)}}function rejected(e){try{step(a.throw(e))}catch(e){c(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i(function(t){t(e)})}(e.value).then(fulfilled,rejected)}step((a=a.apply(e,t||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.EventNotificationService=void 0;const a=require("@nestjs/common"),n=require("../../notifications");let c=class EventNotificationService{constructor(e,t){this.notificationService=e,this.notificationSendService=t}send(e){return i(this,void 0,void 0,function*(){if(null==e?void 0:e.web){yield this.notificationSendService.send({type:"web",recipients:e.web.recipients,template_key:e.web.template_key,variables:e.web.variables,meta:e.web.meta})}if(null==e?void 0:e.email){yield this.notificationService.create({type:"email",template_key:e.email.template_key,recipients:e.email.recipients,variables:e.email.variables});yield this.notificationSendService.send({type:"email",recipients:e.email.recipients,subject:e.email.subject,body:e.email.body,template_key:e.email.template_key,variables:e.email.variables})}if(null==e?void 0:e.kakao){yield this.notificationService.create({type:"kakao",template_key:e.kakao.template_key,recipients:e.kakao.recipients,variables:e.kakao.variables});yield this.notificationSendService.send({type:"kakao",recipients:e.kakao.recipients,template_key:e.kakao.template_key,variables:e.kakao.variables})}if(null==e?void 0:e.sms){yield this.notificationService.create({type:"sms",template_key:e.sms.template_key,recipients:e.sms.recipients,variables:e.sms.variables});yield this.notificationSendService.send({type:"sms",recipients:e.sms.recipients,content:e.sms.content,template_key:e.sms.template_key,variables:e.sms.variables})}if(null==e?void 0:e.slack){yield this.notificationService.create({type:"slack",template_key:e.slack.template_key,recipients:[{user_id:0,recipient:e.slack.channel}],variables:e.slack.variables});yield this.notificationSendService.send({type:"slack",channel:e.slack.channel,content:e.slack.content,template_key:e.slack.template_key,variables:e.slack.variables})}})}};exports.EventNotificationService=c,exports.EventNotificationService=c=e([(0,a.Injectable)(),t("design:paramtypes",[n.NotificationService,n.NotificationSendService])],c);
1
+ var e=this&&this.__decorate||function(e,t,i,n){var a,s=arguments.length,c=s<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,i):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)c=Reflect.decorate(e,t,i,n);else for(var l=e.length-1;l>=0;l--)(a=e[l])&&(c=(s<3?a(c):s>3?a(t,i,c):a(t,i))||c);return s>3&&c&&Object.defineProperty(t,i,c),c},t=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)},i=this&&this.__awaiter||function(e,t,i,n){return new(i||(i=Promise))(function(a,s){function fulfilled(e){try{step(n.next(e))}catch(e){s(e)}}function rejected(e){try{step(n.throw(e))}catch(e){s(e)}}function step(e){e.done?a(e.value):function adopt(e){return e instanceof i?e:new i(function(t){t(e)})}(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.EventNotificationService=void 0;const n=require("@nestjs/common"),a=require("../../notifications");let s=class EventNotificationService{constructor(e){this.notificationSendService=e}send(e){return i(this,void 0,void 0,function*(){const t=this.generateBatchId();return(null==e?void 0:e.in_app)&&(yield this.notificationSendService.send({batch_id:t,channels:["in_app"],recipients:e.in_app.recipients,title:e.in_app.title,content:e.in_app.content,template_key:e.in_app.template_key,variables:e.in_app.variables,event_type:e.in_app.event_type,event_id:e.in_app.event_id,meta:e.in_app.meta})),(null==e?void 0:e.mobile_push)&&(yield this.notificationSendService.send({batch_id:t,channels:["mobile_push"],recipients:e.mobile_push.recipients,title:e.mobile_push.title,content:e.mobile_push.content,template_key:e.mobile_push.template_key,variables:e.mobile_push.variables,meta:e.mobile_push.meta})),(null==e?void 0:e.web_push)&&(yield this.notificationSendService.send({batch_id:t,channels:["web_push"],recipients:e.web_push.recipients,title:e.web_push.title,content:e.web_push.content,template_key:e.web_push.template_key,variables:e.web_push.variables,meta:e.web_push.meta})),(null==e?void 0:e.email)&&(yield this.notificationSendService.send({batch_id:t,channels:["email"],recipients:e.email.recipients,title:e.email.subject,content:e.email.body,template_key:e.email.template_key,variables:e.email.variables})),(null==e?void 0:e.kakao)&&(yield this.notificationSendService.send({batch_id:t,channels:["kakao"],recipients:e.kakao.recipients,template_key:e.kakao.template_key,variables:e.kakao.variables})),(null==e?void 0:e.sms)&&(yield this.notificationSendService.send({batch_id:t,channels:["sms"],recipients:e.sms.recipients,content:e.sms.content,template_key:e.sms.template_key,variables:e.sms.variables})),(null==e?void 0:e.slack)&&(yield this.notificationSendService.send({batch_id:t,channels:["slack"],recipients:[{user_id:0,recipient:e.slack.channel}],content:e.slack.content,template_key:e.slack.template_key,variables:e.slack.variables})),{batch_id:t}})}generateBatchId(){return`BATCH_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}};exports.EventNotificationService=s,exports.EventNotificationService=s=e([(0,n.Injectable)(),t("design:paramtypes",[a.NotificationSendService])],s);
@@ -7,7 +7,25 @@ export interface NotificationRecipient {
7
7
  meta?: Record<string, any>;
8
8
  }
9
9
  export interface NotificationOptions {
10
- web?: {
10
+ in_app?: {
11
+ recipients: NotificationRecipient[];
12
+ title?: string;
13
+ content?: string;
14
+ template_key?: string;
15
+ variables?: Record<string, any>;
16
+ event_type?: string;
17
+ event_id?: number;
18
+ meta?: Record<string, any>;
19
+ };
20
+ mobile_push?: {
21
+ recipients: NotificationRecipient[];
22
+ title?: string;
23
+ content?: string;
24
+ template_key?: string;
25
+ variables?: Record<string, any>;
26
+ meta?: Record<string, any>;
27
+ };
28
+ web_push?: {
11
29
  recipients: NotificationRecipient[];
12
30
  title?: string;
13
31
  content?: string;
@@ -41,7 +59,7 @@ export interface NotificationOptions {
41
59
  };
42
60
  }
43
61
  export type NotificationPayload = {
44
- type: 'web';
62
+ type: 'in_app';
45
63
  recipients: Array<{
46
64
  recipient: string;
47
65
  user_id: number;
@@ -54,6 +72,32 @@ export type NotificationPayload = {
54
72
  content?: string;
55
73
  template_key?: string;
56
74
  variables?: Record<string, any>;
75
+ event_type?: string;
76
+ event_id?: number;
77
+ meta?: Record<string, any>;
78
+ } | {
79
+ type: 'mobile_push';
80
+ recipients: Array<{
81
+ recipient: string;
82
+ user_id: number;
83
+ variables?: Record<string, any>;
84
+ }>;
85
+ title?: string;
86
+ content?: string;
87
+ template_key?: string;
88
+ variables?: Record<string, any>;
89
+ meta?: Record<string, any>;
90
+ } | {
91
+ type: 'web_push';
92
+ recipients: Array<{
93
+ recipient: string;
94
+ user_id: number;
95
+ variables?: Record<string, any>;
96
+ }>;
97
+ title?: string;
98
+ content?: string;
99
+ template_key?: string;
100
+ variables?: Record<string, any>;
57
101
  meta?: Record<string, any>;
58
102
  } | {
59
103
  type: 'email';
@@ -1 +1 @@
1
- var e=this&&this.__decorate||function(e,i,t,o){var r,c=arguments.length,n=c<3?i:null===o?o=Object.getOwnPropertyDescriptor(i,t):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,i,t,o);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(n=(c<3?r(n):c>3?r(i,t,n):r(i,t))||n);return c>3&&n&&Object.defineProperty(i,t,n),n};Object.defineProperty(exports,"__esModule",{value:!0}),exports.NotificationModule=void 0;const i=require("@nestjs/common"),t=require("@nestjs/typeorm"),o=require("../database/entities"),r=require("./services");let c=class NotificationModule{};exports.NotificationModule=c,exports.NotificationModule=c=e([(0,i.Global)(),(0,i.Module)({imports:[t.TypeOrmModule.forFeature([o.Config,o.Notification,o.NotificationRecipient])],providers:[r.NotificationService,r.NotificationSendService,r.MessageTemplateService,r.EmailService,r.KakaoService,r.SmsService,r.SlackService,r.WebNotificationService],exports:[r.NotificationSendService,r.NotificationService]})],c);
1
+ var e=this&&this.__decorate||function(e,t,i,o){var r,c=arguments.length,a=c<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,i,o);else for(var n=e.length-1;n>=0;n--)(r=e[n])&&(a=(c<3?r(a):c>3?r(t,i,a):r(t,i))||a);return c>3&&a&&Object.defineProperty(t,i,a),a};Object.defineProperty(exports,"__esModule",{value:!0}),exports.NotificationModule=void 0;const t=require("@nestjs/common"),i=require("@nestjs/typeorm"),o=require("../database/entities"),r=require("./services");let c=class NotificationModule{};exports.NotificationModule=c,exports.NotificationModule=c=e([(0,t.Global)(),(0,t.Module)({imports:[i.TypeOrmModule.forFeature([o.Config,o.Notification])],providers:[r.NotificationService,r.NotificationSendService,r.MessageTemplateService,r.EmailService,r.KakaoService,r.SmsService,r.SlackService],exports:[r.NotificationSendService,r.NotificationService]})],c);
@@ -5,4 +5,3 @@ export * from './email.service';
5
5
  export * from './kakao.service';
6
6
  export * from './sms.service';
7
7
  export * from './slack.service';
8
- export * from './web.service';
@@ -1 +1 @@
1
- var e=this&&this.__createBinding||(Object.create?function(e,r,t,i){void 0===i&&(i=t);var o=Object.getOwnPropertyDescriptor(r,t);o&&!("get"in o?!r.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return r[t]}}),Object.defineProperty(e,i,o)}:function(e,r,t,i){void 0===i&&(i=t),e[i]=r[t]}),r=this&&this.__exportStar||function(r,t){for(var i in r)"default"===i||Object.prototype.hasOwnProperty.call(t,i)||e(t,r,i)};Object.defineProperty(exports,"__esModule",{value:!0}),r(require("./notification.service"),exports),r(require("./notification-send.service"),exports),r(require("./message-template.service"),exports),r(require("./email.service"),exports),r(require("./kakao.service"),exports),r(require("./sms.service"),exports),r(require("./slack.service"),exports),r(require("./web.service"),exports);
1
+ var e=this&&this.__createBinding||(Object.create?function(e,r,t,i){void 0===i&&(i=t);var o=Object.getOwnPropertyDescriptor(r,t);o&&!("get"in o?!r.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return r[t]}}),Object.defineProperty(e,i,o)}:function(e,r,t,i){void 0===i&&(i=t),e[i]=r[t]}),r=this&&this.__exportStar||function(r,t){for(var i in r)"default"===i||Object.prototype.hasOwnProperty.call(t,i)||e(t,r,i)};Object.defineProperty(exports,"__esModule",{value:!0}),r(require("./notification.service"),exports),r(require("./notification-send.service"),exports),r(require("./message-template.service"),exports),r(require("./email.service"),exports),r(require("./kakao.service"),exports),r(require("./sms.service"),exports),r(require("./slack.service"),exports);
@@ -3,7 +3,7 @@ import { Config } from '../../database/entities';
3
3
  export declare class MessageTemplateService {
4
4
  private configRepository;
5
5
  constructor(configRepository: Repository<Config>);
6
- getTemplate(type: 'web' | 'email' | 'sms' | 'slack' | 'kakao', templateKey: string): Promise<any>;
6
+ getTemplate(type: 'in_app' | 'mobile_push' | 'web_push' | 'email' | 'sms' | 'slack' | 'kakao', templateKey: string): Promise<any>;
7
7
  getTemplates(): Promise<Record<string, any>>;
8
8
  updateTemplates(templates: any): Promise<void>;
9
9
  renderTemplate(template: {
@@ -1,26 +1,48 @@
1
- import { DataSource } from 'typeorm';
2
- import { NotificationPayload } from '..';
3
1
  import { EmailService } from './email.service';
4
2
  import { KakaoService } from './kakao.service';
5
3
  import { MessageTemplateService } from './message-template.service';
4
+ import { NotificationService } from './notification.service';
6
5
  import { SlackService } from './slack.service';
7
6
  import { SmsService } from './sms.service';
8
- import { WebNotificationService } from './web.service';
7
+ export interface SendNotificationDto {
8
+ batch_id?: string;
9
+ recipients: Array<{
10
+ user_id: number;
11
+ recipient?: string;
12
+ variables?: Record<string, any>;
13
+ }>;
14
+ channels: Array<'in_app' | 'mobile_push' | 'web_push' | 'email' | 'sms' | 'kakao' | 'slack'>;
15
+ template_key?: string;
16
+ title?: string;
17
+ content?: string;
18
+ variables?: Record<string, any>;
19
+ event_type?: string;
20
+ event_id?: number;
21
+ meta?: Record<string, any>;
22
+ }
9
23
  export declare class NotificationSendService {
24
+ private readonly notificationService;
10
25
  private readonly emailService;
11
26
  private readonly smsService;
12
27
  private readonly kakaoService;
13
28
  private readonly slackService;
14
- private readonly webNotificationService;
15
- private readonly messageTemplateService;
16
- private readonly dataSource;
17
- constructor(emailService: EmailService, smsService: SmsService, kakaoService: KakaoService, slackService: SlackService, webNotificationService: WebNotificationService, messageTemplateService: MessageTemplateService, dataSource: DataSource);
18
- send(payload: NotificationPayload): Promise<any[] | import("@aws-sdk/client-ses").SendEmailCommandOutput | import("resend").CreateEmailResponse | {
29
+ private readonly templateService;
30
+ private readonly logger;
31
+ constructor(notificationService: NotificationService, emailService: EmailService, smsService: SmsService, kakaoService: KakaoService, slackService: SlackService, templateService: MessageTemplateService);
32
+ send(dto: SendNotificationDto): Promise<any[] | {
33
+ batch_id: string;
34
+ total_count: number;
35
+ send_results: any[];
36
+ }>;
37
+ private sendSingle;
38
+ private sendBatch;
39
+ private sendToChannel;
40
+ private sendBatchToChannel;
41
+ resendBatch(batch_id: string, channel: string): Promise<{
19
42
  success: boolean;
43
+ batch_id: string;
44
+ channel: string;
45
+ count: number;
20
46
  }>;
21
- private sendWeb;
22
- private sendEmail;
23
- private sendSms;
24
- private sendKakao;
25
- private sendSlack;
47
+ private renderTemplate;
26
48
  }
@@ -1 +1 @@
1
- var e=this&&this.__decorate||function(e,t,i,r){var s,n=arguments.length,a=n<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,i):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,i,r);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(a=(n<3?s(a):n>3?s(t,i,a):s(t,i))||a);return n>3&&a&&Object.defineProperty(t,i,a),a},t=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)},i=this&&this.__awaiter||function(e,t,i,r){return new(i||(i=Promise))(function(s,n){function fulfilled(e){try{step(r.next(e))}catch(e){n(e)}}function rejected(e){try{step(r.throw(e))}catch(e){n(e)}}function step(e){e.done?s(e.value):function adopt(e){return e instanceof i?e:new i(function(t){t(e)})}(e.value).then(fulfilled,rejected)}step((r=r.apply(e,t||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.NotificationSendService=void 0;const r=require("@nestjs/common"),s=require("typeorm"),n=require("./email.service"),a=require("./kakao.service"),c=require("./message-template.service"),o=require("./slack.service"),l=require("./sms.service"),d=require("./web.service");let m=class NotificationSendService{constructor(e,t,i,r,s,n,a){this.emailService=e,this.smsService=t,this.kakaoService=i,this.slackService=r,this.webNotificationService=s,this.messageTemplateService=n,this.dataSource=a}send(e){return i(this,void 0,void 0,function*(){switch(e.type){case"web":return this.sendWeb(e);case"email":return this.sendEmail(e);case"sms":return this.sendSms(e);case"kakao":return this.sendKakao(e);case"slack":return this.sendSlack(e)}})}sendWeb(e){return i(this,void 0,void 0,function*(){const t=[];for(const i of e.recipients){let r,s;if(e.template_key){const t=yield this.messageTemplateService.getTemplate("web",e.template_key);if(!t)throw new Error("Template not found "+e.template_key);const n=Object.assign(Object.assign({},e.variables),i.variables);r=this.messageTemplateService.renderTemplate(t,n).title||e.title||"",s=this.messageTemplateService.renderTemplate(t,n).content}else{if(!e.title||!e.content)throw new Error("title, content is required");r=e.title,s=e.content}t.push({recipient:i.recipient,user_id:i.user_id,title:r,content:s,variables:i.variables,meta:i.meta||e.meta})}return yield this.webNotificationService.send(Object.assign(Object.assign({},e),{recipients:t}))})}sendEmail(e){return i(this,void 0,void 0,function*(){const t=[];for(const i of e.recipients){let r,s;if(e.template_key){const t=yield this.messageTemplateService.getTemplate("email",e.template_key);if(!t)throw new Error("Template not found "+e.template_key);const n=Object.assign(Object.assign({},e.variables),i.variables);r=this.messageTemplateService.renderTemplate(t,n).content,s=t.subject}else{if(!e.subject||!e.body)throw new Error("subject, body is required");r=e.body,s=e.subject}t.push({recipient:i.recipient,user_id:i.user_id,subject:s,text:r,variables:i.variables})}return yield this.emailService.send(t)})}sendSms(e){return i(this,void 0,void 0,function*(){const t=[];for(const i of e.recipients){let r;if(e.template_key){const t=yield this.messageTemplateService.getTemplate("sms",e.template_key);if(!t)throw new Error("Template not found "+e.template_key);const s=Object.assign(Object.assign({},e.variables),i.variables);r=this.messageTemplateService.renderTemplate(t,s).content}else{if(!e.content)throw new Error("content is required");r=e.content}t.push({recipient:i.recipient,user_id:i.user_id,content:r,variables:i.variables})}return yield this.smsService.send(t)})}sendKakao(e){return i(this,void 0,void 0,function*(){const t=[];for(const i of e.recipients){let r;if(!e.template_key)throw new Error("template_key is required");const s=yield this.messageTemplateService.getTemplate("kakao",e.template_key);if(!s)throw new Error("Template not found "+e.template_key);const n=Object.assign(Object.assign({},e.variables),i.variables);r=this.messageTemplateService.renderTemplate(s,n).content,t.push({recipient:i.recipient,user_id:i.user_id,sender_key:s.sender_key,template_code:s.template_code,message:r})}return yield this.kakaoService.send(t)})}sendSlack(e){return i(this,void 0,void 0,function*(){let t;if(e.template_key){const i=yield this.messageTemplateService.getTemplate("slack",e.template_key);if(!i)throw new Error("Template not found "+e.template_key);t=this.messageTemplateService.renderTemplate(i,e.variables||{}).content}else{if(!e.content)throw new Error("content is required");t=e.content}return[yield this.slackService.send(e.channel,t)]})}};exports.NotificationSendService=m,exports.NotificationSendService=m=e([(0,r.Injectable)(),t("design:paramtypes",[n.EmailService,l.SmsService,a.KakaoService,o.SlackService,d.WebNotificationService,c.MessageTemplateService,s.DataSource])],m);
1
+ var e,t=this&&this.__decorate||function(e,t,i,n){var r,s=arguments.length,a=s<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,i):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,i,n);else for(var o=e.length-1;o>=0;o--)(r=e[o])&&(a=(s<3?r(a):s>3?r(t,i,a):r(t,i))||a);return s>3&&a&&Object.defineProperty(t,i,a),a},i=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)},n=this&&this.__awaiter||function(e,t,i,n){return new(i||(i=Promise))(function(r,s){function fulfilled(e){try{step(n.next(e))}catch(e){s(e)}}function rejected(e){try{step(n.throw(e))}catch(e){s(e)}}function step(e){e.done?r(e.value):function adopt(e){return e instanceof i?e:new i(function(t){t(e)})}(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.NotificationSendService=void 0;const r=require("@nestjs/common"),s=require("../../enums.common"),a=require("./email.service"),o=require("./kakao.service"),c=require("./message-template.service"),l=require("./notification.service"),d=require("./slack.service"),h=require("./sms.service");let p=e=class NotificationSendService{constructor(t,i,n,s,a,o){this.notificationService=t,this.emailService=i,this.smsService=n,this.kakaoService=s,this.slackService=a,this.templateService=o,this.logger=new r.Logger(e.name)}send(e){return n(this,void 0,void 0,function*(){const{title:t,content:i}=yield this.renderTemplate(e);return 1===e.recipients.length?(this.logger.log(`1:1 알림 발송 시작: ${t}`),yield this.sendSingle(Object.assign(Object.assign({},e),{title:t,content:i}))):(this.logger.log(`1:N 배치 알림 발송 시작: ${t} (${e.recipients.length}명)`),yield this.sendBatch(Object.assign(Object.assign({},e),{title:t,content:i})))})}sendSingle(e){return n(this,void 0,void 0,function*(){const t=e.recipients[0],i=[];for(const n of e.channels){let r;try{"in_app"===n?(r=yield this.notificationService.createSingle({user_id:t.user_id,recipient:t.recipient,type:"in_app",template_key:e.template_key,event_type:e.event_type,event_id:e.event_id,title:e.title,content:e.content,variables:Object.assign(Object.assign({},e.variables),t.variables),meta:e.meta}),r.status=s.NOTIFICATION_STATUS.SENT,r.sent_at=new Date,yield this.notificationService.notificationRepository.save(r)):(r=yield this.notificationService.createSingle({user_id:null,recipient:t.recipient,type:n,template_key:e.template_key,event_type:e.event_type,event_id:e.event_id,title:e.title,content:e.content,variables:Object.assign(Object.assign({},e.variables),t.variables),meta:Object.assign(Object.assign({},e.meta),{target_user_id:t.user_id})}),yield this.sendToChannel(n,{recipient:t.recipient,title:e.title,content:e.content,meta:e.meta}),r.status=s.NOTIFICATION_STATUS.SENT,r.sent_at=new Date,yield this.notificationService.notificationRepository.save(r),this.logger.log(`${n} 발송 성공: user_id=${t.user_id}`)),i.push({channel:n,status:"success",notification:r})}catch(e){this.logger.error(`${n} 발송 실패: ${e.message}`,e.stack),r&&(r.status=s.NOTIFICATION_STATUS.FAILED,r.failed_at=new Date,r.reason_failed=e.message,yield this.notificationService.notificationRepository.save(r)),i.push({channel:n,status:"failed",error:e.message})}}return i})}sendBatch(e){return n(this,void 0,void 0,function*(){const{batch_id:t,total_count:i}=yield this.notificationService.createBatch({batch_id:e.batch_id,recipients:e.recipients,type:"in_app",template_key:e.template_key,event_type:e.event_type,event_id:e.event_id,title:e.title,content:e.content,variables:e.variables,meta:e.meta,channels:e.channels});this.logger.log(`배치 생성 완료: ${t} (${i}건)`);const n=e.channels.filter(e=>"in_app"!==e),r=[];for(const i of n)try{yield this.sendBatchToChannel(i,{recipients:e.recipients,title:e.title,content:e.content,meta:e.meta}),yield this.notificationService.notificationRepository.update({batch_id:t,type:i},{status:s.NOTIFICATION_STATUS.SENT,sent_at:new Date}),r.push({channel:i,status:"sent"}),this.logger.log(`${i} 배치 발송 성공: ${e.recipients.length}명`)}catch(e){this.logger.error(`${i} 배치 발송 실패: ${e.message}`,e.stack),yield this.notificationService.notificationRepository.update({batch_id:t,type:i},{status:s.NOTIFICATION_STATUS.FAILED,failed_at:new Date,reason_failed:e.message}),r.push({channel:i,status:"failed",error:e.message})}return{batch_id:t,total_count:i,send_results:r}})}sendToChannel(e,t){return n(this,void 0,void 0,function*(){var i,n,r,s,a;switch(e){case"mobile_push":throw this.logger.warn("mobile_push 채널은 아직 구현되지 않았습니다"),new Error("mobile_push not implemented yet");case"web_push":throw this.logger.warn("web_push 채널은 아직 구현되지 않았습니다"),new Error("web_push not implemented yet");case"email":return yield this.emailService.send([{recipient:t.recipient,user_id:null===(i=t.meta)||void 0===i?void 0:i.target_user_id,subject:t.title,text:t.content}]);case"sms":return yield this.smsService.send([{recipient:t.recipient,user_id:null===(n=t.meta)||void 0===n?void 0:n.target_user_id,message:t.content}]);case"kakao":return yield this.kakaoService.send([{recipient:t.recipient,user_id:null===(r=t.meta)||void 0===r?void 0:r.target_user_id,sender_key:null===(s=t.meta)||void 0===s?void 0:s.sender_key,template_code:null===(a=t.meta)||void 0===a?void 0:a.template_code,message:t.content}]);case"slack":return yield this.slackService.send(t.recipient,t.content);default:throw new Error(`Unknown channel: ${e}`)}})}sendBatchToChannel(e,t){return n(this,void 0,void 0,function*(){switch(e){case"mobile_push":throw this.logger.warn("mobile_push 배치 발송은 아직 구현되지 않았습니다"),new Error("mobile_push batch sending not implemented yet");case"web_push":throw this.logger.warn("web_push 배치 발송은 아직 구현되지 않았습니다"),new Error("web_push batch sending not implemented yet");case"email":{const e=t.recipients.map(e=>({recipient:e.recipient,user_id:e.user_id,subject:t.title,text:t.content})).filter(e=>e.recipient);if(0===e.length)throw new Error("No email addresses provided");return yield this.emailService.send(e)}case"sms":{const e=t.recipients.map(e=>({recipient:e.recipient,user_id:e.user_id,message:t.content})).filter(e=>e.recipient);if(0===e.length)throw new Error("No phone numbers provided");return yield this.smsService.send(e)}case"kakao":{const e=t.recipients.map(e=>{var i,n;return{recipient:e.recipient,user_id:e.user_id,sender_key:null===(i=t.meta)||void 0===i?void 0:i.sender_key,template_code:null===(n=t.meta)||void 0===n?void 0:n.template_code,message:t.content}}).filter(e=>e.recipient);if(0===e.length)throw new Error("No kakao recipients provided");return yield this.kakaoService.send(e)}default:throw new Error(`Batch sending not supported for ${e}`)}})}resendBatch(e,t){return n(this,void 0,void 0,function*(){this.logger.log(`배치 재발송 시작: ${e}, ${t}`);const i=yield this.notificationService.notificationRepository.find({where:{batch_id:e,type:t}});if(0===i.length)throw new Error(`Batch records not found: ${e}, ${t}`);const n=i.map(e=>({user_id:e.user_id,recipient:e.recipient,variables:e.variables})),r=i[0];try{return yield this.sendBatchToChannel(t,{recipients:n,title:r.title,content:r.content,meta:r.meta}),yield this.notificationService.notificationRepository.update({batch_id:e,type:t},{status:s.NOTIFICATION_STATUS.SENT,sent_at:new Date}),this.logger.log(`배치 재발송 성공: ${e}`),{success:!0,batch_id:e,channel:t,count:n.length}}catch(i){throw this.logger.error(`배치 재발송 실패: ${i.message}`,i.stack),yield this.notificationService.notificationRepository.update({batch_id:e,type:t},{status:s.NOTIFICATION_STATUS.FAILED,failed_at:new Date,reason_failed:i.message}),i}})}renderTemplate(e){return n(this,void 0,void 0,function*(){var t;if(e.template_key){const i=e.channels[0],n=yield this.templateService.getTemplate(i,e.template_key);if(!n)throw new Error(`Template not found: ${e.template_key} for ${i}`);const r=Object.assign(Object.assign({},e.variables),(null===(t=e.recipients[0])||void 0===t?void 0:t.variables)||{}),s=this.templateService.renderTemplate(n,r);return{title:s.title||e.title||"",content:s.content}}if(!e.title||!e.content)throw new Error("title and content are required when template_key is not provided");return{title:e.title,content:e.content}})}};exports.NotificationSendService=p,exports.NotificationSendService=p=e=t([(0,r.Injectable)(),i("design:paramtypes",[l.NotificationService,a.EmailService,h.SmsService,o.KakaoService,d.SlackService,c.MessageTemplateService])],p);
@@ -1,39 +1,72 @@
1
- import { ConfigService } from '@nestjs/config';
2
1
  import { Repository } from 'typeorm';
3
- import { Notification, NotificationRecipient } from '../../database/entities';
2
+ import { Notification } from '../../database/entities';
4
3
  import { NOTIFICATION_STATUS } from '../../enums.common';
5
4
  export declare class NotificationService {
6
- private readonly notificationRepository;
7
- private readonly notificationRecipientRepository;
8
- private readonly configService;
9
- constructor(notificationRepository: Repository<Notification>, notificationRecipientRepository: Repository<NotificationRecipient>, configService: ConfigService);
10
- create({ type, template_key, title, content, recipients, variables, meta, }: {
5
+ readonly notificationRepository: Repository<Notification>;
6
+ constructor(notificationRepository: Repository<Notification>);
7
+ createSingle({ user_id, recipient, type, template_key, event_type, event_id, title, content, variables, meta, }: {
8
+ user_id: number;
9
+ recipient?: string;
11
10
  type: string;
12
11
  template_key: string;
12
+ event_type?: string;
13
+ event_id?: number;
13
14
  title?: string;
14
15
  content?: string;
16
+ variables?: Record<string, any>;
17
+ meta?: Record<string, any>;
18
+ }): Promise<{
19
+ user_id: number;
20
+ recipient: string;
21
+ type: any;
22
+ template_key: string;
23
+ event_type: any;
24
+ event_id: number;
25
+ title: string;
26
+ content: string;
27
+ variables: Record<string, any>;
28
+ meta: Record<string, any>;
29
+ status: NOTIFICATION_STATUS.PENDING;
30
+ } & Notification>;
31
+ createBatch({ batch_id, recipients, type, template_key, event_type, event_id, title, content, variables, meta, channels, }: {
32
+ batch_id?: string;
15
33
  recipients: Array<{
16
34
  user_id: number;
17
- recipient: string;
35
+ recipient?: string;
18
36
  variables?: Record<string, any>;
19
37
  }>;
38
+ type: string;
39
+ template_key: string;
40
+ event_type?: string;
41
+ event_id?: number;
42
+ title: string;
43
+ content: string;
20
44
  variables?: Record<string, any>;
21
45
  meta?: Record<string, any>;
46
+ channels?: string[];
22
47
  }): Promise<{
23
- notification: {
24
- type: string;
25
- template_key: string;
26
- title: string;
27
- content: string;
28
- sender: string;
29
- meta: Record<string, any>;
30
- status: NOTIFICATION_STATUS.PENDING;
31
- } & Notification;
32
- recipients: NotificationRecipient[];
48
+ batch_id: string;
49
+ total_count: number;
50
+ notifications: any[];
51
+ }>;
52
+ findByUser(user_id: number, options?: {
53
+ limit?: number;
54
+ offset?: number;
55
+ unread_only?: boolean;
56
+ }): Promise<Notification[]>;
57
+ countUnread(user_id: number): Promise<number>;
58
+ markAsRead(id: number, user_id: number): Promise<import("typeorm").UpdateResult>;
59
+ markAllAsRead(user_id: number): Promise<import("typeorm").UpdateResult>;
60
+ delete(id: number, user_id: number): Promise<import("typeorm").UpdateResult>;
61
+ markBatchAsSent(batch_id: string, channel: string): Promise<import("typeorm").UpdateResult>;
62
+ markBatchAsFailed(batch_id: string, channel: string, reason: string): Promise<import("typeorm").UpdateResult>;
63
+ findBatchMaster(batch_id: string, channel: string): Promise<Notification>;
64
+ findBatchRecipients(batch_id: string): Promise<Notification[]>;
65
+ getBatchStats(batch_id: string): Promise<{
66
+ total: number;
67
+ read: number;
68
+ unread: number;
69
+ read_rate: number;
33
70
  }>;
34
- private getSenderByType;
35
- findAll(): Promise<Notification[]>;
36
- find(id: number): Promise<Notification>;
37
- resend(notification_id: number, user_id?: number): Promise<NotificationRecipient[]>;
38
- markAsRead(notification_id: number, user_id: number): Promise<NotificationRecipient>;
71
+ private generateBatchId;
39
72
  }
@@ -1 +1 @@
1
- var e=this&&this.__decorate||function(e,t,i,n){var o,r=arguments.length,c=r<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,i):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)c=Reflect.decorate(e,t,i,n);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(c=(r<3?o(c):r>3?o(t,i,c):o(t,i))||c);return r>3&&c&&Object.defineProperty(t,i,c),c},t=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)},i=this&&this.__param||function(e,t){return function(i,n){t(i,n,e)}},n=this&&this.__awaiter||function(e,t,i,n){return new(i||(i=Promise))(function(o,r){function fulfilled(e){try{step(n.next(e))}catch(e){r(e)}}function rejected(e){try{step(n.throw(e))}catch(e){r(e)}}function step(e){e.done?o(e.value):function adopt(e){return e instanceof i?e:new i(function(t){t(e)})}(e.value).then(fulfilled,rejected)}step((n=n.apply(e,t||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.NotificationService=void 0;const o=require("@nestjs/common"),r=require("@nestjs/config"),c=require("@nestjs/typeorm"),s=require("typeorm"),a=require("../../database/entities"),f=require("../../enums.common");let u=class NotificationService{constructor(e,t,i){this.notificationRepository=e,this.notificationRecipientRepository=t,this.configService=i}create(e){return n(this,arguments,void 0,function*({type:e,template_key:t,title:i,content:n,recipients:o,variables:r,meta:c}){const s=this.getSenderByType(e),a=yield this.notificationRepository.save({type:e,template_key:t,title:i,content:n,sender:s,meta:c,status:f.NOTIFICATION_STATUS.PENDING}),u=o.map(t=>this.notificationRecipientRepository.create({notification_id:a.id,type:e,user_id:t.user_id,recipient:t.recipient,title:i,content:n,meta:c,variables:t.variables,status:f.NOTIFICATION_STATUS.PENDING}));return yield this.notificationRecipientRepository.save(u),{notification:a,recipients:u}})}getSenderByType(e){switch(e){case"web":return"system";case"email":return this.configService.get("EMAIL_FROM")||"noreply@example.com";case"sms":return this.configService.get("SMS_FROM")||"";case"kakao":return this.configService.get("KAKAO_FROM")||"";case"slack":return this.configService.get("SLACK_CHANNEL")||"";default:return""}}findAll(){return n(this,void 0,void 0,function*(){return this.notificationRepository.find({relations:["recipients"],order:{created_at:"DESC"}})})}find(e){return n(this,void 0,void 0,function*(){return this.notificationRepository.findOne({where:{id:e},relations:["recipients"]})})}resend(e,t){return n(this,void 0,void 0,function*(){const i=yield this.notificationRecipientRepository.find({where:t?{notification_id:e,user_id:t}:{notification_id:e}});for(const e of i)e.status=f.NOTIFICATION_STATUS.PENDING,e.failed_at=null,e.reason_failed=null,yield this.notificationRecipientRepository.save(e);return i})}markAsRead(e,t){return n(this,void 0,void 0,function*(){const i=yield this.notificationRecipientRepository.findOne({where:{notification_id:e,user_id:t}});return i&&(i.status=f.NOTIFICATION_STATUS.READ,i.read_at=new Date,yield this.notificationRecipientRepository.save(i)),i})}};exports.NotificationService=u,exports.NotificationService=u=e([(0,o.Injectable)(),i(0,(0,c.InjectRepository)(a.Notification)),i(1,(0,c.InjectRepository)(a.NotificationRecipient)),t("design:paramtypes",[s.Repository,s.Repository,r.ConfigService])],u);
1
+ var t=this&&this.__decorate||function(t,e,i,n){var r,a=arguments.length,o=a<3?e:null===n?n=Object.getOwnPropertyDescriptor(e,i):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(t,e,i,n);else for(var s=t.length-1;s>=0;s--)(r=t[s])&&(o=(a<3?r(o):a>3?r(e,i,o):r(e,i))||o);return a>3&&o&&Object.defineProperty(e,i,o),o},e=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)},i=this&&this.__param||function(t,e){return function(i,n){e(i,n,t)}},n=this&&this.__awaiter||function(t,e,i,n){return new(i||(i=Promise))(function(r,a){function fulfilled(t){try{step(n.next(t))}catch(t){a(t)}}function rejected(t){try{step(n.throw(t))}catch(t){a(t)}}function step(t){t.done?r(t.value):function adopt(t){return t instanceof i?t:new i(function(e){e(t)})}(t.value).then(fulfilled,rejected)}step((n=n.apply(t,e||[])).next())})};Object.defineProperty(exports,"__esModule",{value:!0}),exports.NotificationService=void 0;const r=require("@nestjs/common"),a=require("@nestjs/typeorm"),o=require("typeorm"),s=require("../../database/entities"),d=require("../../enums.common");let c=class NotificationService{constructor(t){this.notificationRepository=t}createSingle(t){return n(this,arguments,void 0,function*({user_id:t,recipient:e,type:i,template_key:n,event_type:r,event_id:a,title:o,content:s,variables:c,meta:u}){return yield this.notificationRepository.save({user_id:t,recipient:e,type:i,template_key:n,event_type:r,event_id:a,title:o,content:s,variables:c,meta:u,status:d.NOTIFICATION_STATUS.PENDING})})}createBatch(t){return n(this,arguments,void 0,function*({batch_id:t,recipients:e,type:i,template_key:n,event_type:r,event_id:a,title:o,content:s,variables:c,meta:u,channels:p=["in_app","mobile_push"]}){const l=t||this.generateBatchId(),_=[];for(const t of p){const i=e.map(e=>({user_id:e.user_id,recipient:e.recipient,type:t,template_key:n,event_type:r,event_id:a,title:o,content:s,variables:Object.assign(Object.assign({},c),e.variables),meta:u,batch_id:l,status:"in_app"===t?d.NOTIFICATION_STATUS.SENT:d.NOTIFICATION_STATUS.PENDING,sent_at:"in_app"===t?new Date:null}));_.push(...i)}const f=yield this.notificationRepository.save(_);return{batch_id:l,total_count:f.length,notifications:f}})}findByUser(t,e){return n(this,void 0,void 0,function*(){const i=this.notificationRepository.createQueryBuilder("n").where("n.user_id = :user_id",{user_id:t}).andWhere("n.type = :type",{type:"in_app"}).andWhere("n.deleted_at IS NULL");return(null==e?void 0:e.unread_only)&&i.andWhere("n.read_at IS NULL"),i.orderBy("n.created_at","DESC").limit((null==e?void 0:e.limit)||20).offset((null==e?void 0:e.offset)||0),yield i.getMany()})}countUnread(t){return n(this,void 0,void 0,function*(){return yield this.notificationRepository.count({where:{user_id:t,type:"in_app",read_at:(0,o.IsNull)(),deleted_at:(0,o.IsNull)()}})})}markAsRead(t,e){return n(this,void 0,void 0,function*(){return yield this.notificationRepository.update({id:t,user_id:e,type:"in_app"},{status:d.NOTIFICATION_STATUS.READ,read_at:new Date})})}markAllAsRead(t){return n(this,void 0,void 0,function*(){return yield this.notificationRepository.update({user_id:t,type:"in_app",read_at:(0,o.IsNull)()},{status:d.NOTIFICATION_STATUS.READ,read_at:new Date})})}delete(t,e){return n(this,void 0,void 0,function*(){return yield this.notificationRepository.softDelete({id:t,user_id:e,type:"in_app"})})}markBatchAsSent(t,e){return n(this,void 0,void 0,function*(){return yield this.notificationRepository.update({batch_id:t,type:e,user_id:(0,o.IsNull)()},{status:d.NOTIFICATION_STATUS.SENT,sent_at:new Date})})}markBatchAsFailed(t,e,i){return n(this,void 0,void 0,function*(){return yield this.notificationRepository.update({batch_id:t,type:e,user_id:(0,o.IsNull)()},{status:d.NOTIFICATION_STATUS.FAILED,failed_at:new Date,reason_failed:i})})}findBatchMaster(t,e){return n(this,void 0,void 0,function*(){return yield this.notificationRepository.findOne({where:{batch_id:t,type:e,user_id:(0,o.IsNull)()}})})}findBatchRecipients(t){return n(this,void 0,void 0,function*(){return yield this.notificationRepository.find({where:{batch_id:t,type:"in_app",user_id:(0,o.Not)((0,o.IsNull)())},order:{created_at:"DESC"}})})}getBatchStats(t){return n(this,void 0,void 0,function*(){const e=yield this.notificationRepository.createQueryBuilder("n").select("COUNT(*)","total").addSelect("COUNT(n.read_at)","read").addSelect("COUNT(*) - COUNT(n.read_at)","unread").addSelect("ROUND(COUNT(n.read_at) * 100.0 / COUNT(*), 2)","read_rate").where("n.batch_id = :batch_id",{batch_id:t}).andWhere("n.type = :type",{type:"in_app"}).andWhere("n.user_id IS NOT NULL").getRawOne();return{total:parseInt(e.total),read:parseInt(e.read),unread:parseInt(e.unread),read_rate:parseFloat(e.read_rate)}})}generateBatchId(){return`BATCH_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}};exports.NotificationService=c,exports.NotificationService=c=t([(0,r.Injectable)(),i(0,(0,a.InjectRepository)(s.Notification)),e("design:paramtypes",[o.Repository])],c);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comasoft/nestjs",
3
- "version": "0.2.26",
3
+ "version": "0.2.27",
4
4
  "description": "",
5
5
  "private": false,
6
6
  "exports": {