fiberx-backend-toolkit 0.0.77 → 0.0.78

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.
@@ -60,6 +60,8 @@ export declare const DEFAULT_TOTP_DIGITS = 6;
60
60
  export declare const DEFAULT_TOTP_WINDOW = 1;
61
61
  export declare const DEFAULT_RBAC_CACHE_KEY = "RBAC_SNAPSHOT";
62
62
  export declare const DEFAULT_RBAC_CACHE_TTL: number;
63
+ export declare const DEFAULT_MAILER_CACHE_KEY = "MAILER_SNAPSHOT";
64
+ export declare const DEFAULT_MAILER_CACHE_TTL: number;
63
65
  export declare const EMAIL_ENQUEUE_TYPES_FILE_NAME = "types/email_enqueue_type.generated.ts";
64
66
  export declare const EMAIL_ENQUEUE_UTIL_FILE_NAME = "utils/email_enqueue_util.generated.ts";
65
67
  export declare const CONTENT_CACHE_TTL_KEY = "CONTENT_CACHE_TTL";
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DEFAULT_CONTENT_CACHE_TTL = exports.DEFAULT_CONTENT_LANG = exports.DEFAULT_CONTENT_URL = exports.CONTENT_LANG_KEY = exports.CONTENT_URL_KEY = exports.CONTENT_CACHE_TTL_KEY = exports.EMAIL_ENQUEUE_UTIL_FILE_NAME = exports.EMAIL_ENQUEUE_TYPES_FILE_NAME = exports.DEFAULT_RBAC_CACHE_TTL = exports.DEFAULT_RBAC_CACHE_KEY = exports.DEFAULT_TOTP_WINDOW = exports.DEFAULT_TOTP_DIGITS = exports.DEFAULT_TOTP_STEP = exports.ALPHABET_CORPUS = exports.CHARACTER_CORPUS = exports.REQUEST_RATE_LIMITTER_OPTIONS = exports.CORS_MAX_AGE_IN_MICRO_SECONDS = exports.CORS_MAX_AGE_IN_SECONDS = exports.CORS_ALLOWED_HEADERS = exports.HEADERS_KEY_NAME = exports.CORS_ALLOWED_METHODS = exports.DEVICE_ID_HEADERS_NAME = exports.DEVICE_ID_COOKIE_NAME = exports.DEVICE_ID_COOKIE_MAX_AGE = exports.REQUEST_ID_HEADERS_NAME = exports.REQUEST_ID_COOKIE_NAME = exports.REQUEST_ID_COOKIE_MAX_AGE = exports.SEQUELIZE_SEEDER_META_TABLE_NAME = exports.SEQUELIZE_META_TABLE_NAME = exports.EMAIL_ENQUEUE_DIR = exports.SEEDERS_DIR = exports.MIGRATIONS_DIR = exports.MODELS_DIR = exports.SCHEMA_SNAPSHOTS_DIR = exports.SCHEMAS_DIR = exports.ENV_VAR_DIR = exports.LOG_DIR = exports.BASE_DIR = void 0;
6
+ exports.DEFAULT_CONTENT_CACHE_TTL = exports.DEFAULT_CONTENT_LANG = exports.DEFAULT_CONTENT_URL = exports.CONTENT_LANG_KEY = exports.CONTENT_URL_KEY = exports.CONTENT_CACHE_TTL_KEY = exports.EMAIL_ENQUEUE_UTIL_FILE_NAME = exports.EMAIL_ENQUEUE_TYPES_FILE_NAME = exports.DEFAULT_MAILER_CACHE_TTL = exports.DEFAULT_MAILER_CACHE_KEY = exports.DEFAULT_RBAC_CACHE_TTL = exports.DEFAULT_RBAC_CACHE_KEY = exports.DEFAULT_TOTP_WINDOW = exports.DEFAULT_TOTP_DIGITS = exports.DEFAULT_TOTP_STEP = exports.ALPHABET_CORPUS = exports.CHARACTER_CORPUS = exports.REQUEST_RATE_LIMITTER_OPTIONS = exports.CORS_MAX_AGE_IN_MICRO_SECONDS = exports.CORS_MAX_AGE_IN_SECONDS = exports.CORS_ALLOWED_HEADERS = exports.HEADERS_KEY_NAME = exports.CORS_ALLOWED_METHODS = exports.DEVICE_ID_HEADERS_NAME = exports.DEVICE_ID_COOKIE_NAME = exports.DEVICE_ID_COOKIE_MAX_AGE = exports.REQUEST_ID_HEADERS_NAME = exports.REQUEST_ID_COOKIE_NAME = exports.REQUEST_ID_COOKIE_MAX_AGE = exports.SEQUELIZE_SEEDER_META_TABLE_NAME = exports.SEQUELIZE_META_TABLE_NAME = exports.EMAIL_ENQUEUE_DIR = exports.SEEDERS_DIR = exports.MIGRATIONS_DIR = exports.MODELS_DIR = exports.SCHEMA_SNAPSHOTS_DIR = exports.SCHEMAS_DIR = exports.ENV_VAR_DIR = exports.LOG_DIR = exports.BASE_DIR = void 0;
7
7
  const path_1 = __importDefault(require("path"));
8
8
  exports.BASE_DIR = process.cwd();
9
9
  exports.LOG_DIR = path_1.default.join(exports.BASE_DIR, "logs");
@@ -109,6 +109,8 @@ exports.DEFAULT_TOTP_DIGITS = 6;
109
109
  exports.DEFAULT_TOTP_WINDOW = 1;
110
110
  exports.DEFAULT_RBAC_CACHE_KEY = "RBAC_SNAPSHOT";
111
111
  exports.DEFAULT_RBAC_CACHE_TTL = (1000 * 60 * 60 * 24); // 24 hours
112
+ exports.DEFAULT_MAILER_CACHE_KEY = "MAILER_SNAPSHOT";
113
+ exports.DEFAULT_MAILER_CACHE_TTL = (1000 * 60 * 60 * 24); // 24 hours
112
114
  exports.EMAIL_ENQUEUE_TYPES_FILE_NAME = "types/email_enqueue_type.generated.ts";
113
115
  exports.EMAIL_ENQUEUE_UTIL_FILE_NAME = "utils/email_enqueue_util.generated.ts";
114
116
  exports.CONTENT_CACHE_TTL_KEY = "CONTENT_CACHE_TTL";
@@ -1,3 +1,4 @@
1
1
  import EmailEnqueueGenerator from "./generators/email_enqueue_generator";
2
2
  import EmailEnqueueProcessor from "./processors/email_enqueue_processor";
3
- export { EmailEnqueueGenerator, EmailEnqueueProcessor };
3
+ import MailerDataLoaderUtil from "./utils/mailer_data_loader_util";
4
+ export { EmailEnqueueGenerator, EmailEnqueueProcessor, MailerDataLoaderUtil };
@@ -3,8 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.EmailEnqueueProcessor = exports.EmailEnqueueGenerator = void 0;
6
+ exports.MailerDataLoaderUtil = exports.EmailEnqueueProcessor = exports.EmailEnqueueGenerator = void 0;
7
7
  const email_enqueue_generator_1 = __importDefault(require("./generators/email_enqueue_generator"));
8
8
  exports.EmailEnqueueGenerator = email_enqueue_generator_1.default;
9
9
  const email_enqueue_processor_1 = __importDefault(require("./processors/email_enqueue_processor"));
10
10
  exports.EmailEnqueueProcessor = email_enqueue_processor_1.default;
11
+ const mailer_data_loader_util_1 = __importDefault(require("./utils/mailer_data_loader_util"));
12
+ exports.MailerDataLoaderUtil = mailer_data_loader_util_1.default;
@@ -0,0 +1,38 @@
1
+ import { MailerDataLoaderProvider, MailerDataLoaderOptionsInterface } from "../../types/mailer_type";
2
+ declare class MailerDataLoaderUtil<TMailerConfig, TBaseTemplate, TNotificationType, TEmailContentTempltae> {
3
+ private readonly provider;
4
+ private static instance;
5
+ private readonly logger;
6
+ private readonly cache;
7
+ private readonly CACHE_KEY;
8
+ private readonly DEFAULT_TTL;
9
+ private loading_promise;
10
+ private constructor();
11
+ /**
12
+ * ===============================
13
+ * BUILD SNAPSHOT
14
+ * ===============================
15
+ */
16
+ private buildSnapshot;
17
+ static initialize<TMailerConfig, TBaseTemplate, TNotificationType, TEmailContentTempltae>(provider: MailerDataLoaderProvider<TMailerConfig, TBaseTemplate, TNotificationType, TEmailContentTempltae>, options?: MailerDataLoaderOptionsInterface): MailerDataLoaderUtil<TMailerConfig, TBaseTemplate, TNotificationType, TEmailContentTempltae>;
18
+ static getInstance<TMailerConfig, TBaseTemplate, TNotificationType, TEmailContentTempltae>(): MailerDataLoaderUtil<TMailerConfig, TBaseTemplate, TNotificationType, TEmailContentTempltae>;
19
+ /**
20
+ * ===============================
21
+ * LOAD Mailer
22
+ * ===============================
23
+ */
24
+ load(force_refresh?: boolean): Promise<void>;
25
+ /**
26
+ * ===============================
27
+ * ACCESSORS
28
+ * ===============================
29
+ */
30
+ private getSnapshot;
31
+ getMailerConfig(): TMailerConfig | null;
32
+ getBaseTemplate(): TBaseTemplate | null;
33
+ getNotificationTypes(): TNotificationType[];
34
+ getEmailTemplates(): TEmailContentTempltae[];
35
+ getTemplateByNotificationCode(code: string): Promise<TEmailContentTempltae | null>;
36
+ refresh(): Promise<void>;
37
+ }
38
+ export default MailerDataLoaderUtil;
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const main_1 = require("../../utils/main");
4
+ const constants_1 = require("../../config/constants");
5
+ class MailerDataLoaderUtil {
6
+ provider;
7
+ static instance = null;
8
+ logger = new main_1.LoggerUtil("mailer_data_loader_util");
9
+ cache = new main_1.InMemoryCacheUtil();
10
+ CACHE_KEY;
11
+ DEFAULT_TTL;
12
+ loading_promise = null;
13
+ constructor(provider, options) {
14
+ this.provider = provider;
15
+ this.CACHE_KEY = options?.cache_key ?? constants_1.DEFAULT_MAILER_CACHE_KEY;
16
+ this.DEFAULT_TTL = options?.cache_ttl ?? constants_1.DEFAULT_MAILER_CACHE_TTL;
17
+ }
18
+ /**
19
+ * ===============================
20
+ * BUILD SNAPSHOT
21
+ * ===============================
22
+ */
23
+ async buildSnapshot() {
24
+ const mailer_config = await this.provider.fetchMailerConfig();
25
+ const base_template = await this.provider.fetchBaseTemplate();
26
+ const notification_types = await this.provider.fetchNotificationTypes();
27
+ const email_contents = await this.provider.fetchEmailContentTemplates();
28
+ const notification_by_code = new Map();
29
+ const templates_by_notification_code = new Map();
30
+ // RolePermissions
31
+ for (const notification of notification_types) {
32
+ const notification_code = this.provider.getNotificaionCodeFromNotification(notification);
33
+ notification_by_code.set(notification_code, notification);
34
+ }
35
+ for (const template of email_contents) {
36
+ const notification_code = this.provider.getNotificaionCodeFromTemplate(template);
37
+ templates_by_notification_code.set(notification_code, template);
38
+ }
39
+ return {
40
+ mailer_config,
41
+ base_template,
42
+ notification_types,
43
+ email_contents,
44
+ notification_by_code,
45
+ templates_by_notification_code
46
+ };
47
+ }
48
+ // Method to Initialize singleton (MUST be called once)
49
+ static initialize(provider, options) {
50
+ if (this.instance) {
51
+ throw new Error("MailerDataLoaderUtil already initialized.");
52
+ }
53
+ this.instance = new MailerDataLoaderUtil(provider, options);
54
+ return this.instance;
55
+ }
56
+ // Method to Get singleton instance
57
+ static getInstance() {
58
+ if (!this.instance) {
59
+ throw new Error("RBACLoaderUtil not initialized.");
60
+ }
61
+ return this.instance;
62
+ }
63
+ /**
64
+ * ===============================
65
+ * LOAD Mailer
66
+ * ===============================
67
+ */
68
+ async load(force_refresh = false) {
69
+ if (!force_refresh && this.cache.has(this.CACHE_KEY)) {
70
+ return;
71
+ }
72
+ if (this.loading_promise) {
73
+ return this.loading_promise;
74
+ }
75
+ this.loading_promise = (async () => {
76
+ try {
77
+ const snapshot = await this.buildSnapshot();
78
+ this.cache.set(this.CACHE_KEY, snapshot, this.DEFAULT_TTL);
79
+ }
80
+ catch (error) {
81
+ this.logger.error("Failed to load Mailer snapshot", { error });
82
+ throw error;
83
+ }
84
+ finally {
85
+ this.loading_promise = null;
86
+ }
87
+ })();
88
+ return this.loading_promise;
89
+ }
90
+ /**
91
+ * ===============================
92
+ * ACCESSORS
93
+ * ===============================
94
+ */
95
+ getSnapshot() {
96
+ const snapshot = this.cache.get(this.CACHE_KEY);
97
+ if (!snapshot) {
98
+ throw new Error("Mailer Data Loader Util snapshot not loaded. Call load() first.");
99
+ }
100
+ return snapshot;
101
+ }
102
+ getMailerConfig() {
103
+ return this.getSnapshot().mailer_config;
104
+ }
105
+ getBaseTemplate() {
106
+ return this.getSnapshot().base_template;
107
+ }
108
+ getNotificationTypes() {
109
+ return this.getSnapshot().notification_types;
110
+ }
111
+ getEmailTemplates() {
112
+ return this.getSnapshot().email_contents;
113
+ }
114
+ async getTemplateByNotificationCode(code) {
115
+ const templates_by_notification_code = this.getSnapshot().templates_by_notification_code;
116
+ if (templates_by_notification_code.has(code)) {
117
+ return templates_by_notification_code.get(code) ?? null;
118
+ }
119
+ return await this.provider.fetchEmailContentTemplateByNotificationcode(code);
120
+ }
121
+ // --------------------------
122
+ // Refresh
123
+ // --------------------------
124
+ async refresh() {
125
+ await this.load(true);
126
+ }
127
+ }
128
+ exports.default = MailerDataLoaderUtil;
@@ -39,3 +39,24 @@ export interface EmailQueueAdapter<TQueueEntity, TNotification, TTemplate, TMail
39
39
  created_by?: number | null;
40
40
  }): Promise<TQueueEntity>;
41
41
  }
42
+ export interface MailerDataLoaderProvider<TMailerConfig, TBaseTemplate, TNotificationType, TEmailContentTempltae> {
43
+ fetchMailerConfig(): Promise<TMailerConfig | null>;
44
+ fetchBaseTemplate(): Promise<TBaseTemplate | null>;
45
+ fetchNotificationTypes(): Promise<TNotificationType[]>;
46
+ fetchEmailContentTemplates(): Promise<TEmailContentTempltae[]>;
47
+ fetchEmailContentTemplateByNotificationcode(code: string): Promise<TEmailContentTempltae | null>;
48
+ getNotificaionCodeFromNotification(notification: TNotificationType): string;
49
+ getNotificaionCodeFromTemplate(email_content_template: TEmailContentTempltae): string;
50
+ }
51
+ export interface MailerDataLoaderSnapshot<TMailerConfig, TBaseTemplate, TNotificationType, TEmailContentTempltae> {
52
+ mailer_config: TMailerConfig | null;
53
+ base_template: TBaseTemplate | null;
54
+ notification_types: TNotificationType[];
55
+ email_contents: TEmailContentTempltae[];
56
+ notification_by_code: Map<string, TNotificationType>;
57
+ templates_by_notification_code: Map<string, TEmailContentTempltae>;
58
+ }
59
+ export interface MailerDataLoaderOptionsInterface {
60
+ cache_key?: string;
61
+ cache_ttl?: number;
62
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fiberx-backend-toolkit",
3
- "version": "0.0.77",
3
+ "version": "0.0.78",
4
4
  "description": "A TypeScript backend toolkit providing shared domain logic, infrastructure helpers, and utilities for FiberX server-side applications and services.",
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",