ziegel-platform
The @breadstone/ziegel-platform package provides core component functionality and infrastructure for the ziegel framework. It delivers foundational component model, type conversion systems, object factories, globalization support, and service abstractions for enterprise applications.
Platform Foundation: Essential component infrastructure and cross-cutting concerns that power enterprise application development.
🚀 Why ziegel-platform?
- 🏗️ Component Model: Interfaces for initializable, startable, stoppable components with property change notifications
- 🔄 Type Conversion: Comprehensive type converter system with built-in converters for all primitive types
- 🏭 Object Factories: Advanced object creation patterns with activation handling and dependency injection support
- 🌍 Globalization: Culture providers with reactive culture management and localization support
- 📅 Date/Time Adapters: Pluggable date/time library support for moment.js, date-fns, luxon integration
- 💾 Caching Services: Sophisticated cache registration and management with weak reference support
- 🎯 Decorators: Powerful memoization, notification, and type conversion decorators
- ⏱️ Interval Management: Aggregated interval handling for periodic operations and background tasks
📦 Installation
npm install @breadstone/ziegel-platform
# or
yarn add @breadstone/ziegel-platformDependencies: @breadstone/ziegel-core
⭐ Key Features
Component Model & Lifecycle
Enterprise component lifecycle management with standardized interfaces:
import {
IInitializable,
IStartable,
IStopable,
INotifyPropertyChanged
} from '@breadstone/ziegel-platform';
class DatabaseService implements IInitializable, IStartable, IStopable {
private isConnected = false;
async initialize(): Promise<void> {
console.log('Initializing database configuration...');
// Load configuration, validate settings
}
async start(): Promise<void> {
console.log('Starting database connection...');
this.isConnected = true;
// Establish connections, start health checks
}
async stop(): Promise<void> {
console.log('Stopping database service...');
this.isConnected = false;
// Close connections, cleanup resources
}
}
// Component with property change notifications
class UserProfile implements INotifyPropertyChanged {
private _name: string = '';
get name(): string { return this._name; }
set name(value: string) {
if (this._name !== value) {
this._name = value;
this.notifyPropertyChanged('name');
}
}
notifyPropertyChanged(propertyName: string): void {
// Emit property change events
}
}Advanced Type Conversion System
Robust type conversion with support for complex scenarios:
import {
TypeConverters,
ArrayTypeConverter,
BooleanTypeConverter,
NumberTypeConverter,
TypeConverter
} from '@breadstone/ziegel-platform';
// Built-in type converters
const stringArray = TypeConverters.array.convert(['1', '2', '3'], Number);
// Result: [1, 2, 3]
const boolValue = TypeConverters.boolean.convert('true');
// Result: true
const numberValue = TypeConverters.number.convert('42.5');
// Result: 42.5
// Custom type converter with decorator
class ApiResponse {
constructor(public data: any, public status: number) {}
}
class ApiResponseConverter {
convert(value: any): ApiResponse {
return new ApiResponse(value.data, value.status);
}
}
@TypeConverter(ApiResponse, ApiResponseConverter)
class ApiService {
@TypeConverter(String, 'upper')
formatResponse(data: any): string {
return TypeConverters.string.convert(data).toUpperCase();
}
}Object Factory Pattern
Enterprise object creation with dependency injection support:
import { ObjectFactory, IObjectFactory } from '@breadstone/ziegel-platform';
interface IEmailService {
sendEmail(to: string, subject: string, body: string): Promise<void>;
}
class SmtpEmailService implements IEmailService {
async sendEmail(to: string, subject: string, body: string): Promise<void> {
console.log(`Sending email to ${to}: ${subject}`);
}
}
class SendGridEmailService implements IEmailService {
async sendEmail(to: string, subject: string, body: string): Promise<void> {
console.log(`Sending via SendGrid to ${to}: ${subject}`);
}
}
// Factory registration
const factory = new ObjectFactory();
factory.register('EmailService', () => {
const env = process.env.NODE_ENV;
return env === 'production'
? new SendGridEmailService()
: new SmtpEmailService();
});
factory.register('UserService', (factory) => {
const emailService = factory.create<IEmailService>('EmailService');
return new UserService(emailService);
});
// Usage
const userService = factory.create<UserService>('UserService');// Initialize services after registration
const userRepo = container.get('IUserRepository');
userRepo.initialize();
} }
// Register provider container.addProvider(new DataServiceProvider());
### Application Builder
Streamlined application setup and configuration:
```typescript
import { ApplicationBuilder } from '@breadstone/ziegel-platform';
const app = ApplicationBuilder
.create()
.configureServices(services => {
services.addSingleton('ILogger', ConsoleLogger);
services.addTransient('IEmailService', EmailService);
})
.configureLogging(logging => {
logging.setMinimumLevel('INFO');
logging.addConsole();
})
.build();
await app.start();Configuration Management
Type-safe configuration with environment support:
import { Configuration, ConfigurationBuilder } from '@breadstone/ziegel-platform';
interface AppConfig {
database: {
connectionString: string;
timeout: number;
};
api: {
baseUrl: string;
timeout: number;
};
}
const config = ConfigurationBuilder
.create<AppConfig>()
.addJsonFile('appsettings.json')
.addJsonFile(`appsettings.${process.env.NODE_ENV}.json`, optional: true)
.addEnvironmentVariables()
.build();
// Type-safe access
const dbConnection = config.get('database.connectionString');
const apiTimeout = config.get('api.timeout');Culture Provider
Internationalization and localization support:
import { CultureProvider, CultureInfo } from '@breadstone/ziegel-platform';
const cultureProvider = new CultureProvider();
// Set application culture
cultureProvider.setCulture('de-DE');
// Get current culture info
const culture = cultureProvider.getCurrentCulture();
console.log(culture.name); // "de-DE"
console.log(culture.displayName); // "German (Germany)"
// Format numbers and dates according to culture
const numberFormat = culture.numberFormat;
const dateFormat = culture.dateTimeFormat;Event System
Robust event-driven architecture support:
import { EventBus, Event, EventHandler } from '@breadstone/ziegel-platform';
// Define events
class UserCreatedEvent extends Event {
constructor(public readonly userId: string, public readonly email: string) {
super();
}
}
// Define event handlers
@EventHandler(UserCreatedEvent)
class SendWelcomeEmailHandler {
handle(event: UserCreatedEvent): void {
console.log(`Sending welcome email to ${event.email}`);
}
}
// Setup event bus
const eventBus = new EventBus();
eventBus.subscribe(UserCreatedEvent, new SendWelcomeEmailHandler());
// Publish events
await eventBus.publish(new UserCreatedEvent('123', 'user@example.com'));Advanced Usage
Custom Service Lifetimes
Control how services are instantiated and managed:
import { ServiceLifetime } from '@breadstone/ziegel-platform';
// Singleton - one instance for the entire application
container.register(DatabaseService, ServiceLifetime.Singleton);
// Transient - new instance every time
container.register(EmailService, ServiceLifetime.Transient);
// Scoped - one instance per scope/request
container.register(UserContext, ServiceLifetime.Scoped);Middleware Pipeline
Build processing pipelines with middleware:
import { Pipeline, Middleware } from '@breadstone/ziegel-platform';
class ValidationMiddleware implements Middleware<Request, Response> {
async invoke(context: Request, next: () => Promise<Response>): Promise<Response> {
// Validate request
if (!this.isValid(context)) {
throw new ValidationError('Invalid request');
}
return await next();
}
}
const pipeline = Pipeline.create<Request, Response>()
.use(new ValidationMiddleware())
.use(new AuthenticationMiddleware())
.use(new BusinessLogicMiddleware());
const result = await pipeline.execute(request);Best Practices
1. Use Interface-Based Registration
Register services by interfaces for better testability:
// ✅ Good
container.bind<IUserService>('IUserService').to(UserService);
// ❌ Avoid
container.register(UserService);2. Organize with Service Providers
Group related service registrations:
class SecurityServiceProvider extends ServiceProvider {
register(container: Container): void {
container.bind('IAuthService').to(JwtAuthService);
container.bind('IEncryption').to(AesEncryption);
container.bind('IHasher').to(BcryptHasher);
}
}3. Use Configuration Sections
Organize configuration into logical sections:
// appsettings.json
{
"database": {
"connectionString": "...",
"timeout": 30
},
"logging": {
"level": "Information"
}
}
// Access sections
const dbConfig = config.getSection('database');
const connectionString = dbConfig.get('connectionString');4. Handle Events Asynchronously
Use async event handlers for better performance:
@EventHandler(OrderCreatedEvent)
class UpdateInventoryHandler {
async handle(event: OrderCreatedEvent): Promise<void> {
await this.inventoryService.updateStock(event.productId, event.quantity);
}
}Integration with Other Packages
ziegel-platform serves as the foundation for many other ziegel packages:
- ziegel-platform-http - HTTP services using platform DI
- ziegel-platform-logging - Logging infrastructure
- ziegel-platform-configuration - Enhanced configuration
- ziegel-platform-messaging - Message handling
Testing
Mock services easily for unit testing:
import { Container } from '@breadstone/ziegel-platform';
describe('UserService', () => {
let container: Container;
let userService: UserService;
let mockDatabase: jest.Mocked<DatabaseService>;
beforeEach(() => {
mockDatabase = {
connect: jest.fn(),
query: jest.fn()
} as any;
container = new Container();
container.bind(DatabaseService).toConstantValue(mockDatabase);
container.bind(UserService).toSelf();
userService = container.get(UserService);
});
it('should connect to database when getting users', async () => {
await userService.getUsers();
expect(mockDatabase.connect).toHaveBeenCalled();
});
});Migration Guide
From Other DI Containers
From InversifyJS
// InversifyJS
container.bind<IUserService>(TYPES.UserService).to(UserService);
// ziegel-platform
container.bind<IUserService>('IUserService').to(UserService);From TypeDI
// TypeDI
@Service()
class UserService {}
// ziegel-platform
@Injectable()
class UserService {}API Reference
For detailed API documentation, see the generated API reference.