@ackplus/nest-dynamic-templates
Version:
Dynamic template management for NestJS applications
290 lines (240 loc) • 7.82 kB
Markdown
# NestJS Dynamic Templates
A powerful NestJS module for dynamic template management with support for multiple template engines and languages.
## Features
- 🚀 Multiple template engines (Nunjucks, Handlebars, EJS, Pug)
- 🌐 Multiple language support (HTML, MJML, Markdown, Text)
- 💾 Database storage for templates and layouts
- 🔧 Configurable and extensible
- 🎯 TypeScript support
- 📦 Easy integration
## Installation
```bash
npm install @ackplus/nest-dynamic-templates
# or
yarn add @ackplus/nest-dynamic-templates
```
## Usage
### Option 1: Basic Usage (No Configuration Required)
```typescript
import { Module } from '@nestjs/common';
import { NestDynamicTemplatesModule } from '@ackplus/nest-dynamic-templates';
@Module({
imports: [
NestDynamicTemplatesModule, // Provides basic services with default configuration
],
})
export class AppModule {}
```
### Option 2: Using forFeature() (Explicit Basic Usage)
```typescript
import { Module } from '@nestjs/common';
import { NestDynamicTemplatesModule } from '@ackplus/nest-dynamic-templates';
@Module({
imports: [
NestDynamicTemplatesModule.forFeature(), // Explicitly import basic services
],
})
export class AppModule {}
```
### Option 3: Using forRoot() (With Configuration)
```typescript
import { Module } from '@nestjs/common';
import { NestDynamicTemplatesModule, TemplateEngineEnum, TemplateLanguageEnum } from '@ackplus/nest-dynamic-templates';
@Module({
imports: [
NestDynamicTemplatesModule.forRoot({
isGlobal: true,
engines: {
template: [TemplateEngineEnum.NUNJUCKS, TemplateEngineEnum.HANDLEBARS],
language: [TemplateLanguageEnum.HTML, TemplateLanguageEnum.MJML],
},
enginesOptions: {
filters: {
uppercase: (str) => str.toUpperCase(),
reverse: (str) => str.split('').reverse().join(''),
},
template: {
[TemplateEngineEnum.NUNJUCKS]: {
autoescape: true,
},
},
},
}),
],
})
export class AppModule {}
```
### Option 4: Using forRootAsync() (Async Configuration)
#### With useFactory
```typescript
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { NestDynamicTemplatesModule } from '@ackplus/nest-dynamic-templates';
@Module({
imports: [
ConfigModule.forRoot(),
NestDynamicTemplatesModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
isGlobal: true,
engines: {
template: configService.get('TEMPLATE_ENGINES')?.split(',') || ['nunjucks'],
language: configService.get('LANGUAGE_ENGINES')?.split(',') || ['html'],
},
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}
```
#### With useClass
```typescript
import { Injectable } from '@nestjs/common';
import {
NestDynamicTemplatesModuleOptionsFactory,
NestDynamicTemplatesModuleConfig,
TemplateEngineEnum,
TemplateLanguageEnum
} from '@ackplus/nest-dynamic-templates';
@Injectable()
export class TemplatesConfigService implements NestDynamicTemplatesModuleOptionsFactory {
createNestDynamicTemplatesModuleOptions(): NestDynamicTemplatesModuleConfig {
return {
isGlobal: true,
engines: {
template: [TemplateEngineEnum.NUNJUCKS],
language: [TemplateLanguageEnum.HTML, TemplateLanguageEnum.MJML],
},
};
}
}
@Module({
imports: [
NestDynamicTemplatesModule.forRootAsync({
useClass: TemplatesConfigService,
}),
],
providers: [TemplatesConfigService],
})
export class AppModule {}
```
## Using the Services
Once imported, you can inject and use the template services:
```typescript
import { Injectable } from '@nestjs/common';
import { TemplateService, TemplateLayoutService } from '@ackplus/nest-dynamic-templates';
@Injectable()
export class EmailService {
constructor(
private readonly templateService: TemplateService,
private readonly templateLayoutService: TemplateLayoutService,
) {}
async sendWelcomeEmail(user: any) {
// Create a template
const template = await this.templateService.createTemplate({
name: 'welcome-email',
displayName: 'Welcome Email',
engine: 'nunjucks',
language: 'html',
subject: 'Welcome {{ user.name }}!',
content: '<h1>Hello {{ user.name }}</h1><p>Welcome to our platform!</p>',
scope: 'system',
locale: 'en',
});
// Render the template
const rendered = await this.templateService.renderTemplate('welcome-email', {
user: { name: user.name },
});
console.log('Rendered email:', rendered);
// Send email using your preferred email service
}
async createEmailLayout() {
// Create a layout
const layout = await this.templateLayoutService.createTemplateLayout({
name: 'email-layout',
displayName: 'Email Layout',
engine: 'nunjucks',
language: 'html',
content: `
<!DOCTYPE html>
<html>
<head><title>{{ subject }}</title></head>
<body>
<header>Our Company</header>
<main>{{ content | safe }}</main>
<footer>© 2024 Our Company</footer>
</body>
</html>
`,
scope: 'system',
locale: 'en',
});
return layout;
}
}
```
## Configuration Options
### NestDynamicTemplatesModuleConfig
```typescript
interface NestDynamicTemplatesModuleConfig {
isGlobal?: boolean; // Make module global
engines?: {
template?: TemplateEngineEnum[]; // Enabled template engines
language?: TemplateLanguageEnum[]; // Enabled language engines
};
enginesOptions?: {
filters?: Record<string, Function>; // Custom filters
template?: Partial<Record<TemplateEngineEnum, any>>; // Engine-specific options
language?: Partial<Record<TemplateLanguageEnum, any>>; // Language-specific options
};
}
```
### Supported Engines
#### Template Engines
- `nunjucks` - Nunjucks templating
- `handlebars` - Handlebars templating
- `ejs` - EJS templating
- `pug` - Pug templating
#### Language Engines
- `html` - HTML output
- `mjml` - MJML email templates
- `markdown` - Markdown output
- `text` - Plain text output
## Benefits of Each Approach
### Basic Usage (`NestDynamicTemplatesModule`)
- ✅ **Zero configuration** - Works out of the box
- ✅ **Quick setup** - Just import and use
- ✅ **Default engines** - Nunjucks + HTML/MJML/Text
- ❌ **Limited customization** - No custom filters or options
### forFeature()
- ✅ **Explicit** - Clear intent for basic usage
- ✅ **Same as basic** - All benefits of basic usage
- ✅ **Consistent API** - Matches other NestJS modules
### forRoot()
- ✅ **Full configuration** - Complete control over engines and options
- ✅ **Custom filters** - Add your own template filters
- ✅ **Engine options** - Configure individual engines
- ✅ **Global module** - Available throughout the app
### forRootAsync()
- ✅ **Dynamic configuration** - Load config from external sources
- ✅ **Dependency injection** - Use other services for configuration
- ✅ **Environment-based** - Different configs for different environments
- ✅ **Factory pattern** - Clean separation of configuration logic
## Migration Guide
If you're upgrading from a previous version:
### Before
```typescript
// Only forRoot was available
NestDynamicTemplatesModule.forRoot(config)
```
### After
```typescript
// Multiple options now available
NestDynamicTemplatesModule // Basic usage
NestDynamicTemplatesModule.forFeature() // Explicit basic usage
NestDynamicTemplatesModule.forRoot(config) // With configuration
NestDynamicTemplatesModule.forRootAsync(...) // Async configuration
```
## License
MIT