summaryrefslogtreecommitdiff
path: root/lib/mail/mailer.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mail/mailer.ts')
-rw-r--r--lib/mail/mailer.ts133
1 files changed, 126 insertions, 7 deletions
diff --git a/lib/mail/mailer.ts b/lib/mail/mailer.ts
index 329e2e52..61201e99 100644
--- a/lib/mail/mailer.ts
+++ b/lib/mail/mailer.ts
@@ -15,18 +15,137 @@ const transporter = nodemailer.createTransport({
},
});
-// 템플릿 로더 함수 - 단순화된 버전
+// 헬퍼 함수들 등록
+function registerHandlebarsHelpers() {
+ // i18next 헬퍼 등록
+ handlebars.registerHelper('t', function(key: string, options: { hash?: Record<string, unknown> }) {
+ // options.hash에는 Handlebars에서 넘긴 named parameter들이 들어있음
+ return i18next.t(key, options.hash || {});
+ });
+
+ // eq 헬퍼 등록 - 두 값을 비교 (블록 헬퍼)
+ handlebars.registerHelper('eq', function(a: any, b: any, options: any) {
+ if (a === b) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ // 기타 유용한 헬퍼들
+ handlebars.registerHelper('ne', function(a: any, b: any, options: any) {
+ if (a !== b) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ handlebars.registerHelper('gt', function(a: any, b: any, options: any) {
+ if (a > b) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ handlebars.registerHelper('gte', function(a: any, b: any, options: any) {
+ if (a >= b) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ handlebars.registerHelper('lt', function(a: any, b: any, options: any) {
+ if (a < b) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ handlebars.registerHelper('lte', function(a: any, b: any, options: any) {
+ if (a <= b) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ // and 헬퍼 - 모든 조건이 true인지 확인 (블록 헬퍼)
+ handlebars.registerHelper('and', function(...args: any[]) {
+ // 마지막 인자는 Handlebars 옵션
+ const options = args[args.length - 1];
+ const values = args.slice(0, -1);
+
+ if (values.every(Boolean)) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ // or 헬퍼 - 하나라도 true인지 확인 (블록 헬퍼)
+ handlebars.registerHelper('or', function(...args: any[]) {
+ // 마지막 인자는 Handlebars 옵션
+ const options = args[args.length - 1];
+ const values = args.slice(0, -1);
+
+ if (values.some(Boolean)) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ // not 헬퍼 - 값 반전 (블록 헬퍼)
+ handlebars.registerHelper('not', function(value: any, options: any) {
+ if (!value) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ // formatDate 헬퍼 - 날짜 포맷팅
+ handlebars.registerHelper('formatDate', function(date: string | Date, format: string = 'YYYY-MM-DD') {
+ if (!date) return '';
+ const dateObj = new Date(date);
+ if (isNaN(dateObj.getTime())) return '';
+
+ // 간단한 날짜 포맷팅 (더 복잡한 경우 moment.js나 date-fns 사용)
+ const year = dateObj.getFullYear();
+ const month = String(dateObj.getMonth() + 1).padStart(2, '0');
+ const day = String(dateObj.getDate()).padStart(2, '0');
+
+ return format
+ .replace('YYYY', String(year))
+ .replace('MM', month)
+ .replace('DD', day);
+ });
+
+ // formatNumber 헬퍼 - 숫자 포맷팅
+ handlebars.registerHelper('formatNumber', function(number: number, locale: string = 'ko-KR') {
+ if (typeof number !== 'number') return number;
+ return new Intl.NumberFormat(locale).format(number);
+ });
+}
+
+// 헬퍼 등록 실행
+registerHandlebarsHelpers();
+
+// 템플릿 로더 함수
function loadTemplate(templateName: string, data: Record<string, unknown>) {
const templatePath = path.join(process.cwd(), 'lib', 'mail', 'templates', `${templateName}.hbs`);
+
+ if (!fs.existsSync(templatePath)) {
+ throw new Error(`Template not found: ${templatePath}`);
+ }
+
const source = fs.readFileSync(templatePath, 'utf8');
const template = handlebars.compile(source);
return template(data);
}
-// i18next 헬퍼 등록
-handlebars.registerHelper('t', function(key: string, options: { hash?: Record<string, unknown> }) {
- // options.hash에는 Handlebars에서 넘긴 named parameter들이 들어있음
- return i18next.t(key, options.hash || {});
-});
-
export { transporter, loadTemplate }; \ No newline at end of file