feat(dcrouter): add configurable baseDir and centralized path resolution; use resolved data paths for storage, cache and DNS

This commit is contained in:
2026-02-16 09:52:38 +00:00
parent 4d77a94bbb
commit 090bd747e1
6 changed files with 55 additions and 38 deletions

View File

@@ -1,5 +1,15 @@
# Changelog
## 2026-02-16 - 6.3.0 - feat(dcrouter)
add configurable baseDir and centralized path resolution; use resolved data paths for storage, cache and DNS
- Introduce IDcRouterOptions.baseDir to allow configuring base directory for dcrouter data (defaults to ~/.serve.zone/dcrouter).
- Add DcRouter.resolvedPaths and resolvePaths(baseDir) in ts/paths.ts to centralize computation of dcrouterHomeDir, dataDir, defaultTsmDbPath, defaultStoragePath and dnsRecordsDir.
- Use resolvedPaths throughout DcRouter: default filesystem storage fsPath, CacheDb storagePath, and DNS records loading now reference resolved paths.
- Replace ensureDirectories() behavior with ensureDataDirectories(resolvedPaths) to only create data-related directories; keep legacy ensureDirectories wrapper delegating to the new function.
- Simplify paths module by removing unused legacy path constants and adding a focused API for path resolution and directory creation.
- Remove an unused import (paths) in contentscanner, cleaning up imports.
## 2026-02-16 - 6.2.4 - fix(deps)
bump @push.rocks/smartproxy to ^25.5.0

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@serve.zone/dcrouter',
version: '6.2.4',
version: '6.3.0',
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
}

View File

@@ -23,9 +23,12 @@ import { MetricsManager } from './monitoring/index.js';
import { RadiusServer, type IRadiusServerConfig } from './radius/index.js';
export interface IDcRouterOptions {
/**
/** Base directory for all dcrouter data. Defaults to ~/.serve.zone/dcrouter */
baseDir?: string;
/**
* Direct SmartProxy configuration - gives full control over HTTP/HTTPS and TCP/SNI traffic
* This is the preferred way to configure HTTP/HTTPS and general TCP/SNI traffic
* This is the preferred way to configure HTTP/HTTPS and general TCP/SNI traffic
*/
smartProxyConfig?: plugins.smartproxy.ISmartProxyOptions;
@@ -170,6 +173,7 @@ export interface PortProxyRuleContext {
export class DcRouter {
public options: IDcRouterOptions;
public resolvedPaths: ReturnType<typeof paths.resolvePaths>;
// Core services
public smartProxy?: plugins.smartproxy.SmartProxy;
@@ -210,10 +214,13 @@ export class DcRouter {
...optionsArg
};
// Resolve all data paths from baseDir
this.resolvedPaths = paths.resolvePaths(this.options.baseDir);
// Default storage to filesystem if not configured
if (!this.options.storage) {
this.options.storage = {
fsPath: plugins.path.join(paths.dcrouterHomeDir, 'storage'),
fsPath: this.resolvedPaths.defaultStoragePath,
};
}
@@ -372,7 +379,7 @@ export class DcRouter {
// Initialize CacheDb singleton
this.cacheDb = CacheDb.getInstance({
storagePath: cacheConfig.storagePath || paths.defaultTsmDbPath,
storagePath: cacheConfig.storagePath || this.resolvedPaths.defaultTsmDbPath,
dbName: cacheConfig.dbName || 'dcrouter',
debug: false,
});
@@ -1306,7 +1313,7 @@ export class DcRouter {
try {
// Ensure paths are imported
const dnsDir = paths.dnsRecordsDir;
const dnsDir = this.resolvedPaths.dnsRecordsDir;
// Check if directory exists
if (!plugins.fs.existsSync(dnsDir)) {
@@ -1370,7 +1377,7 @@ export class DcRouter {
}
// Ensure necessary directories exist
paths.ensureDirectories();
paths.ensureDataDirectories(this.resolvedPaths);
// Generate DKIM keys for each email domain
for (const domainConfig of this.options.emailConfig.domains) {

View File

@@ -1,7 +1,6 @@
import * as plugins from './plugins.js';
// Base directories
export const baseDir = process.cwd();
// Code/asset paths (not affected by baseDir)
export const packageDir = plugins.path.join(
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
'../'
@@ -20,35 +19,37 @@ export const dataDir = process.env.DATA_DIR
// Default TsmDB path for CacheDb
export const defaultTsmDbPath = plugins.path.join(dcrouterHomeDir, 'tsmdb');
// MTA directories
export const keysDir = plugins.path.join(dataDir, 'keys');
// DNS records directory (only surviving MTA directory reference)
export const dnsRecordsDir = plugins.path.join(dataDir, 'dns');
export const sentEmailsDir = plugins.path.join(dataDir, 'emails', 'sent');
export const receivedEmailsDir = plugins.path.join(dataDir, 'emails', 'received');
export const failedEmailsDir = plugins.path.join(dataDir, 'emails', 'failed'); // For failed emails
export const logsDir = plugins.path.join(dataDir, 'logs'); // For logs
// Email template directories
export const emailTemplatesDir = plugins.path.join(dataDir, 'templates', 'email');
export const MtaAttachmentsDir = plugins.path.join(dataDir, 'attachments'); // For email attachments
/**
* Resolve all data paths from a given baseDir.
* When no baseDir is provided, falls back to ~/.serve.zone/dcrouter.
* Specific overrides (e.g. DATA_DIR env) take precedence.
*/
export function resolvePaths(baseDir?: string) {
const root = baseDir ?? plugins.path.join(plugins.os.homedir(), '.serve.zone', 'dcrouter');
const resolvedDataDir = process.env.DATA_DIR ?? plugins.path.join(root, 'data');
return {
dcrouterHomeDir: root,
dataDir: resolvedDataDir,
defaultTsmDbPath: plugins.path.join(root, 'tsmdb'),
defaultStoragePath: plugins.path.join(root, 'storage'),
dnsRecordsDir: plugins.path.join(resolvedDataDir, 'dns'),
};
}
// Configuration path
export const configPath = process.env.CONFIG_PATH
? process.env.CONFIG_PATH
: plugins.path.join(baseDir, 'config.json');
/**
* Ensure only the data directories that are actually used exist.
*/
export function ensureDataDirectories(resolvedPaths: ReturnType<typeof resolvePaths>) {
plugins.fsUtils.ensureDirSync(resolvedPaths.dataDir);
plugins.fsUtils.ensureDirSync(resolvedPaths.dnsRecordsDir);
}
// Create directories if they don't exist
/**
* Legacy wrapper — delegates to ensureDataDirectories with module-level defaults.
*/
export function ensureDirectories() {
// Ensure data directories
plugins.fsUtils.ensureDirSync(dataDir);
plugins.fsUtils.ensureDirSync(keysDir);
plugins.fsUtils.ensureDirSync(dnsRecordsDir);
plugins.fsUtils.ensureDirSync(sentEmailsDir);
plugins.fsUtils.ensureDirSync(receivedEmailsDir);
plugins.fsUtils.ensureDirSync(failedEmailsDir);
plugins.fsUtils.ensureDirSync(logsDir);
// Ensure email template directories
plugins.fsUtils.ensureDirSync(emailTemplatesDir);
plugins.fsUtils.ensureDirSync(MtaAttachmentsDir);
}
ensureDataDirectories(resolvePaths());
}

View File

@@ -1,5 +1,4 @@
import * as plugins from '../plugins.js';
import * as paths from '../paths.js';
import { logger } from '../logger.js';
import { Email, type Core } from '@push.rocks/smartmta';
type IAttachment = Core.IAttachment;

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@serve.zone/dcrouter',
version: '6.2.4',
version: '6.3.0',
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
}