@groundbrick/service-base 0.0.1
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/README.md +713 -0
- package/dist/core/BaseService.d.ts +55 -0
- package/dist/core/BaseService.d.ts.map +1 -0
- package/dist/core/BaseService.js +123 -0
- package/dist/core/BaseService.js.map +1 -0
- package/dist/email/EmailConfigurationService.d.ts +14 -0
- package/dist/email/EmailConfigurationService.d.ts.map +1 -0
- package/dist/email/EmailConfigurationService.js +60 -0
- package/dist/email/EmailConfigurationService.js.map +1 -0
- package/dist/email/EmailService.d.ts +15 -0
- package/dist/email/EmailService.d.ts.map +1 -0
- package/dist/email/EmailService.js +96 -0
- package/dist/email/EmailService.js.map +1 -0
- package/dist/email/interfaces/EmailInterfaces.d.ts +45 -0
- package/dist/email/interfaces/EmailInterfaces.d.ts.map +1 -0
- package/dist/email/interfaces/EmailInterfaces.js +2 -0
- package/dist/email/interfaces/EmailInterfaces.js.map +1 -0
- package/dist/email/providers/SmtpEmailProvider.d.ts +14 -0
- package/dist/email/providers/SmtpEmailProvider.d.ts.map +1 -0
- package/dist/email/providers/SmtpEmailProvider.js +88 -0
- package/dist/email/providers/SmtpEmailProvider.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/types/BusinessError.d.ts +31 -0
- package/dist/types/BusinessError.d.ts.map +1 -0
- package/dist/types/BusinessError.js +57 -0
- package/dist/types/BusinessError.js.map +1 -0
- package/dist/types/ServiceOptions.d.ts +14 -0
- package/dist/types/ServiceOptions.d.ts.map +1 -0
- package/dist/types/ServiceOptions.js +2 -0
- package/dist/types/ServiceOptions.js.map +1 -0
- package/dist/types/ServiceResult.d.ts +31 -0
- package/dist/types/ServiceResult.d.ts.map +1 -0
- package/dist/types/ServiceResult.js +61 -0
- package/dist/types/ServiceResult.js.map +1 -0
- package/dist/validation/ValidationError.d.ts +14 -0
- package/dist/validation/ValidationError.d.ts.map +1 -0
- package/dist/validation/ValidationError.js +2 -0
- package/dist/validation/ValidationError.js.map +1 -0
- package/dist/validation/ValidationHelper.d.ts +70 -0
- package/dist/validation/ValidationHelper.d.ts.map +1 -0
- package/dist/validation/ValidationHelper.js +169 -0
- package/dist/validation/ValidationHelper.js.map +1 -0
- package/dist/validation/ValidationResult.d.ts +12 -0
- package/dist/validation/ValidationResult.d.ts.map +1 -0
- package/dist/validation/ValidationResult.js +2 -0
- package/dist/validation/ValidationResult.js.map +1 -0
- package/dist/validation/Validator.d.ts +35 -0
- package/dist/validation/Validator.d.ts.map +1 -0
- package/dist/validation/Validator.js +52 -0
- package/dist/validation/Validator.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Logger } from '@groundbrick/logger';
|
|
2
|
+
import { DatabaseTransaction, DatabaseClient } from '@groundbrick/db-core';
|
|
3
|
+
import { ServiceOptions } from '../types/ServiceOptions.js';
|
|
4
|
+
import { ValidationRules, Validator } from '../validation/Validator.js';
|
|
5
|
+
import { ValidationResult } from '../validation/ValidationResult.js';
|
|
6
|
+
/**
|
|
7
|
+
* Abstract base service class providing common service layer functionality
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Integrated logging with service context
|
|
11
|
+
* - Transaction management helpers
|
|
12
|
+
* - Input validation framework
|
|
13
|
+
* - Standardized error handling
|
|
14
|
+
* - Repository integration patterns
|
|
15
|
+
*/
|
|
16
|
+
export declare abstract class BaseService {
|
|
17
|
+
protected readonly logger: Logger;
|
|
18
|
+
protected readonly db?: DatabaseClient;
|
|
19
|
+
protected readonly validator: Validator;
|
|
20
|
+
constructor(options?: ServiceOptions);
|
|
21
|
+
/**
|
|
22
|
+
* Validate input data against provided rules
|
|
23
|
+
* @param data - Data to validate
|
|
24
|
+
* @param rules - Validation rules
|
|
25
|
+
* @returns ValidationResult with errors if any
|
|
26
|
+
*/
|
|
27
|
+
protected validate<T>(data: T, rules: ValidationRules): Promise<ValidationResult>;
|
|
28
|
+
/**
|
|
29
|
+
* Execute operation within a database transaction
|
|
30
|
+
* @param callback - Function to execute within transaction
|
|
31
|
+
* @returns Promise with callback result
|
|
32
|
+
*/
|
|
33
|
+
protected withTransaction<T>(callback: (tx: DatabaseTransaction) => Promise<T>): Promise<T>;
|
|
34
|
+
/**
|
|
35
|
+
* Validate required fields are present and not empty
|
|
36
|
+
* @param data - Object to check
|
|
37
|
+
* @param fields - Required field names
|
|
38
|
+
* @throws BusinessError if validation fails
|
|
39
|
+
*/
|
|
40
|
+
protected validateRequired(data: Record<string, any>, fields: string[]): void;
|
|
41
|
+
/**
|
|
42
|
+
* Log operation start with timing
|
|
43
|
+
* @param operation - Operation name
|
|
44
|
+
* @param metadata - Additional metadata
|
|
45
|
+
* @returns Timer function to call when operation completes
|
|
46
|
+
*/
|
|
47
|
+
protected startOperation(operation: string, metadata?: Record<string, any>): () => void;
|
|
48
|
+
/**
|
|
49
|
+
* Safe JSON serialization for logging
|
|
50
|
+
* @param obj - Object to serialize
|
|
51
|
+
* @returns Serialized object or error info
|
|
52
|
+
*/
|
|
53
|
+
protected safeSerialize(obj: any): any;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=BaseService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseService.d.ts","sourceRoot":"","sources":["../../src/core/BaseService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAIrE;;;;;;;;;GASG;AACH,8BAAsB,WAAW;IAC7B,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAClC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,cAAc,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;gBAE5B,OAAO,CAAC,EAAE,cAAc;IAWpC;;;;;OAKG;cACa,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoBvF;;;;OAIG;cACa,eAAe,CAAC,CAAC,EAC7B,QAAQ,EAAE,CAAC,EAAE,EAAE,mBAAmB,KAAK,OAAO,CAAC,CAAC,CAAC,GAClD,OAAO,CAAC,CAAC,CAAC;IAgCb;;;;;OAKG;IACH,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAmB7E;;;;;OAKG;IACH,SAAS,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,IAAI;IAKvF;;;;OAIG;IACH,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG;CAOzC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { createLogger } from '@groundbrick/logger';
|
|
2
|
+
import { Validator } from '../validation/Validator.js';
|
|
3
|
+
import { BusinessError } from '../types/BusinessError.js';
|
|
4
|
+
import { createErrorResult } from '../types/ServiceResult.js';
|
|
5
|
+
/**
|
|
6
|
+
* Abstract base service class providing common service layer functionality
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Integrated logging with service context
|
|
10
|
+
* - Transaction management helpers
|
|
11
|
+
* - Input validation framework
|
|
12
|
+
* - Standardized error handling
|
|
13
|
+
* - Repository integration patterns
|
|
14
|
+
*/
|
|
15
|
+
export class BaseService {
|
|
16
|
+
logger;
|
|
17
|
+
db;
|
|
18
|
+
validator;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
this.logger = createLogger().child('service');
|
|
21
|
+
this.db = options?.database;
|
|
22
|
+
this.validator = options?.validator || new Validator();
|
|
23
|
+
// Add service class name to logger context if available
|
|
24
|
+
if (this.constructor.name !== 'BaseService') {
|
|
25
|
+
this.logger.addMetadata('serviceClass:', this.constructor.name);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validate input data against provided rules
|
|
30
|
+
* @param data - Data to validate
|
|
31
|
+
* @param rules - Validation rules
|
|
32
|
+
* @returns ValidationResult with errors if any
|
|
33
|
+
*/
|
|
34
|
+
async validate(data, rules) {
|
|
35
|
+
try {
|
|
36
|
+
this.logger.debug('Validating input data', { rules: Object.keys(rules) });
|
|
37
|
+
const result = await this.validator.validate(data, rules);
|
|
38
|
+
if (!result.isValid) {
|
|
39
|
+
this.logger.warn('Validation failed', {
|
|
40
|
+
errors: result.errors,
|
|
41
|
+
fieldCount: Object.keys(rules).length
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
this.logger.error('Validation error', error instanceof Error ? error : new Error(String(error)));
|
|
48
|
+
throw new BusinessError('Validation failed', 'VALIDATION_ERROR', error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Execute operation within a database transaction
|
|
53
|
+
* @param callback - Function to execute within transaction
|
|
54
|
+
* @returns Promise with callback result
|
|
55
|
+
*/
|
|
56
|
+
async withTransaction(callback) {
|
|
57
|
+
if (!this.db) {
|
|
58
|
+
throw new BusinessError('Database not available for transaction', 'NO_DATABASE');
|
|
59
|
+
}
|
|
60
|
+
const transactionId = Math.random().toString(36).substring(7);
|
|
61
|
+
this.logger.debug('Starting transaction', {
|
|
62
|
+
transactionId,
|
|
63
|
+
dbType: this.db.getDatabaseType() // Database client knows its type
|
|
64
|
+
});
|
|
65
|
+
try {
|
|
66
|
+
// Use the database client's transaction method which handles commit/rollback automatically
|
|
67
|
+
const result = await this.db.transaction(async (transaction) => {
|
|
68
|
+
this.logger.debug('Transaction started successfully', {
|
|
69
|
+
transactionId,
|
|
70
|
+
dbType: transaction.getDatabaseType() // Transaction knows its type too!
|
|
71
|
+
});
|
|
72
|
+
return await callback(transaction);
|
|
73
|
+
});
|
|
74
|
+
this.logger.debug('Transaction completed successfully', { transactionId });
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
this.logger.error('Transaction failed', error instanceof Error ? error : new Error(String(error)), { transactionId });
|
|
79
|
+
throw createErrorResult(error);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Validate required fields are present and not empty
|
|
84
|
+
* @param data - Object to check
|
|
85
|
+
* @param fields - Required field names
|
|
86
|
+
* @throws BusinessError if validation fails
|
|
87
|
+
*/
|
|
88
|
+
validateRequired(data, fields) {
|
|
89
|
+
const missing = [];
|
|
90
|
+
for (const field of fields) {
|
|
91
|
+
if (data[field] === undefined || data[field] === null || data[field] === '') {
|
|
92
|
+
missing.push(field);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (missing.length > 0) {
|
|
96
|
+
throw new BusinessError(`Missing required fields: ${missing.join(', ')}`, 'MISSING_REQUIRED_FIELDS', undefined, { missingFields: missing });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Log operation start with timing
|
|
101
|
+
* @param operation - Operation name
|
|
102
|
+
* @param metadata - Additional metadata
|
|
103
|
+
* @returns Timer function to call when operation completes
|
|
104
|
+
*/
|
|
105
|
+
startOperation(operation, metadata) {
|
|
106
|
+
this.logger.info(`Starting ${operation}`, metadata);
|
|
107
|
+
return this.logger.startTimer(`service-${operation}`);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Safe JSON serialization for logging
|
|
111
|
+
* @param obj - Object to serialize
|
|
112
|
+
* @returns Serialized object or error info
|
|
113
|
+
*/
|
|
114
|
+
safeSerialize(obj) {
|
|
115
|
+
try {
|
|
116
|
+
return JSON.parse(JSON.stringify(obj));
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return { error: 'Unable to serialize object' };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=BaseService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseService.js","sourceRoot":"","sources":["../../src/core/BaseService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EmailService } from './EmailService.js';
|
|
2
|
+
export interface EmailConfigRepository {
|
|
3
|
+
findByKey(key: string): Promise<{
|
|
4
|
+
value: string;
|
|
5
|
+
} | null>;
|
|
6
|
+
}
|
|
7
|
+
export declare class EmailConfigurationService {
|
|
8
|
+
private configRepository;
|
|
9
|
+
private logger;
|
|
10
|
+
constructor(configRepository: EmailConfigRepository);
|
|
11
|
+
createEmailService(): Promise<EmailService>;
|
|
12
|
+
private loadEmailConfig;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=EmailConfigurationService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmailConfigurationService.d.ts","sourceRoot":"","sources":["../../src/email/EmailConfigurationService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKjD,MAAM,WAAW,qBAAqB;IAClC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CAC7D;AAED,qBAAa,yBAAyB;IAGtB,OAAO,CAAC,gBAAgB;IAFpC,OAAO,CAAC,MAAM,CAAS;gBAEH,gBAAgB,EAAE,qBAAqB;IAIrD,kBAAkB,IAAI,OAAO,CAAC,YAAY,CAAC;YAmBnC,eAAe;CAqChC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { EmailService } from './EmailService.js';
|
|
2
|
+
import { SmtpEmailProvider } from './providers/SmtpEmailProvider.js';
|
|
3
|
+
import { createLogger } from '@groundbrick/logger';
|
|
4
|
+
export class EmailConfigurationService {
|
|
5
|
+
configRepository;
|
|
6
|
+
logger;
|
|
7
|
+
constructor(configRepository) {
|
|
8
|
+
this.configRepository = configRepository;
|
|
9
|
+
this.logger = createLogger().child('email-config');
|
|
10
|
+
}
|
|
11
|
+
async createEmailService() {
|
|
12
|
+
try {
|
|
13
|
+
const config = await this.loadEmailConfig();
|
|
14
|
+
const provider = new SmtpEmailProvider();
|
|
15
|
+
const emailService = new EmailService(provider);
|
|
16
|
+
await emailService.initialize(config);
|
|
17
|
+
return emailService;
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
this.logger.warn('Failed to create email service with SMTP provider, using fallback', {
|
|
21
|
+
error: error instanceof Error ? error.message : String(error)
|
|
22
|
+
});
|
|
23
|
+
// Return service without provider (will log emails instead of sending)
|
|
24
|
+
return new EmailService();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async loadEmailConfig() {
|
|
28
|
+
const configs = await Promise.all([
|
|
29
|
+
this.configRepository.findByKey('smtp_host'),
|
|
30
|
+
this.configRepository.findByKey('smtp_port'),
|
|
31
|
+
this.configRepository.findByKey('smtp_secure'),
|
|
32
|
+
this.configRepository.findByKey('smtp_user'),
|
|
33
|
+
this.configRepository.findByKey('smtp_password'),
|
|
34
|
+
this.configRepository.findByKey('email_from_address'),
|
|
35
|
+
this.configRepository.findByKey('email_from_name')
|
|
36
|
+
]);
|
|
37
|
+
const [host, port, secure, user, password, fromAddress, fromName] = configs;
|
|
38
|
+
if (!host?.value || !port?.value || !fromAddress?.value) {
|
|
39
|
+
throw new Error('Missing required email configuration: host, port, or from_address');
|
|
40
|
+
}
|
|
41
|
+
const config = {
|
|
42
|
+
host: host.value,
|
|
43
|
+
port: parseInt(port.value),
|
|
44
|
+
secure: secure?.value === 'true',
|
|
45
|
+
from: {
|
|
46
|
+
address: fromAddress.value,
|
|
47
|
+
name: fromName?.value
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
// Only add auth if both user and password are provided
|
|
51
|
+
if (user?.value && password?.value) {
|
|
52
|
+
config.auth = {
|
|
53
|
+
user: user.value,
|
|
54
|
+
pass: password.value
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return config;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=EmailConfigurationService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmailConfigurationService.js","sourceRoot":"","sources":["../../src/email/EmailConfigurationService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAErE,OAAO,EAAU,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAM3D,MAAM,OAAO,yBAAyB;IAGd;IAFZ,MAAM,CAAS;IAEvB,YAAoB,gBAAuC;QAAvC,qBAAgB,GAAhB,gBAAgB,CAAuB;QACvD,IAAI,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,kBAAkB;QACpB,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;YAC5C,MAAM,QAAQ,GAAG,IAAI,iBAAiB,EAAE,CAAC;YACzC,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;YAEhD,MAAM,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACtC,OAAO,YAAY,CAAC;QAExB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mEAAmE,EAAE;gBAClF,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAChE,CAAC,CAAC;YAEH,uEAAuE;YACvE,OAAO,IAAI,YAAY,EAAE,CAAC;QAC9B,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,eAAe;QACzB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC9B,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAC;YAC5C,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAC;YAC5C,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,aAAa,CAAC;YAC9C,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAC;YAC5C,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,eAAe,CAAC;YAChD,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,oBAAoB,CAAC;YACrD,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,iBAAiB,CAAC;SACrD,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC;QAE5E,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;QACzF,CAAC;QAED,MAAM,MAAM,GAAgB;YACxB,IAAI,EAAE,IAAI,CAAC,KAAK;YAChB,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;YAC1B,MAAM,EAAE,MAAM,EAAE,KAAK,KAAK,MAAM;YAChC,IAAI,EAAE;gBACF,OAAO,EAAE,WAAW,CAAC,KAAK;gBAC1B,IAAI,EAAE,QAAQ,EAAE,KAAK;aACxB;SACJ,CAAC;QAEF,uDAAuD;QACvD,IAAI,IAAI,EAAE,KAAK,IAAI,QAAQ,EAAE,KAAK,EAAE,CAAC;YACjC,MAAM,CAAC,IAAI,GAAG;gBACV,IAAI,EAAE,IAAI,CAAC,KAAK;gBAChB,IAAI,EAAE,QAAQ,CAAC,KAAK;aACvB,CAAC;QACN,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EmailProvider, EmailMessage, EmailResult, EmailConfig, EmailAddress } from './interfaces/EmailInterfaces.js';
|
|
2
|
+
export declare class EmailService {
|
|
3
|
+
private logger;
|
|
4
|
+
private provider?;
|
|
5
|
+
private isEnabled;
|
|
6
|
+
constructor(provider?: EmailProvider);
|
|
7
|
+
initialize(config: EmailConfig): Promise<void>;
|
|
8
|
+
sendEmail(message: EmailMessage): Promise<EmailResult>;
|
|
9
|
+
isServiceEnabled(): boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class EmailUtils {
|
|
12
|
+
static createAddress(address: string, name?: string): EmailAddress;
|
|
13
|
+
static createSimpleMessage(to: string | EmailAddress, subject: string, content: string, isHtml?: boolean): EmailMessage;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=EmailService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmailService.d.ts","sourceRoot":"","sources":["../../src/email/EmailService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAGtH,qBAAa,YAAY;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,CAAgB;IACjC,OAAO,CAAC,SAAS,CAAkB;gBAEvB,QAAQ,CAAC,EAAE,aAAa;IAK9B,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB9C,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IA4C5D,gBAAgB,IAAI,OAAO;CAG9B;AAGD,qBAAa,UAAU;IACnB,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY;IAIlE,MAAM,CAAC,mBAAmB,CACtB,EAAE,EAAE,MAAM,GAAG,YAAY,EACzB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,OAAe,GACxB,YAAY;CAgBlB"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { createLogger } from '@groundbrick/logger';
|
|
2
|
+
import { env } from 'process';
|
|
3
|
+
export class EmailService {
|
|
4
|
+
logger;
|
|
5
|
+
provider;
|
|
6
|
+
isEnabled = false;
|
|
7
|
+
constructor(provider) {
|
|
8
|
+
this.logger = createLogger().child('email-service');
|
|
9
|
+
this.provider = provider;
|
|
10
|
+
}
|
|
11
|
+
async initialize(config) {
|
|
12
|
+
if (!this.provider) {
|
|
13
|
+
this.logger.warn('No email provider configured, emails will be logged only');
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
await this.provider.initialize(config);
|
|
18
|
+
this.isEnabled = this.provider.isConfigured();
|
|
19
|
+
if (this.isEnabled) {
|
|
20
|
+
this.logger.info('Email service initialized successfully');
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
this.logger.warn('Email service initialized but not properly configured');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
this.logger.error('Failed to initialize email service', error instanceof Error ? error : new Error(String(error)));
|
|
28
|
+
this.isEnabled = false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async sendEmail(message) {
|
|
32
|
+
const endTimer = this.logger.startTimer('send-email');
|
|
33
|
+
try {
|
|
34
|
+
if (!this.isEnabled || !this.provider) {
|
|
35
|
+
this.logger.info('Email sending disabled, logging email instead', {
|
|
36
|
+
to: message.to,
|
|
37
|
+
subject: message.content.subject
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
success: true,
|
|
41
|
+
messageId: 'mock-' + Date.now()
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const result = await this.provider.sendEmail(message);
|
|
45
|
+
if (result.success) {
|
|
46
|
+
this.logger.info('Email sent successfully', {
|
|
47
|
+
to: message.to,
|
|
48
|
+
subject: message.content.subject,
|
|
49
|
+
messageId: result.messageId
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
this.logger.error('Failed to send email', undefined, {
|
|
54
|
+
to: message.to,
|
|
55
|
+
subject: message.content.subject,
|
|
56
|
+
error: result.error
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
this.logger.error('Email sending error', error instanceof Error ? error : new Error(String(error)));
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
error: error instanceof Error ? error.message : String(error)
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
endTimer();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
isServiceEnabled() {
|
|
73
|
+
return this.isEnabled;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Utility functions for common email operations
|
|
77
|
+
export class EmailUtils {
|
|
78
|
+
static createAddress(address, name) {
|
|
79
|
+
return { address, name };
|
|
80
|
+
}
|
|
81
|
+
static createSimpleMessage(to, subject, content, isHtml = false) {
|
|
82
|
+
if (env.NODE_ENV === 'development') {
|
|
83
|
+
to = 'cleiton.marques@200.systems';
|
|
84
|
+
subject = `[DEV] ${subject}`;
|
|
85
|
+
}
|
|
86
|
+
const toAddress = typeof to === 'string' ? { address: to } : to;
|
|
87
|
+
return {
|
|
88
|
+
to: toAddress,
|
|
89
|
+
content: {
|
|
90
|
+
subject,
|
|
91
|
+
...(isHtml ? { html: content } : { text: content })
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=EmailService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmailService.js","sourceRoot":"","sources":["../../src/email/EmailService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export interface EmailAddress {
|
|
2
|
+
address: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface EmailContent {
|
|
6
|
+
subject: string;
|
|
7
|
+
text?: string;
|
|
8
|
+
html?: string;
|
|
9
|
+
attachments?: EmailAttachment[];
|
|
10
|
+
}
|
|
11
|
+
export interface EmailAttachment {
|
|
12
|
+
filename: string;
|
|
13
|
+
content: Buffer | string;
|
|
14
|
+
contentType: string;
|
|
15
|
+
}
|
|
16
|
+
export interface EmailMessage {
|
|
17
|
+
to: EmailAddress | EmailAddress[];
|
|
18
|
+
from?: EmailAddress;
|
|
19
|
+
cc?: EmailAddress[];
|
|
20
|
+
bcc?: EmailAddress[];
|
|
21
|
+
replyTo?: EmailAddress;
|
|
22
|
+
content: EmailContent;
|
|
23
|
+
}
|
|
24
|
+
export type EmailProviderType = 'smtp';
|
|
25
|
+
export interface EmailConfig {
|
|
26
|
+
host: string;
|
|
27
|
+
port: number;
|
|
28
|
+
secure: boolean;
|
|
29
|
+
auth?: {
|
|
30
|
+
user: string;
|
|
31
|
+
pass: string;
|
|
32
|
+
};
|
|
33
|
+
from: EmailAddress;
|
|
34
|
+
}
|
|
35
|
+
export interface EmailProvider {
|
|
36
|
+
initialize(config: EmailConfig): Promise<void>;
|
|
37
|
+
sendEmail(message: EmailMessage): Promise<EmailResult>;
|
|
38
|
+
isConfigured(): boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface EmailResult {
|
|
41
|
+
success: boolean;
|
|
42
|
+
messageId?: string;
|
|
43
|
+
error?: string;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=EmailInterfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmailInterfaces.d.ts","sourceRoot":"","sources":["../../../src/email/interfaces/EmailInterfaces.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,YAAY,GAAG,YAAY,EAAE,CAAC;IAClC,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC;IACpB,GAAG,CAAC,EAAE,YAAY,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,YAAY,CAAC;CACzB;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACvC,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,IAAI,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC1B,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACvD,YAAY,IAAI,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmailInterfaces.js","sourceRoot":"","sources":["../../../src/email/interfaces/EmailInterfaces.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EmailProvider, EmailMessage, EmailResult, EmailConfig } from '../interfaces/EmailInterfaces.js';
|
|
2
|
+
export declare class SmtpEmailProvider implements EmailProvider {
|
|
3
|
+
private logger;
|
|
4
|
+
private transporter?;
|
|
5
|
+
private config?;
|
|
6
|
+
private configured;
|
|
7
|
+
constructor();
|
|
8
|
+
initialize(config: EmailConfig): Promise<void>;
|
|
9
|
+
sendEmail(message: EmailMessage): Promise<EmailResult>;
|
|
10
|
+
isConfigured(): boolean;
|
|
11
|
+
private formatAddress;
|
|
12
|
+
private formatAddresses;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=SmtpEmailProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SmtpEmailProvider.d.ts","sourceRoot":"","sources":["../../../src/email/providers/SmtpEmailProvider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAgB,MAAM,kCAAkC,CAAC;AAGvH,qBAAa,iBAAkB,YAAW,aAAa;IACnD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,MAAM,CAAC,CAAc;IAC7B,OAAO,CAAC,UAAU,CAAkB;;IAM9B,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC9C,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAuC5D,YAAY,IAAI,OAAO;IAIvB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,eAAe;CAM1B"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// packages/service-base/src/email/providers/SmtpEmailProvider.ts
|
|
2
|
+
import { createTransport } from 'nodemailer';
|
|
3
|
+
import { createLogger } from '@groundbrick/logger';
|
|
4
|
+
export class SmtpEmailProvider {
|
|
5
|
+
logger;
|
|
6
|
+
transporter;
|
|
7
|
+
config;
|
|
8
|
+
configured = false;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.logger = createLogger().child('smtp-provider');
|
|
11
|
+
}
|
|
12
|
+
async initialize(config) {
|
|
13
|
+
try {
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.transporter = createTransport({
|
|
16
|
+
pool: true,
|
|
17
|
+
host: config.host,
|
|
18
|
+
port: config.port,
|
|
19
|
+
secure: config.secure,
|
|
20
|
+
auth: config.auth ? {
|
|
21
|
+
user: config.auth.user,
|
|
22
|
+
pass: config.auth.pass
|
|
23
|
+
} : undefined
|
|
24
|
+
});
|
|
25
|
+
// Test connection
|
|
26
|
+
await this.transporter.verify();
|
|
27
|
+
this.configured = true;
|
|
28
|
+
this.logger.info('SMTP provider initialized successfully', {
|
|
29
|
+
host: config.host,
|
|
30
|
+
port: config.port,
|
|
31
|
+
secure: config.secure,
|
|
32
|
+
hasAuth: !!config.auth
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
this.logger.error('Failed to initialize SMTP provider', error instanceof Error ? error : new Error(String(error)));
|
|
37
|
+
this.configured = false;
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async sendEmail(message) {
|
|
42
|
+
if (!this.transporter || !this.config) {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
error: 'SMTP provider not initialized'
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const mailOptions = {
|
|
50
|
+
from: this.formatAddress(message.from || this.config.from),
|
|
51
|
+
to: this.formatAddresses(message.to),
|
|
52
|
+
cc: message.cc ? this.formatAddresses(message.cc) : undefined,
|
|
53
|
+
bcc: message.bcc ? this.formatAddresses(message.bcc) : undefined,
|
|
54
|
+
replyTo: message.replyTo ? this.formatAddress(message.replyTo) : undefined,
|
|
55
|
+
subject: message.content.subject,
|
|
56
|
+
text: message.content.text,
|
|
57
|
+
html: message.content.html,
|
|
58
|
+
attachments: message.content.attachments
|
|
59
|
+
};
|
|
60
|
+
const result = await this.transporter.sendMail(mailOptions);
|
|
61
|
+
return {
|
|
62
|
+
success: true,
|
|
63
|
+
messageId: result.messageId
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
68
|
+
this.logger.error('Failed to send email via SMTP', error instanceof Error ? error : new Error(String(error)));
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: errorMessage
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
isConfigured() {
|
|
76
|
+
return this.configured;
|
|
77
|
+
}
|
|
78
|
+
formatAddress(address) {
|
|
79
|
+
return address.name ? `"${address.name}" <${address.address}>` : address.address;
|
|
80
|
+
}
|
|
81
|
+
formatAddresses(addresses) {
|
|
82
|
+
if (Array.isArray(addresses)) {
|
|
83
|
+
return addresses.map(addr => this.formatAddress(addr));
|
|
84
|
+
}
|
|
85
|
+
return this.formatAddress(addresses);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=SmtpEmailProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SmtpEmailProvider.js","sourceRoot":"","sources":["../../../src/email/providers/SmtpEmailProvider.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { BaseService } from './core/BaseService.js';
|
|
2
|
+
export { BusinessError } from './types/BusinessError.js';
|
|
3
|
+
export type { ServiceResult } from './types/ServiceResult.js';
|
|
4
|
+
export { createSuccessResult, createErrorResult } from './types/ServiceResult.js';
|
|
5
|
+
export { Validator } from './validation/Validator.js';
|
|
6
|
+
export { ValidationHelper } from './validation/ValidationHelper.js';
|
|
7
|
+
export type { ValidationRule, ValidationRules } from './validation/Validator.js';
|
|
8
|
+
export type { ValidationResult } from './validation/ValidationResult.js';
|
|
9
|
+
export { EmailService, EmailUtils } from './email/EmailService.js';
|
|
10
|
+
export { EmailConfigurationService } from './email/EmailConfigurationService.js';
|
|
11
|
+
export { SmtpEmailProvider } from './email/providers/SmtpEmailProvider.js';
|
|
12
|
+
export type { EmailAddress, EmailContent, EmailAttachment, EmailMessage, EmailConfig, EmailProvider, EmailResult } from './email/interfaces/EmailInterfaces.js';
|
|
13
|
+
export type { ServiceOptions } from './types/ServiceOptions.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAMpD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAMlF,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjF,YAAY,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAMzE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAE3E,YAAY,EACR,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,WAAW,EACX,aAAa,EACb,WAAW,EACd,MAAM,uCAAuC,CAAC;AAM/C,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// packages/service-base/src/index.ts
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// CORE CLASSES
|
|
4
|
+
// ============================================================================
|
|
5
|
+
export { BaseService } from './core/BaseService.js';
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// ERROR HANDLING
|
|
8
|
+
// ============================================================================
|
|
9
|
+
export { BusinessError } from './types/BusinessError.js';
|
|
10
|
+
export { createSuccessResult, createErrorResult } from './types/ServiceResult.js';
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// VALIDATION
|
|
13
|
+
// ============================================================================
|
|
14
|
+
export { Validator } from './validation/Validator.js';
|
|
15
|
+
export { ValidationHelper } from './validation/ValidationHelper.js';
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// EMAIL SERVICES
|
|
18
|
+
// ============================================================================
|
|
19
|
+
export { EmailService, EmailUtils } from './email/EmailService.js';
|
|
20
|
+
export { EmailConfigurationService } from './email/EmailConfigurationService.js';
|
|
21
|
+
export { SmtpEmailProvider } from './email/providers/SmtpEmailProvider.js';
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,+EAA+E;AAC/E,eAAe;AACf,+EAA+E;AAE/E,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElF,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAIpE,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC"}
|