@flusys/nestjs-email 1.1.0-beta
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.
- package/cjs/config/email-config.service.js +94 -0
- package/cjs/config/email.constants.js +40 -0
- package/cjs/config/index.js +19 -0
- package/cjs/controllers/email-config.controller.js +59 -0
- package/cjs/controllers/email-send.controller.js +142 -0
- package/cjs/controllers/email-template.controller.js +84 -0
- package/cjs/controllers/index.js +20 -0
- package/cjs/docs/email-swagger.config.js +176 -0
- package/cjs/docs/index.js +11 -0
- package/cjs/dtos/email-config.dto.js +238 -0
- package/cjs/dtos/email-send.dto.js +376 -0
- package/cjs/dtos/email-template.dto.js +283 -0
- package/cjs/dtos/index.js +20 -0
- package/cjs/entities/email-config-base.entity.js +111 -0
- package/cjs/entities/email-config-with-company.entity.js +63 -0
- package/cjs/entities/email-config.entity.js +25 -0
- package/cjs/entities/email-template-base.entity.js +134 -0
- package/cjs/entities/email-template-with-company.entity.js +63 -0
- package/cjs/entities/email-template.entity.js +25 -0
- package/cjs/entities/index.js +41 -0
- package/cjs/enums/email-provider-type.enum.js +18 -0
- package/cjs/enums/index.js +18 -0
- package/cjs/index.js +27 -0
- package/cjs/interfaces/email-config.interface.js +4 -0
- package/cjs/interfaces/email-module-options.interface.js +4 -0
- package/cjs/interfaces/email-provider.interface.js +6 -0
- package/cjs/interfaces/email-template.interface.js +4 -0
- package/cjs/interfaces/index.js +21 -0
- package/cjs/modules/email.module.js +177 -0
- package/cjs/modules/index.js +18 -0
- package/cjs/providers/email-factory.service.js +160 -0
- package/cjs/providers/email-provider.registry.js +51 -0
- package/cjs/providers/index.js +22 -0
- package/cjs/providers/mailgun-provider.js +125 -0
- package/cjs/providers/sendgrid-provider.js +156 -0
- package/cjs/providers/smtp-provider.js +185 -0
- package/cjs/services/email-datasource.provider.js +215 -0
- package/cjs/services/email-provider-config.service.js +180 -0
- package/cjs/services/email-send.service.js +228 -0
- package/cjs/services/email-template.service.js +186 -0
- package/cjs/services/index.js +21 -0
- package/config/email-config.service.d.ts +13 -0
- package/config/email.constants.d.ts +11 -0
- package/config/index.d.ts +2 -0
- package/controllers/email-config.controller.d.ts +17 -0
- package/controllers/email-send.controller.d.ts +19 -0
- package/controllers/email-template.controller.d.ts +25 -0
- package/controllers/index.d.ts +3 -0
- package/docs/email-swagger.config.d.ts +3 -0
- package/docs/index.d.ts +1 -0
- package/dtos/email-config.dto.d.ts +33 -0
- package/dtos/email-send.dto.d.ts +45 -0
- package/dtos/email-template.dto.d.ts +42 -0
- package/dtos/index.d.ts +3 -0
- package/entities/email-config-base.entity.d.ts +11 -0
- package/entities/email-config-with-company.entity.d.ts +4 -0
- package/entities/email-config.entity.d.ts +3 -0
- package/entities/email-template-base.entity.d.ts +14 -0
- package/entities/email-template-with-company.entity.d.ts +4 -0
- package/entities/email-template.entity.d.ts +3 -0
- package/entities/index.d.ts +7 -0
- package/enums/email-provider-type.enum.d.ts +5 -0
- package/enums/index.d.ts +1 -0
- package/fesm/config/email-config.service.js +84 -0
- package/fesm/config/email.constants.js +13 -0
- package/fesm/config/index.js +2 -0
- package/fesm/controllers/email-config.controller.js +49 -0
- package/fesm/controllers/email-send.controller.js +132 -0
- package/fesm/controllers/email-template.controller.js +74 -0
- package/fesm/controllers/index.js +3 -0
- package/fesm/docs/email-swagger.config.js +172 -0
- package/fesm/docs/index.js +1 -0
- package/fesm/dtos/email-config.dto.js +223 -0
- package/fesm/dtos/email-send.dto.js +360 -0
- package/fesm/dtos/email-template.dto.js +268 -0
- package/fesm/dtos/index.js +3 -0
- package/fesm/entities/email-config-base.entity.js +101 -0
- package/fesm/entities/email-config-with-company.entity.js +53 -0
- package/fesm/entities/email-config.entity.js +15 -0
- package/fesm/entities/email-template-base.entity.js +124 -0
- package/fesm/entities/email-template-with-company.entity.js +53 -0
- package/fesm/entities/email-template.entity.js +15 -0
- package/fesm/entities/index.js +20 -0
- package/fesm/enums/email-provider-type.enum.js +8 -0
- package/fesm/enums/index.js +1 -0
- package/fesm/index.js +10 -0
- package/fesm/interfaces/email-config.interface.js +3 -0
- package/fesm/interfaces/email-module-options.interface.js +3 -0
- package/fesm/interfaces/email-provider.interface.js +5 -0
- package/fesm/interfaces/email-template.interface.js +3 -0
- package/fesm/interfaces/index.js +4 -0
- package/fesm/modules/email.module.js +167 -0
- package/fesm/modules/index.js +1 -0
- package/fesm/providers/email-factory.service.js +109 -0
- package/fesm/providers/email-provider.registry.js +44 -0
- package/fesm/providers/index.js +5 -0
- package/fesm/providers/mailgun-provider.js +119 -0
- package/fesm/providers/sendgrid-provider.js +150 -0
- package/fesm/providers/smtp-provider.js +137 -0
- package/fesm/services/email-datasource.provider.js +164 -0
- package/fesm/services/email-provider-config.service.js +170 -0
- package/fesm/services/email-send.service.js +218 -0
- package/fesm/services/email-template.service.js +176 -0
- package/fesm/services/index.js +4 -0
- package/index.d.ts +9 -0
- package/interfaces/email-config.interface.d.ts +28 -0
- package/interfaces/email-module-options.interface.d.ts +26 -0
- package/interfaces/email-provider.interface.d.ts +34 -0
- package/interfaces/email-template.interface.d.ts +64 -0
- package/interfaces/index.d.ts +4 -0
- package/modules/email.module.d.ts +9 -0
- package/modules/index.d.ts +1 -0
- package/package.json +105 -0
- package/providers/email-factory.service.d.ts +14 -0
- package/providers/email-provider.registry.d.ts +10 -0
- package/providers/index.d.ts +5 -0
- package/providers/mailgun-provider.d.ts +11 -0
- package/providers/sendgrid-provider.d.ts +11 -0
- package/providers/smtp-provider.d.ts +11 -0
- package/services/email-datasource.provider.d.ts +25 -0
- package/services/email-provider-config.service.d.ts +32 -0
- package/services/email-send.service.d.ts +20 -0
- package/services/email-template.service.d.ts +31 -0
- package/services/index.d.ts +4 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) {
|
|
3
|
+
Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
} else {
|
|
10
|
+
obj[key] = value;
|
|
11
|
+
}
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
15
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
18
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
|
+
}
|
|
20
|
+
function _ts_metadata(k, v) {
|
|
21
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
22
|
+
}
|
|
23
|
+
function _ts_param(paramIndex, decorator) {
|
|
24
|
+
return function(target, key) {
|
|
25
|
+
decorator(target, key, paramIndex);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
import { RequestScopedApiService, HybridCache } from '@flusys/nestjs-shared/classes';
|
|
29
|
+
import { UtilsService } from '@flusys/nestjs-shared/modules';
|
|
30
|
+
import { Inject, Injectable, Scope } from '@nestjs/common';
|
|
31
|
+
import { EmailConfigService } from '../config';
|
|
32
|
+
import { EmailTemplate, EmailTemplateWithCompany } from '../entities';
|
|
33
|
+
import { EmailDataSourceProvider } from './email-datasource.provider';
|
|
34
|
+
export class EmailTemplateService extends RequestScopedApiService {
|
|
35
|
+
/**
|
|
36
|
+
* Resolve entity class for this service
|
|
37
|
+
*/ resolveEntity() {
|
|
38
|
+
const enableCompanyFeature = this.emailConfig.isCompanyFeatureEnabled();
|
|
39
|
+
return enableCompanyFeature ? EmailTemplateWithCompany : EmailTemplate;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get DataSource provider for this service
|
|
43
|
+
*/ getDataSourceProvider() {
|
|
44
|
+
return this.dataSourceProvider;
|
|
45
|
+
}
|
|
46
|
+
async convertSingleDtoToEntity(dto, user) {
|
|
47
|
+
// For updates, fetch existing template to handle versioning
|
|
48
|
+
const updateDto = dto;
|
|
49
|
+
if (updateDto.id) {
|
|
50
|
+
await this.ensureRepositoryInitialized();
|
|
51
|
+
const existing = await this.repository.findOne({
|
|
52
|
+
where: {
|
|
53
|
+
id: updateDto.id
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (existing) {
|
|
57
|
+
// Auto-increment schema version if schema changed
|
|
58
|
+
if (dto.schema && JSON.stringify(dto.schema) !== JSON.stringify(existing.schema)) {
|
|
59
|
+
dto.schemaVersion = existing.schemaVersion + 1;
|
|
60
|
+
this.logger.log(`Schema changed for template ${updateDto.id}, incrementing version from ${existing.schemaVersion} to ${dto.schemaVersion}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
let templateEntity = {
|
|
65
|
+
...dto
|
|
66
|
+
};
|
|
67
|
+
// Set company fields if company feature is enabled
|
|
68
|
+
if (this.emailConfig.isCompanyFeatureEnabled()) {
|
|
69
|
+
templateEntity.companyId = user?.companyId ?? null;
|
|
70
|
+
}
|
|
71
|
+
return templateEntity;
|
|
72
|
+
}
|
|
73
|
+
async getSelectQuery(query, _user, select) {
|
|
74
|
+
if (!select || !select.length) {
|
|
75
|
+
select = [
|
|
76
|
+
'id',
|
|
77
|
+
'name',
|
|
78
|
+
'slug',
|
|
79
|
+
'description',
|
|
80
|
+
'subject',
|
|
81
|
+
'schema',
|
|
82
|
+
'htmlContent',
|
|
83
|
+
'textContent',
|
|
84
|
+
'schemaVersion',
|
|
85
|
+
'isActive',
|
|
86
|
+
'isHtml',
|
|
87
|
+
'metadata',
|
|
88
|
+
'createdAt',
|
|
89
|
+
'updatedAt'
|
|
90
|
+
];
|
|
91
|
+
if (this.emailConfig.isCompanyFeatureEnabled()) {
|
|
92
|
+
select.push('companyId');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const selectFields = select.map((field)=>`${this.entityName}.${field}`);
|
|
96
|
+
query.select(selectFields);
|
|
97
|
+
return {
|
|
98
|
+
query,
|
|
99
|
+
isRaw: false
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Override: Extra query manipulation - Auto-filter by user's company
|
|
104
|
+
*/ async getExtraManipulateQuery(query, filterDto, user) {
|
|
105
|
+
const result = await super.getExtraManipulateQuery(query, filterDto, user);
|
|
106
|
+
const enableCompanyFeature = this.emailConfig.isCompanyFeatureEnabled();
|
|
107
|
+
if (enableCompanyFeature && user?.companyId) {
|
|
108
|
+
query.andWhere('emailTemplate.companyId = :companyId', {
|
|
109
|
+
companyId: user.companyId
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
query.orderBy(`${this.entityName}.createdAt`, 'DESC');
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Find template by ID directly (bypasses company filtering)
|
|
117
|
+
*/ async findByIdDirect(id) {
|
|
118
|
+
await this.ensureRepositoryInitialized();
|
|
119
|
+
return await this.repository.findOne({
|
|
120
|
+
where: {
|
|
121
|
+
id
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Find template by slug (scoped to user's company if enabled)
|
|
127
|
+
*/ async findBySlug(slug, user) {
|
|
128
|
+
await this.ensureRepositoryInitialized();
|
|
129
|
+
const where = {
|
|
130
|
+
slug,
|
|
131
|
+
isActive: true
|
|
132
|
+
};
|
|
133
|
+
if (this.emailConfig.isCompanyFeatureEnabled() && user?.companyId) {
|
|
134
|
+
where.companyId = user.companyId;
|
|
135
|
+
}
|
|
136
|
+
return await this.repository.findOne({
|
|
137
|
+
where
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Get all active templates (scoped to user's company if enabled)
|
|
142
|
+
*/ async getActiveTemplates(user) {
|
|
143
|
+
await this.ensureRepositoryInitialized();
|
|
144
|
+
const where = {
|
|
145
|
+
isActive: true
|
|
146
|
+
};
|
|
147
|
+
if (this.emailConfig.isCompanyFeatureEnabled() && user?.companyId) {
|
|
148
|
+
where.companyId = user.companyId;
|
|
149
|
+
}
|
|
150
|
+
return await this.repository.find({
|
|
151
|
+
where,
|
|
152
|
+
order: {
|
|
153
|
+
name: 'ASC'
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
constructor(cacheManager, utilsService, emailConfig, dataSourceProvider){
|
|
158
|
+
super('emailTemplate', null, cacheManager, utilsService, EmailTemplateService.name, true), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "emailConfig", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.emailConfig = emailConfig, this.dataSourceProvider = dataSourceProvider;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
EmailTemplateService = _ts_decorate([
|
|
162
|
+
Injectable({
|
|
163
|
+
scope: Scope.REQUEST
|
|
164
|
+
}),
|
|
165
|
+
_ts_param(0, Inject('CACHE_INSTANCE')),
|
|
166
|
+
_ts_param(1, Inject(UtilsService)),
|
|
167
|
+
_ts_param(2, Inject(EmailConfigService)),
|
|
168
|
+
_ts_param(3, Inject(EmailDataSourceProvider)),
|
|
169
|
+
_ts_metadata("design:type", Function),
|
|
170
|
+
_ts_metadata("design:paramtypes", [
|
|
171
|
+
typeof HybridCache === "undefined" ? Object : HybridCache,
|
|
172
|
+
typeof UtilsService === "undefined" ? Object : UtilsService,
|
|
173
|
+
typeof EmailConfigService === "undefined" ? Object : EmailConfigService,
|
|
174
|
+
typeof EmailDataSourceProvider === "undefined" ? Object : EmailDataSourceProvider
|
|
175
|
+
])
|
|
176
|
+
], EmailTemplateService);
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { IIdentity } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { EmailProviderTypeEnum } from '../enums';
|
|
3
|
+
export interface IEmailConfig extends IIdentity {
|
|
4
|
+
name: string;
|
|
5
|
+
provider: EmailProviderTypeEnum;
|
|
6
|
+
config: Record<string, any>;
|
|
7
|
+
fromEmail: string | null;
|
|
8
|
+
fromName: string | null;
|
|
9
|
+
isActive: boolean;
|
|
10
|
+
companyId?: string | null;
|
|
11
|
+
}
|
|
12
|
+
export interface ISmtpConfig {
|
|
13
|
+
host: string;
|
|
14
|
+
port: number;
|
|
15
|
+
secure?: boolean;
|
|
16
|
+
auth?: {
|
|
17
|
+
user: string;
|
|
18
|
+
pass: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export interface ISendGridConfig {
|
|
22
|
+
apiKey: string;
|
|
23
|
+
}
|
|
24
|
+
export interface IMailgunConfig {
|
|
25
|
+
apiKey: string;
|
|
26
|
+
domain: string;
|
|
27
|
+
region?: 'us' | 'eu';
|
|
28
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { IBootstrapAppConfig, IDataSourceServiceOptions, IDynamicModuleConfig, IModuleOptionsFactory } from '@flusys/nestjs-core';
|
|
2
|
+
import { ModuleMetadata, Type } from '@nestjs/common';
|
|
3
|
+
export interface IEmailModuleConfig extends IDataSourceServiceOptions {
|
|
4
|
+
defaultProvider?: string;
|
|
5
|
+
rateLimitPerMinute?: number;
|
|
6
|
+
enableLogging?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface IEmailModuleConfigFull {
|
|
9
|
+
bootstrapAppConfig?: IBootstrapAppConfig;
|
|
10
|
+
config?: IEmailModuleConfig;
|
|
11
|
+
}
|
|
12
|
+
export interface EmailModuleOptions extends IDynamicModuleConfig {
|
|
13
|
+
bootstrapAppConfig?: IBootstrapAppConfig;
|
|
14
|
+
config?: IEmailModuleConfig;
|
|
15
|
+
}
|
|
16
|
+
export interface EmailOptionsFactory extends IModuleOptionsFactory<IEmailModuleConfig> {
|
|
17
|
+
createEmailOptions(): Promise<IEmailModuleConfig> | IEmailModuleConfig;
|
|
18
|
+
createOptions(): Promise<IEmailModuleConfig> | IEmailModuleConfig;
|
|
19
|
+
}
|
|
20
|
+
export interface EmailModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'>, IDynamicModuleConfig {
|
|
21
|
+
bootstrapAppConfig: IBootstrapAppConfig;
|
|
22
|
+
useFactory?: (...args: any[]) => Promise<IEmailModuleConfig> | IEmailModuleConfig;
|
|
23
|
+
inject?: any[];
|
|
24
|
+
useClass?: Type<EmailOptionsFactory>;
|
|
25
|
+
useExisting?: Type<EmailOptionsFactory>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface IEmailProviderConfig {
|
|
2
|
+
provider: string;
|
|
3
|
+
config: Record<string, any>;
|
|
4
|
+
}
|
|
5
|
+
export interface IEmailAttachment {
|
|
6
|
+
filename: string;
|
|
7
|
+
content: Buffer | string;
|
|
8
|
+
contentType?: string;
|
|
9
|
+
encoding?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface IEmailSendOptions {
|
|
12
|
+
to: string | string[];
|
|
13
|
+
cc?: string | string[];
|
|
14
|
+
bcc?: string | string[];
|
|
15
|
+
subject: string;
|
|
16
|
+
html?: string;
|
|
17
|
+
text?: string;
|
|
18
|
+
from?: string;
|
|
19
|
+
fromName?: string;
|
|
20
|
+
replyTo?: string;
|
|
21
|
+
attachments?: IEmailAttachment[];
|
|
22
|
+
}
|
|
23
|
+
export interface IEmailSendResult {
|
|
24
|
+
success: boolean;
|
|
25
|
+
messageId?: string;
|
|
26
|
+
error?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface IEmailProvider {
|
|
29
|
+
sendEmail(options: IEmailSendOptions): Promise<IEmailSendResult>;
|
|
30
|
+
sendBulkEmails(options: IEmailSendOptions[]): Promise<IEmailSendResult[]>;
|
|
31
|
+
healthCheck(): Promise<boolean>;
|
|
32
|
+
initialize?(config: any): Promise<void>;
|
|
33
|
+
close?(): Promise<void>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { IIdentity } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
export interface IEmailTemplateVariable {
|
|
3
|
+
name: string;
|
|
4
|
+
type: 'string' | 'number' | 'boolean' | 'date';
|
|
5
|
+
required?: boolean;
|
|
6
|
+
defaultValue?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface IEmailTemplate extends IIdentity {
|
|
10
|
+
name: string;
|
|
11
|
+
slug: string;
|
|
12
|
+
description: string | null;
|
|
13
|
+
subject: string;
|
|
14
|
+
schema: Record<string, unknown>;
|
|
15
|
+
htmlContent: string;
|
|
16
|
+
textContent: string | null;
|
|
17
|
+
schemaVersion: number;
|
|
18
|
+
isActive: boolean;
|
|
19
|
+
isHtml: boolean;
|
|
20
|
+
metadata: Record<string, unknown> | null;
|
|
21
|
+
companyId?: string | null;
|
|
22
|
+
}
|
|
23
|
+
export interface IEmailSection {
|
|
24
|
+
id: string;
|
|
25
|
+
type: 'header' | 'body' | 'footer';
|
|
26
|
+
name: string;
|
|
27
|
+
blocks: IEmailBlock[];
|
|
28
|
+
order: number;
|
|
29
|
+
style?: IEmailSectionStyle;
|
|
30
|
+
}
|
|
31
|
+
export interface IEmailSectionStyle {
|
|
32
|
+
backgroundColor?: string;
|
|
33
|
+
padding?: string;
|
|
34
|
+
maxWidth?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface IEmailBlock {
|
|
37
|
+
id: string;
|
|
38
|
+
type: 'text' | 'image' | 'button' | 'divider' | 'html';
|
|
39
|
+
order: number;
|
|
40
|
+
content: Record<string, any>;
|
|
41
|
+
style?: IEmailBlockStyle;
|
|
42
|
+
}
|
|
43
|
+
export interface IEmailBlockStyle {
|
|
44
|
+
textAlign?: 'left' | 'center' | 'right';
|
|
45
|
+
padding?: string;
|
|
46
|
+
margin?: string;
|
|
47
|
+
backgroundColor?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface IEmailSettings {
|
|
50
|
+
maxWidth?: string;
|
|
51
|
+
backgroundColor?: string;
|
|
52
|
+
fontFamily?: string;
|
|
53
|
+
baseTextColor?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface IEmailSchema {
|
|
56
|
+
id: string;
|
|
57
|
+
version: string;
|
|
58
|
+
name: string;
|
|
59
|
+
subject: string;
|
|
60
|
+
preheader?: string;
|
|
61
|
+
sections: IEmailSection[];
|
|
62
|
+
variables?: IEmailTemplateVariable[];
|
|
63
|
+
settings?: IEmailSettings;
|
|
64
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { EmailModuleAsyncOptions, EmailModuleOptions } from '../interfaces';
|
|
3
|
+
export declare class EmailModule {
|
|
4
|
+
static forRoot(options: EmailModuleOptions): DynamicModule;
|
|
5
|
+
static forRootAsync(options: EmailModuleAsyncOptions): DynamicModule;
|
|
6
|
+
private static getControllers;
|
|
7
|
+
private static getProviders;
|
|
8
|
+
private static createAsyncProviders;
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './email.module';
|
package/package.json
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flusys/nestjs-email",
|
|
3
|
+
"version": "1.1.0-beta",
|
|
4
|
+
"description": "Modular email package with SMTP, SendGrid, and Mailgun providers",
|
|
5
|
+
"main": "cjs/index.js",
|
|
6
|
+
"module": "fesm/index.js",
|
|
7
|
+
"types": "index.d.ts",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"keywords": [
|
|
10
|
+
"nestjs",
|
|
11
|
+
"email",
|
|
12
|
+
"smtp",
|
|
13
|
+
"sendgrid",
|
|
14
|
+
"mailgun",
|
|
15
|
+
"template",
|
|
16
|
+
"@flusys"
|
|
17
|
+
],
|
|
18
|
+
"license": "UNLICENSED",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./index.d.ts",
|
|
22
|
+
"import": "./fesm/index.js",
|
|
23
|
+
"require": "./cjs/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./config": {
|
|
26
|
+
"types": "./config/index.d.ts",
|
|
27
|
+
"import": "./fesm/config/index.js",
|
|
28
|
+
"require": "./cjs/config/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./controllers": {
|
|
31
|
+
"types": "./controllers/index.d.ts",
|
|
32
|
+
"import": "./fesm/controllers/index.js",
|
|
33
|
+
"require": "./cjs/controllers/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./dtos": {
|
|
36
|
+
"types": "./dtos/index.d.ts",
|
|
37
|
+
"import": "./fesm/dtos/index.js",
|
|
38
|
+
"require": "./cjs/dtos/index.js"
|
|
39
|
+
},
|
|
40
|
+
"./entities": {
|
|
41
|
+
"types": "./entities/index.d.ts",
|
|
42
|
+
"import": "./fesm/entities/index.js",
|
|
43
|
+
"require": "./cjs/entities/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./enums": {
|
|
46
|
+
"types": "./enums/index.d.ts",
|
|
47
|
+
"import": "./fesm/enums/index.js",
|
|
48
|
+
"require": "./cjs/enums/index.js"
|
|
49
|
+
},
|
|
50
|
+
"./interfaces": {
|
|
51
|
+
"types": "./interfaces/index.d.ts",
|
|
52
|
+
"import": "./fesm/interfaces/index.js",
|
|
53
|
+
"require": "./cjs/interfaces/index.js"
|
|
54
|
+
},
|
|
55
|
+
"./modules": {
|
|
56
|
+
"types": "./modules/index.d.ts",
|
|
57
|
+
"import": "./fesm/modules/index.js",
|
|
58
|
+
"require": "./cjs/modules/index.js"
|
|
59
|
+
},
|
|
60
|
+
"./providers": {
|
|
61
|
+
"types": "./providers/index.d.ts",
|
|
62
|
+
"import": "./fesm/providers/index.js",
|
|
63
|
+
"require": "./cjs/providers/index.js"
|
|
64
|
+
},
|
|
65
|
+
"./services": {
|
|
66
|
+
"types": "./services/index.d.ts",
|
|
67
|
+
"import": "./fesm/services/index.js",
|
|
68
|
+
"require": "./cjs/services/index.js"
|
|
69
|
+
},
|
|
70
|
+
"./*": {
|
|
71
|
+
"types": "./*.d.ts",
|
|
72
|
+
"import": "./*.js",
|
|
73
|
+
"require": "./*.js"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"@nestjs/common": "^10.0.0 || ^11.0.0",
|
|
78
|
+
"@nestjs/config": "^3.0.0 || ^4.0.0",
|
|
79
|
+
"@nestjs/core": "^10.0.0 || ^11.0.0",
|
|
80
|
+
"@nestjs/platform-express": "^10.0.0 || ^11.0.0",
|
|
81
|
+
"@nestjs/swagger": "^7.0.0 || ^11.0.0",
|
|
82
|
+
"@nestjs/typeorm": "^10.0.0 || ^11.0.0",
|
|
83
|
+
"class-transformer": "^0.5.0",
|
|
84
|
+
"class-validator": "^0.14.0",
|
|
85
|
+
"typeorm": "^0.3.0",
|
|
86
|
+
"nodemailer": "^6.9.0",
|
|
87
|
+
"@sendgrid/mail": "^8.0.0",
|
|
88
|
+
"mailgun.js": "^10.0.0"
|
|
89
|
+
},
|
|
90
|
+
"peerDependenciesMeta": {
|
|
91
|
+
"nodemailer": {
|
|
92
|
+
"optional": false
|
|
93
|
+
},
|
|
94
|
+
"@sendgrid/mail": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
97
|
+
"mailgun.js": {
|
|
98
|
+
"optional": true
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"dependencies": {
|
|
102
|
+
"@flusys/nestjs-core": "1.1.0-beta",
|
|
103
|
+
"@flusys/nestjs-shared": "1.1.0-beta"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { OnModuleDestroy } from '@nestjs/common';
|
|
2
|
+
import { EmailConfigService } from '../config/email-config.service';
|
|
3
|
+
import { IEmailProvider, IEmailProviderConfig } from '../interfaces';
|
|
4
|
+
export declare class EmailFactoryService implements OnModuleDestroy {
|
|
5
|
+
private readonly emailConfigService;
|
|
6
|
+
private readonly logger;
|
|
7
|
+
private providerCache;
|
|
8
|
+
constructor(emailConfigService: EmailConfigService);
|
|
9
|
+
private generateCacheKey;
|
|
10
|
+
createProvider(config: IEmailProviderConfig): Promise<IEmailProvider>;
|
|
11
|
+
isProviderAvailable(providerName: string): boolean;
|
|
12
|
+
getAvailableProviders(): string[];
|
|
13
|
+
onModuleDestroy(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Type } from '@nestjs/common';
|
|
2
|
+
import { IEmailProvider } from '../interfaces';
|
|
3
|
+
export declare class EmailProviderRegistry {
|
|
4
|
+
private static providers;
|
|
5
|
+
static register(providerName: string, providerClass: Type<IEmailProvider>): void;
|
|
6
|
+
static get(providerName: string): Type<IEmailProvider> | undefined;
|
|
7
|
+
static has(providerName: string): boolean;
|
|
8
|
+
static getAll(): string[];
|
|
9
|
+
static clear(): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IEmailProvider, IEmailSendOptions, IEmailSendResult, IMailgunConfig } from '../interfaces';
|
|
2
|
+
export declare class MailgunProvider implements IEmailProvider {
|
|
3
|
+
private logger;
|
|
4
|
+
private client;
|
|
5
|
+
private config;
|
|
6
|
+
initialize(config: IMailgunConfig): Promise<void>;
|
|
7
|
+
sendEmail(options: IEmailSendOptions): Promise<IEmailSendResult>;
|
|
8
|
+
sendBulkEmails(options: IEmailSendOptions[]): Promise<IEmailSendResult[]>;
|
|
9
|
+
healthCheck(): Promise<boolean>;
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IEmailProvider, IEmailSendOptions, IEmailSendResult, ISendGridConfig } from '../interfaces';
|
|
2
|
+
export declare class SendGridProvider implements IEmailProvider {
|
|
3
|
+
private logger;
|
|
4
|
+
private sgMail;
|
|
5
|
+
private config;
|
|
6
|
+
initialize(config: ISendGridConfig): Promise<void>;
|
|
7
|
+
sendEmail(options: IEmailSendOptions): Promise<IEmailSendResult>;
|
|
8
|
+
sendBulkEmails(options: IEmailSendOptions[]): Promise<IEmailSendResult[]>;
|
|
9
|
+
healthCheck(): Promise<boolean>;
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IEmailProvider, IEmailSendOptions, IEmailSendResult, ISmtpConfig } from '../interfaces';
|
|
2
|
+
export declare class SmtpProvider implements IEmailProvider {
|
|
3
|
+
private logger;
|
|
4
|
+
private transporter;
|
|
5
|
+
private config;
|
|
6
|
+
initialize(config: ISmtpConfig): Promise<void>;
|
|
7
|
+
sendEmail(options: IEmailSendOptions): Promise<IEmailSendResult>;
|
|
8
|
+
sendBulkEmails(options: IEmailSendOptions[]): Promise<IEmailSendResult[]>;
|
|
9
|
+
healthCheck(): Promise<boolean>;
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { MultiTenantDataSourceService } from '@flusys/nestjs-shared/modules';
|
|
2
|
+
import { IDatabaseConfig, ITenantDatabaseConfig } from '@flusys/nestjs-core';
|
|
3
|
+
import { Logger } from '@nestjs/common';
|
|
4
|
+
import { Request } from 'express';
|
|
5
|
+
import { DataSource } from 'typeorm';
|
|
6
|
+
import { EmailModuleOptions } from '../interfaces';
|
|
7
|
+
export declare class EmailDataSourceProvider extends MultiTenantDataSourceService {
|
|
8
|
+
private readonly emailOptions;
|
|
9
|
+
protected readonly logger: Logger;
|
|
10
|
+
protected static readonly tenantConnections: Map<string, DataSource>;
|
|
11
|
+
protected static singleDataSource: DataSource | null;
|
|
12
|
+
protected static readonly tenantsRegistry: Map<string, ITenantDatabaseConfig>;
|
|
13
|
+
protected static initialized: boolean;
|
|
14
|
+
protected static readonly connectionLocks: Map<string, Promise<DataSource>>;
|
|
15
|
+
protected static singleConnectionLock: Promise<DataSource> | null;
|
|
16
|
+
constructor(emailOptions: EmailModuleOptions, request?: Request);
|
|
17
|
+
private static buildParentOptions;
|
|
18
|
+
getEnableCompanyFeature(): boolean;
|
|
19
|
+
getEnableCompanyFeatureForTenant(tenant?: ITenantDatabaseConfig): boolean;
|
|
20
|
+
getEnableCompanyFeatureForCurrentTenant(): boolean;
|
|
21
|
+
getEmailEntities(enableCompanyFeature?: boolean): Promise<any[]>;
|
|
22
|
+
protected createDataSourceFromConfig(config: IDatabaseConfig): Promise<DataSource>;
|
|
23
|
+
protected getSingleDataSource(): Promise<DataSource>;
|
|
24
|
+
protected getOrCreateTenantConnection(tenant: ITenantDatabaseConfig): Promise<DataSource>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { RequestScopedApiService, HybridCache } from '@flusys/nestjs-shared/classes';
|
|
2
|
+
import { FilterAndPaginationDto } from '@flusys/nestjs-shared/dtos';
|
|
3
|
+
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
4
|
+
import { UtilsService } from '@flusys/nestjs-shared/modules';
|
|
5
|
+
import { EntityTarget, Repository, SelectQueryBuilder } from 'typeorm';
|
|
6
|
+
import { EmailConfigService } from '../config';
|
|
7
|
+
import { CreateEmailConfigDto, UpdateEmailConfigDto } from '../dtos';
|
|
8
|
+
import { EmailConfigBase } from '../entities';
|
|
9
|
+
import { EmailProviderTypeEnum } from '../enums';
|
|
10
|
+
import { IEmailConfig } from '../interfaces';
|
|
11
|
+
import { EmailDataSourceProvider } from './email-datasource.provider';
|
|
12
|
+
export declare class EmailProviderConfigService extends RequestScopedApiService<CreateEmailConfigDto, UpdateEmailConfigDto, IEmailConfig, EmailConfigBase, Repository<EmailConfigBase>> {
|
|
13
|
+
protected cacheManager: HybridCache;
|
|
14
|
+
protected utilsService: UtilsService;
|
|
15
|
+
private readonly emailConfig;
|
|
16
|
+
private readonly dataSourceProvider;
|
|
17
|
+
constructor(cacheManager: HybridCache, utilsService: UtilsService, emailConfig: EmailConfigService, dataSourceProvider: EmailDataSourceProvider);
|
|
18
|
+
protected resolveEntity(): EntityTarget<EmailConfigBase>;
|
|
19
|
+
protected getDataSourceProvider(): EmailDataSourceProvider;
|
|
20
|
+
convertSingleDtoToEntity(dto: CreateEmailConfigDto | UpdateEmailConfigDto, user: ILoggedUserInfo | null): Promise<EmailConfigBase>;
|
|
21
|
+
getSelectQuery(query: SelectQueryBuilder<EmailConfigBase>, _user: ILoggedUserInfo | null, select?: string[]): Promise<{
|
|
22
|
+
query: SelectQueryBuilder<EmailConfigBase>;
|
|
23
|
+
isRaw: boolean;
|
|
24
|
+
}>;
|
|
25
|
+
protected getExtraManipulateQuery(query: SelectQueryBuilder<EmailConfigBase>, filterDto: FilterAndPaginationDto, user: ILoggedUserInfo | null): Promise<{
|
|
26
|
+
query: SelectQueryBuilder<EmailConfigBase>;
|
|
27
|
+
isRaw: boolean;
|
|
28
|
+
}>;
|
|
29
|
+
findByIdDirect(id: string): Promise<EmailConfigBase | null>;
|
|
30
|
+
getDefaultConfig(user?: ILoggedUserInfo): Promise<EmailConfigBase | null>;
|
|
31
|
+
getConfigByProvider(provider: EmailProviderTypeEnum, user?: ILoggedUserInfo): Promise<EmailConfigBase[]>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { EmailConfigService } from '../config';
|
|
3
|
+
import { SendEmailDto, SendTemplateEmailDto } from '../dtos';
|
|
4
|
+
import { IEmailSendResult } from '../interfaces';
|
|
5
|
+
import { EmailFactoryService } from '../providers';
|
|
6
|
+
import { EmailProviderConfigService } from './email-provider-config.service';
|
|
7
|
+
import { EmailTemplateService } from './email-template.service';
|
|
8
|
+
export declare class EmailSendService {
|
|
9
|
+
private readonly emailFactory;
|
|
10
|
+
private readonly emailConfigService;
|
|
11
|
+
private readonly emailProviderConfigService;
|
|
12
|
+
private readonly emailTemplateService;
|
|
13
|
+
private readonly logger;
|
|
14
|
+
constructor(emailFactory: EmailFactoryService, emailConfigService: EmailConfigService, emailProviderConfigService: EmailProviderConfigService, emailTemplateService: EmailTemplateService);
|
|
15
|
+
private getEmailProviderWithConfig;
|
|
16
|
+
private interpolateVariables;
|
|
17
|
+
sendEmail(dto: SendEmailDto, user?: ILoggedUserInfo): Promise<IEmailSendResult>;
|
|
18
|
+
sendTemplateEmail(dto: SendTemplateEmailDto, user?: ILoggedUserInfo): Promise<IEmailSendResult>;
|
|
19
|
+
sendTestEmail(emailConfigId: string, recipient: string, user?: ILoggedUserInfo): Promise<IEmailSendResult>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { RequestScopedApiService, HybridCache } from '@flusys/nestjs-shared/classes';
|
|
2
|
+
import { FilterAndPaginationDto } from '@flusys/nestjs-shared/dtos';
|
|
3
|
+
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
4
|
+
import { UtilsService } from '@flusys/nestjs-shared/modules';
|
|
5
|
+
import { EntityTarget, Repository, SelectQueryBuilder } from 'typeorm';
|
|
6
|
+
import { EmailConfigService } from '../config';
|
|
7
|
+
import { CreateEmailTemplateDto, UpdateEmailTemplateDto } from '../dtos';
|
|
8
|
+
import { EmailTemplateBase } from '../entities';
|
|
9
|
+
import { IEmailTemplate } from '../interfaces';
|
|
10
|
+
import { EmailDataSourceProvider } from './email-datasource.provider';
|
|
11
|
+
export declare class EmailTemplateService extends RequestScopedApiService<CreateEmailTemplateDto, UpdateEmailTemplateDto, IEmailTemplate, EmailTemplateBase, Repository<EmailTemplateBase>> {
|
|
12
|
+
protected cacheManager: HybridCache;
|
|
13
|
+
protected utilsService: UtilsService;
|
|
14
|
+
private readonly emailConfig;
|
|
15
|
+
private readonly dataSourceProvider;
|
|
16
|
+
constructor(cacheManager: HybridCache, utilsService: UtilsService, emailConfig: EmailConfigService, dataSourceProvider: EmailDataSourceProvider);
|
|
17
|
+
protected resolveEntity(): EntityTarget<EmailTemplateBase>;
|
|
18
|
+
protected getDataSourceProvider(): EmailDataSourceProvider;
|
|
19
|
+
convertSingleDtoToEntity(dto: CreateEmailTemplateDto | UpdateEmailTemplateDto, user: ILoggedUserInfo | null): Promise<EmailTemplateBase>;
|
|
20
|
+
getSelectQuery(query: SelectQueryBuilder<EmailTemplateBase>, _user: ILoggedUserInfo | null, select?: string[]): Promise<{
|
|
21
|
+
query: SelectQueryBuilder<EmailTemplateBase>;
|
|
22
|
+
isRaw: boolean;
|
|
23
|
+
}>;
|
|
24
|
+
protected getExtraManipulateQuery(query: SelectQueryBuilder<EmailTemplateBase>, filterDto: FilterAndPaginationDto, user: ILoggedUserInfo | null): Promise<{
|
|
25
|
+
query: SelectQueryBuilder<EmailTemplateBase>;
|
|
26
|
+
isRaw: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
findByIdDirect(id: string): Promise<EmailTemplateBase | null>;
|
|
29
|
+
findBySlug(slug: string, user?: ILoggedUserInfo): Promise<EmailTemplateBase | null>;
|
|
30
|
+
getActiveTemplates(user?: ILoggedUserInfo): Promise<EmailTemplateBase[]>;
|
|
31
|
+
}
|