update
This commit is contained in:
@ -1,59 +1,2 @@
|
||||
// Export configuration interfaces
|
||||
export * from './base.config.js';
|
||||
export * from './email.config.js';
|
||||
export * from './sms.config.js';
|
||||
export * from './platform.config.js';
|
||||
|
||||
// Export validation tools
|
||||
export * from './validator.js';
|
||||
export * from './schemas.js';
|
||||
|
||||
// Re-export commonly used types
|
||||
import type { IPlatformConfig } from './platform.config.js';
|
||||
import type { ISmsConfig } from './sms.config.js';
|
||||
import type {
|
||||
IBaseConfig,
|
||||
ITlsConfig,
|
||||
IHttpServerConfig,
|
||||
IRateLimitConfig,
|
||||
IQueueConfig
|
||||
} from './base.config.js';
|
||||
|
||||
// Default platform configuration
|
||||
export const defaultConfig: IPlatformConfig = {
|
||||
id: 'platform-service-config',
|
||||
version: '1.0.0',
|
||||
environment: 'production',
|
||||
name: 'PlatformService',
|
||||
enabled: true,
|
||||
logging: {
|
||||
level: 'info',
|
||||
structured: true,
|
||||
correlationTracking: true
|
||||
},
|
||||
server: {
|
||||
enabled: true,
|
||||
host: '0.0.0.0',
|
||||
port: 3000,
|
||||
cors: true
|
||||
},
|
||||
// Email configuration removed - use IUnifiedEmailServerOptions in DcRouter instead
|
||||
email: undefined,
|
||||
paths: {
|
||||
dataDir: 'data',
|
||||
logsDir: 'logs',
|
||||
tempDir: 'temp',
|
||||
emailTemplatesDir: 'templates/email'
|
||||
}
|
||||
};
|
||||
|
||||
// Export main types for convenience
|
||||
export type {
|
||||
IPlatformConfig,
|
||||
ISmsConfig,
|
||||
IBaseConfig,
|
||||
ITlsConfig,
|
||||
IHttpServerConfig,
|
||||
IRateLimitConfig,
|
||||
IQueueConfig
|
||||
};
|
||||
// Export validation tools only
|
||||
export * from './validator.js';
|
@ -1,6 +1,5 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import { ValidationError } from '../errors/base.errors.js';
|
||||
import type { IBaseConfig } from './base.config.js';
|
||||
|
||||
/**
|
||||
* Validation result
|
||||
@ -95,56 +94,6 @@ export type ValidationSchema = Record<string, {
|
||||
* Validates configuration objects against schemas and provides default values
|
||||
*/
|
||||
export class ConfigValidator {
|
||||
/**
|
||||
* Basic schema for IBaseConfig
|
||||
*/
|
||||
private static baseConfigSchema: ValidationSchema = {
|
||||
id: {
|
||||
type: 'string',
|
||||
required: false
|
||||
},
|
||||
version: {
|
||||
type: 'string',
|
||||
required: false
|
||||
},
|
||||
environment: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
enum: ['development', 'test', 'staging', 'production'],
|
||||
default: 'production'
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: false
|
||||
},
|
||||
enabled: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
default: true
|
||||
},
|
||||
logging: {
|
||||
type: 'object',
|
||||
required: false,
|
||||
schema: {
|
||||
level: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
enum: ['error', 'warn', 'info', 'debug'],
|
||||
default: 'info'
|
||||
},
|
||||
structured: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
default: true
|
||||
},
|
||||
correlationTracking: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
default: true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate a configuration object against a schema
|
||||
@ -261,15 +210,6 @@ export class ConfigValidator {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate base configuration
|
||||
*
|
||||
* @param config Base configuration
|
||||
* @returns Validation result for base configuration
|
||||
*/
|
||||
public static validateBaseConfig(config: IBaseConfig): IValidationResult {
|
||||
return this.validate(config, this.baseConfigSchema);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply defaults to a configuration object based on a schema
|
||||
|
60
ts/mail/routing/classes.email.router.ts
Normal file
60
ts/mail/routing/classes.email.router.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import { EventEmitter } from 'node:events';
|
||||
import type { IEmailRoute, IEmailMatch, IEmailAction, IEmailContext } from './interfaces.js';
|
||||
import type { Email } from '../core/classes.email.js';
|
||||
|
||||
/**
|
||||
* Email router that evaluates routes and determines actions
|
||||
*/
|
||||
export class EmailRouter extends EventEmitter {
|
||||
private routes: IEmailRoute[];
|
||||
private patternCache: Map<string, boolean> = new Map();
|
||||
|
||||
/**
|
||||
* Create a new email router
|
||||
* @param routes Array of email routes
|
||||
*/
|
||||
constructor(routes: IEmailRoute[]) {
|
||||
super();
|
||||
this.routes = this.sortRoutesByPriority(routes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort routes by priority (higher priority first)
|
||||
* @param routes Routes to sort
|
||||
* @returns Sorted routes
|
||||
*/
|
||||
private sortRoutesByPriority(routes: IEmailRoute[]): IEmailRoute[] {
|
||||
return [...routes].sort((a, b) => {
|
||||
const priorityA = a.priority ?? 0;
|
||||
const priorityB = b.priority ?? 0;
|
||||
return priorityB - priorityA; // Higher priority first
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all configured routes
|
||||
* @returns Array of routes
|
||||
*/
|
||||
public getRoutes(): IEmailRoute[] {
|
||||
return [...this.routes];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update routes
|
||||
* @param routes New routes
|
||||
*/
|
||||
public updateRoutes(routes: IEmailRoute[]): void {
|
||||
this.routes = this.sortRoutesByPriority(routes);
|
||||
this.clearCache();
|
||||
this.emit('routesUpdated', this.routes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the pattern cache
|
||||
*/
|
||||
public clearCache(): void {
|
||||
this.patternCache.clear();
|
||||
this.emit('cacheCleared');
|
||||
}
|
||||
}
|
101
ts/mail/routing/interfaces.ts
Normal file
101
ts/mail/routing/interfaces.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import type { Email } from '../core/classes.email.js';
|
||||
import type { IExtendedSmtpSession } from '../delivery/smtpserver/interfaces.js';
|
||||
|
||||
/**
|
||||
* Route configuration for email routing
|
||||
*/
|
||||
export interface IEmailRoute {
|
||||
/** Route identifier */
|
||||
name: string;
|
||||
/** Order of evaluation (higher priority evaluated first, default: 0) */
|
||||
priority?: number;
|
||||
/** Conditions to match */
|
||||
match: IEmailMatch;
|
||||
/** Action to take when matched */
|
||||
action: IEmailAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match criteria for email routing
|
||||
*/
|
||||
export interface IEmailMatch {
|
||||
/** Email patterns to match recipients: "*@example.com", "admin@*" */
|
||||
recipients?: string | string[];
|
||||
/** Email patterns to match senders */
|
||||
senders?: string | string[];
|
||||
/** IP addresses or CIDR ranges to match */
|
||||
clientIp?: string | string[];
|
||||
/** Require authentication status */
|
||||
authenticated?: boolean;
|
||||
|
||||
// Optional advanced matching
|
||||
/** Headers to match */
|
||||
headers?: Record<string, string | RegExp>;
|
||||
/** Message size range */
|
||||
sizeRange?: { min?: number; max?: number };
|
||||
/** Subject line patterns */
|
||||
subject?: string | RegExp;
|
||||
/** Has attachments */
|
||||
hasAttachments?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to take when route matches
|
||||
*/
|
||||
export interface IEmailAction {
|
||||
/** Type of action to perform */
|
||||
type: 'forward' | 'deliver' | 'reject' | 'process';
|
||||
|
||||
/** Forward action configuration */
|
||||
forward?: {
|
||||
/** Target host to forward to */
|
||||
host: string;
|
||||
/** Target port (default: 25) */
|
||||
port?: number;
|
||||
/** Authentication credentials */
|
||||
auth?: {
|
||||
user: string;
|
||||
pass: string;
|
||||
};
|
||||
/** Preserve original headers */
|
||||
preserveHeaders?: boolean;
|
||||
/** Additional headers to add */
|
||||
addHeaders?: Record<string, string>;
|
||||
};
|
||||
|
||||
/** Reject action configuration */
|
||||
reject?: {
|
||||
/** SMTP response code */
|
||||
code: number;
|
||||
/** SMTP response message */
|
||||
message: string;
|
||||
};
|
||||
|
||||
/** Process action configuration */
|
||||
process?: {
|
||||
/** Enable content scanning */
|
||||
scan?: boolean;
|
||||
/** Enable DKIM signing */
|
||||
dkim?: boolean;
|
||||
/** Delivery queue priority */
|
||||
queue?: 'normal' | 'priority' | 'bulk';
|
||||
};
|
||||
|
||||
/** Delivery options (applies to forward/process/deliver) */
|
||||
delivery?: {
|
||||
/** Rate limit (messages per minute) */
|
||||
rateLimit?: number;
|
||||
/** Number of retry attempts */
|
||||
retries?: number;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Context for route evaluation
|
||||
*/
|
||||
export interface IEmailContext {
|
||||
/** The email being routed */
|
||||
email: Email;
|
||||
/** The SMTP session */
|
||||
session: IExtendedSmtpSession;
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
// Email services
|
||||
// Note: EmailService and ApiManager have been removed. Use UnifiedEmailServer directly.
|
@ -2,8 +2,9 @@ import * as plugins from '../plugins.js';
|
||||
import * as paths from '../paths.js';
|
||||
import { logger } from '../logger.js';
|
||||
|
||||
import type { ISmsConfig } from '../config/sms.config.js';
|
||||
import { ConfigValidator, smsConfigSchema } from '../config/index.js';
|
||||
import type { ISmsConfig } from './config/sms.config.js';
|
||||
import { smsConfigSchema } from './config/sms.schema.js';
|
||||
import { ConfigValidator } from '../config/validator.js';
|
||||
|
||||
export class SmsService {
|
||||
public projectinfo: plugins.projectinfo.ProjectInfo;
|
||||
|
109
ts/sms/config/sms.config.ts
Normal file
109
ts/sms/config/sms.config.ts
Normal file
@ -0,0 +1,109 @@
|
||||
/**
|
||||
* SMS service configuration interface
|
||||
*/
|
||||
export interface ISmsConfig {
|
||||
/**
|
||||
* API token for the gateway service
|
||||
*/
|
||||
apiGatewayApiToken: string;
|
||||
|
||||
/**
|
||||
* Default sender ID or phone number
|
||||
*/
|
||||
defaultSender?: string;
|
||||
|
||||
/**
|
||||
* SMS rate limiting
|
||||
*/
|
||||
rateLimit?: {
|
||||
/**
|
||||
* Whether rate limiting is enabled
|
||||
*/
|
||||
enabled?: boolean;
|
||||
|
||||
/**
|
||||
* Maximum requests per period
|
||||
*/
|
||||
maxPerPeriod?: number;
|
||||
|
||||
/**
|
||||
* Period duration in milliseconds
|
||||
*/
|
||||
periodMs?: number;
|
||||
|
||||
/**
|
||||
* Whether to apply rate limit per key
|
||||
*/
|
||||
perKey?: boolean;
|
||||
|
||||
/**
|
||||
* Number of burst tokens
|
||||
*/
|
||||
burstTokens?: number;
|
||||
|
||||
/**
|
||||
* Maximum messages per recipient per day
|
||||
*/
|
||||
maxPerRecipientPerDay?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* SMS provider configuration
|
||||
*/
|
||||
provider?: {
|
||||
/**
|
||||
* Provider type
|
||||
*/
|
||||
type?: 'gateway' | 'twilio' | 'other';
|
||||
|
||||
/**
|
||||
* Provider-specific configuration
|
||||
*/
|
||||
config?: Record<string, any>;
|
||||
|
||||
/**
|
||||
* Fallback provider configuration
|
||||
*/
|
||||
fallback?: {
|
||||
/**
|
||||
* Whether to use fallback provider
|
||||
*/
|
||||
enabled?: boolean;
|
||||
|
||||
/**
|
||||
* Provider type
|
||||
*/
|
||||
type?: 'gateway' | 'twilio' | 'other';
|
||||
|
||||
/**
|
||||
* Provider-specific configuration
|
||||
*/
|
||||
config?: Record<string, any>;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Verification code settings
|
||||
*/
|
||||
verification?: {
|
||||
/**
|
||||
* Code length
|
||||
*/
|
||||
codeLength?: number;
|
||||
|
||||
/**
|
||||
* Code expiration time in seconds
|
||||
*/
|
||||
expirationSeconds?: number;
|
||||
|
||||
/**
|
||||
* Maximum number of attempts
|
||||
*/
|
||||
maxAttempts?: number;
|
||||
|
||||
/**
|
||||
* Cooldown period in seconds
|
||||
*/
|
||||
cooldownSeconds?: number;
|
||||
};
|
||||
}
|
122
ts/sms/config/sms.schema.ts
Normal file
122
ts/sms/config/sms.schema.ts
Normal file
@ -0,0 +1,122 @@
|
||||
import type { ValidationSchema } from '../../config/validator.js';
|
||||
|
||||
/**
|
||||
* SMS service configuration schema
|
||||
*/
|
||||
export const smsConfigSchema: ValidationSchema = {
|
||||
apiGatewayApiToken: {
|
||||
type: 'string',
|
||||
required: true
|
||||
},
|
||||
defaultSender: {
|
||||
type: 'string',
|
||||
required: false
|
||||
},
|
||||
rateLimit: {
|
||||
type: 'object',
|
||||
required: false,
|
||||
schema: {
|
||||
enabled: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
default: true
|
||||
},
|
||||
maxPerPeriod: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
default: 100,
|
||||
min: 1
|
||||
},
|
||||
periodMs: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
default: 60000, // 1 minute
|
||||
min: 1000
|
||||
},
|
||||
perKey: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
default: true
|
||||
},
|
||||
burstTokens: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
default: 5,
|
||||
min: 0
|
||||
},
|
||||
maxPerRecipientPerDay: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
default: 10,
|
||||
min: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
provider: {
|
||||
type: 'object',
|
||||
required: false,
|
||||
schema: {
|
||||
type: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
enum: ['gateway', 'twilio', 'other'],
|
||||
default: 'gateway'
|
||||
},
|
||||
config: {
|
||||
type: 'object',
|
||||
required: false
|
||||
},
|
||||
fallback: {
|
||||
type: 'object',
|
||||
required: false,
|
||||
schema: {
|
||||
enabled: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
enum: ['gateway', 'twilio', 'other']
|
||||
},
|
||||
config: {
|
||||
type: 'object',
|
||||
required: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
verification: {
|
||||
type: 'object',
|
||||
required: false,
|
||||
schema: {
|
||||
codeLength: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
default: 6,
|
||||
min: 4,
|
||||
max: 10
|
||||
},
|
||||
expirationSeconds: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
default: 300, // 5 minutes
|
||||
min: 60
|
||||
},
|
||||
maxAttempts: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
default: 3,
|
||||
min: 1
|
||||
},
|
||||
cooldownSeconds: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
default: 60, // 1 minute
|
||||
min: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user