This commit is contained in:
2025-05-28 11:39:54 +00:00
parent 0e610cba16
commit 77ff948404
10 changed files with 677 additions and 344 deletions

View File

@ -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';

View File

@ -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

View 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');
}
}

View 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;
}

View File

@ -1,2 +0,0 @@
// Email services
// Note: EmailService and ApiManager have been removed. Use UnifiedEmailServer directly.

View File

@ -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
View 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
View 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
}
}
}
};