npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tzmail

v1.0.5

Published

Email library for Next.js with customizable templates and themes

Downloads

92

Readme

Mikeprogrammer973/tzMail

Primeiros passos e uso básico/Inicialização SMTP e primeiro fluxo funcional

Primeiros passos e uso básico - Inicialização SMTP e primeiro fluxo funcional

Visão geral

Este fluxo mostra o caminho mínimo para sair da configuração SMTP e disparar o primeiro email funcional com tzMail. O ponto de partida é , onde dotenv.config() carrega as credenciais do ambiente, SMTP_CONFIG é montado com IEmailConfig, e EmailFactory.initialize() cria a instância única que passa a coordenar envio, templates e anexos.

Na prática, o usuário do pacote monta o SMTP_CONFIG, obtém TemplateService a partir de EmailFactory, cria um template com ThemeType e ITemplateConfig, e envia o email por emailFactory.sendEmail(). Quando template é informado e html não existe, o HTML final é gerado por TemplateService e TemplateBuilder, e o envio real ocorre via Nodemailer no EmailService.

Arquitetura do fluxo mínimo

flowchart TB
    subgraph Boot [Bootstrap da demonstracao]
        Dotenv[dotenv config]
        Index[src index ts]
        Config[SMTP_CONFIG]
        Route[GET test]
        Dotenv --> Config
        Index --> Config
        Index --> Route
    end

    subgraph Factory [EmailFactory]
        FactoryInit[EmailFactory initialize]
        FactoryInstance[Instancia unica]
        EmailSvc[EmailService]
        TemplateSvc[TemplateService]
        AttachSvc[AttachmentService]
        FactoryInit --> FactoryInstance
        FactoryInstance --> EmailSvc
        FactoryInstance --> TemplateSvc
        FactoryInstance --> AttachSvc
    end

    subgraph Templating [Templates e renderizacao]
        TemplateFactory[TemplateFactory]
        TemplateBuilder[TemplateBuilder]
        ThemeSet[Temas]
        TemplateSvc --> TemplateFactory
        TemplateFactory --> ThemeSet
        TemplateFactory --> TemplateBuilder
    end

    subgraph SMTP [Envio SMTP]
        Nodemailer[Transporter Nodemailer]
        SMTPServer[Servidor SMTP]
        EmailSvc --> Nodemailer
        Nodemailer --> SMTPServer
    end

    Route --> AttachSvc
    Route --> FactoryInstance
    FactoryInstance --> TemplateSvc
    FactoryInstance --> EmailSvc

Configuração SMTP mínima com IEmailConfig

IEmailConfig

EmailFactory.initialize() é idempotente: a primeira chamada cria a instância e as chamadas seguintes retornam a mesma instância já configurada. Isso faz com que o SMTP_CONFIG definido no bootstrap seja o ponto único de inicialização do transporte SMTP.

src/core/interfaces/email.interface.ts

IEmailConfig define tudo o que EmailFactory precisa para montar o transporter do Nodemailer e repassar o remetente padrão para EmailService.

| Propriedade | Tipo | Descrição | | --- | --- | --- | | host | string | Host SMTP usado por nodemailer.createTransport. | | port | number | Porta do servidor SMTP. | | secure | boolean | Indica uso de conexão segura no transporte. | | auth.user | string | Usuário SMTP lido do ambiente em . | | auth.pass | string | Senha SMTP lida do ambiente em . | | defaultFrom? | string | Remetente padrão aplicado por EmailService quando options.from não é informado. |

Bootstrap do SMTP em

src/index.ts

O exemplo de demonstração monta o objeto SMTP com credenciais vindas de variáveis de ambiente e um defaultFrom fixo.

dotenv.config();

const SMTP_CONFIG = {
  host: 'smtp.gmail.com',
  port: 587,
  secure: false,
  auth: {
    user: process.env.SMTP_USER!,
    pass: process.env.SMTP_PASS!
  },
  defaultFrom: 'LyraX Corp <[email protected]>'
};

const emailFactory = EmailFactory.initialize(SMTP_CONFIG);

As credenciais SMTP_USER e SMTP_PASS são lidas antes da criação da fábrica. O valor de defaultFrom é repassado para EmailService, que o usa como remetente quando options.from não é enviado em sendEmail().

Relação entre EmailFactory, TemplateService e EmailService

  • EmailFactory é a fachada de entrada do fluxo.
  • EmailFactory.initialize() cria:- EmailService, com o transporter do Nodemailer e defaultFrom.
  • TemplateService, com as opções de template.
  • AttachmentService, para anexos.
  • EmailFactory.getTemplateService() expõe TemplateService para criação e renderização de templates.
  • EmailFactory.sendEmail() delega o envio para EmailService.send().
  • EmailService.send() resolve html diretamente ou renderiza options.template quando html não foi informado.

Contratos de email e anexo

IEmailOptions

src/core/interfaces/email.interface.ts

IEmailOptions representa os dados de envio recebidos por EmailService.send() e por EmailFactory.sendEmail().

| Propriedade | Tipo | Descrição | | --- | --- | --- | | to | string | string[] | Destinatário único ou lista de destinatários. | | subject | string | Assunto do email. | | from? | string | Remetente opcional que sobrescreve defaultFrom. | | cc? | string | string[] | Cópia carbono opcional. | | bcc? | string | string[] | Cópia oculta opcional. | | attachments? | IAttachment[] | Lista de anexos em formato Nodemailer. | | template? | ITemplate | Template a ser renderizado quando html não existir. | | text? | string | Corpo textual opcional. | | html? | string | HTML final; tem prioridade sobre template. |

IAttachment

src/core/interfaces/email.interface.ts

IAttachment é o formato usado em attachments por EmailService.send() e pelas saídas de AttachmentService.

| Propriedade | Tipo | Descrição | | --- | --- | --- | | filename | string | Nome exibido do arquivo anexado. | | content? | string | Buffer | Conteúdo em memória do anexo. | | path? | string | Caminho local do arquivo anexado. | | contentType? | string | MIME type opcional. | | cid? | string | Content ID para uso em imagens embutidas. |

EmailService

src/services/email.service.ts

EmailService encapsula o envio real e monta mailOptions a partir de IEmailOptions.

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | transporter | Transporter | Instância Nodemailer usada em sendMail(). | | defaultFrom | string | undefined | Remetente padrão aplicado quando options.from não existe. |

Dependências do construtor

| Tipo | Descrição | | --- | --- | | Transporter | Transporte Nodemailer criado por EmailFactory. | | string | defaultFrom opcional recebido de IEmailConfig. |

Métodos públicos

| Método | Descrição | | --- | --- | | send | Monta mailOptions, renderiza template quando necessário e chama transporter.sendMail(). |

Comportamento do envio

  • from usa options.from quando existe; caso contrário, usa defaultFrom.
  • to aceita string[] e converte para uma string separada por vírgula.
  • html tem prioridade absoluta.
  • Quando html não é informado e template existe, template.render(options) gera o HTML.
  • attachments, cc, bcc, subject e text são repassados ao transporter.

Resultado retornado

  • Sucesso: { success: true, messageId, response }
  • Falha: { success: false, error }

AttachmentService

src/services/attachment.service.ts

AttachmentService transforma arquivos locais ou buffers em IAttachment prontos para Nodemailer.

Propriedades

Não há campos de instância declarados.

Dependências do construtor

Não possui construtor explícito.

Métodos públicos

| Método | Descrição | | --- | --- | | addFromPath | Valida um caminho local e retorna um IAttachment com path. | | addFromBuffer | Retorna um IAttachment com content a partir de um Buffer. | | addFromUrl | Lança erro de método não implementado. |

Comportamento de addFromPath

addFromUrl() sempre lança Error('Method not implemented yet'). O fluxo de demonstração que usa anexos só funciona com addFromPath() ou addFromBuffer().

  • Faz fs.promises.stat(filePath).
  • Exige que o caminho seja um arquivo.
  • Usa path.basename(filePath) quando options.filename não é informado.
  • Retorna path, contentType e cid quando informados.

Contratos e renderização de template

ITemplate

src/core/interfaces/template.interface.ts

ITemplate representa o objeto de template criado por TemplateFactory e consumido por EmailService.

| Propriedade | Tipo | Descrição | | --- | --- | --- | | name | string | Nome do template, como modern_light. | | theme | ThemeType | Tema associado ao template. | | variant | 'light' | 'dark' | Variação visual do template. | | config | ITemplateConfig | Configuração estrutural do template. |

Métodos

| Método | Descrição | | --- | --- | | render | Gera o HTML final a partir dos dados recebidos. |

ITemplateConfig

src/core/interfaces/template.interface.ts

| Propriedade | Tipo | Descrição | | --- | --- | --- | | header? | IHeaderConfig | Configuração do cabeçalho. | | body? | IBodyConfig | Configuração do corpo. | | footer? | IFooterConfig | Configuração do rodapé. | | layout? | 'full' 'minimal' | Layout geral do email. | | spacing? | 'compact' 'normal' 'relaxed' | Espaçamento global. | | borderRadius? | 'none' 'small' 'medium' 'large' | Raio de borda do container. |

IBodyConfig

src/core/interfaces/template.interface.ts

| Propriedade | Tipo | Descrição | | --- | --- | --- | | title? | string | Título principal do corpo. | | message? | string | Mensagem principal do corpo. | | content? | string | HTML do corpo quando já pronto. | | buttonText? | string | Texto do botão. | | buttonUrl? | string | URL do botão. | | buttonVariant? | 'primary' 'secondary' 'success' 'danger' | Variante visual do botão. | | alignment? | 'left' 'center' 'right' | Alinhamento do conteúdo. | | backgroundColor? | string | Cor de fundo do bloco. | | textColor? | string | Cor do texto do bloco. | | fontSize? | number | Tamanho base da fonte em pixels. |

IHeaderConfig

src/core/interfaces/template.interface.ts

| Propriedade | Tipo | Descrição | | --- | --- | --- | | show | boolean | Define se o cabeçalho será renderizado. | | logo? | { type: 'text' 'image'; text?; imageUrl?; alt?; size? } | Dados do logo textual ou em imagem. | | backgroundColor? | string | Cor de fundo do cabeçalho. | | textColor? | string | Cor do texto do cabeçalho. |

IFooterConfig

src/core/interfaces/template.interface.ts

| Propriedade | Tipo | Descrição | | --- | --- | --- | | show | boolean | Define se o rodapé será renderizado. | | links? | Array<{ text: string; url: string }> | Links do rodapé. | | socialLinks? | Array<{ platform: 'facebook' 'twitter' 'linkedin' 'github'; url: string }> | Links sociais com ícones. | | copyrightText? | string | Texto de copyright. | | unsubscribeText? | string | Texto do link de cancelamento. | | backgroundColor? | string | Cor de fundo do rodapé. | | textColor? | string | Cor do texto do rodapé. |

TemplateFactory

src/factories/template-factory.ts

TemplateFactory transforma ThemeType, variante e configuração em um ITemplate com render().

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | themes | Map<ThemeType, ITheme> | Catálogo estático de temas disponíveis. |

Métodos públicos

| Método | Descrição | | --- | --- | | createTemplate | Cria um template com name, theme, variant, config e render(). | | getTheme | Recupera a instância do tema pelo ThemeType. | | listThemes | Lista os temas disponíveis. | | getThemeInfo | Retorna nome, descrição e features do tema. |

Como createTemplate monta o HTML

  • data.template.config.body.
  • Usa body.content quando existe.
  • Caso contrário, monta um bloco padrão com:- title ou Hello!
  • message ou This is an email generated with tzMail.
  • Usa TemplateBuilder para montar:- cabeçalho com buildHeader()
  • corpo com buildBody()
  • botão opcional com buildButton()
  • rodapé com buildFooter()
  • HTML final com build()

TemplateBuilder

src/templates/base/template-builder.ts

TemplateBuilder constrói a estrutura HTML final e aplica variações específicas de tema nas seções de header, body, button e footer.

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | template | string | HTML acumulado durante a construção. | | theme | ITheme | Tema ativo na renderização. | | config | ITemplateConfig | Configuração do template. | | variant | 'light' 'dark' | Variante de cor usada na renderização. |

Dependências do construtor

| Tipo | Descrição | | --- | --- | | ITheme | Tema concreto, como ModernTheme ou MinimalTheme. | | ITemplateConfig | Configuração de header, body, footer e layout. | | 'light' 'dark' | Variante do template. |

Métodos públicos

| Método | Descrição | | --- | --- | | buildHeader | Adiciona o bloco de cabeçalho ao HTML. | | buildBody | Adiciona o bloco principal do corpo ao HTML. | | buildButton | Adiciona o botão de CTA ao HTML. | | buildFooter | Adiciona o rodapé ao HTML. | | build | Finaliza o documento HTML completo. |

Comportamento relevante

  • buildHeader() retorna cedo quando config.header.show é falso.
  • buildBody() ajusta estilos e processa conteúdo conforme o tema.
  • buildButton() usa primary ou secondary e aplica estilos específicos por tema.
  • buildFooter() inclui links, socialLinks, copyrightText e unsubscribeText.
  • build() define o container central e o <html> completo.

TemplateService

src/services/template.service.ts

TemplateService é a camada central de criação, cache, histórico, renderização e pré-visualização de templates.

Tipos internos

TemplateCache

src/services/template.service.ts

| Propriedade | Tipo | Descrição | | --- | --- | --- | | template | ITemplate | Template armazenado no cache. | | createdAt | Date | Data de criação do cache entry. | | expiresAt | Date | Data de expiração. | | hits | number | Quantidade de acessos ao cache. |

TemplateOptions

src/services/template.service.ts

| Propriedade | Tipo | Descrição | | --- | --- | --- | | cache? | boolean | Ativa ou desativa o cache. | | cacheTTL? | number | TTL em segundos. | | validateConfig? | boolean | Ativa validação da configuração. | | minify? | boolean | Ativa minificação do HTML. | | preview? | boolean | Marca o render como pré-visualização. |

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | templateCache | Map<string, TemplateCache> | Cache in-memory por template. | | defaultTTL | number | TTL padrão em segundos. | | templateHistory | Map<string, ITemplate[]> | Histórico de versões por template. | | options | TemplateOptions | Configuração global do serviço. |

Dependências do construtor

| Tipo | Descrição | | --- | --- | | TemplateOptions | Opções de cache, validação, minificação e preview. |

Métodos públicos

| Método | Descrição | | --- | --- | | createTemplate | Cria ou reaproveita um template no cache. | | cloneTemplate | Clona um template com modificações parciais. | | renderTemplate | Renderiza um template e adiciona metadados _meta. | | previewTemplate | Cria e renderiza um template sem persistir no cache. | | getThemeInfo | Retorna informações detalhadas de tema e configuração padrão. | | listThemes | Lista os ThemeType disponíveis. | | getTemplateStats | Retorna métricas do cache e do histórico. | | clearCache | Remove cache globalmente ou por tema. | | getTemplateHistory | Retorna o histórico de versões de um template. | | restoreTemplateVersion | Reconstrói uma versão anterior. | | preloadTemplates | Pré-carrega templates no cache. | | exportTemplate | Exporta o template para JSON. | | importTemplate | Importa um template a partir de JSON. | | generateExampleTemplate | Gera um template de demonstração. | | isValidTemplate | Valida a estrutura de um objeto template. | | getTemplateDetails | Retorna template atual, histórico, cache e uso. |

Fluxo de estado e cache

  • createTemplate() gera um templateId com themeType, variant e hash do JSON da config.
  • Se o cache estiver ativo e existir entrada válida, incrementa hits e retorna o template cacheado.
  • Se não houver cache, cria o template por TemplateFactory.createTemplate().
  • O template é enriquecido com métodos dinâmicos:- getVersion()
  • getId()
  • clone()
  • O histórico mantém as últimas 10 versões por templateId.
  • cleanExpiredCache() remove entradas vencidas a cada hora via setInterval().

Validação de configuração

validateTemplateConfig() agrega erros e lança uma única exceção quando encontra problemas em:

  • logo de imagem sem imageUrl
  • logo textual sem text
  • links de footer sem text ou url
  • layout fora de full ou minimal
  • spacing fora de compact, normal ou relaxed
  • borderRadius fora de none, small, medium ou large

Metadados adicionados no render

renderTemplate() injeta _meta no payload:

  • isPreview
  • renderDate
  • templateName
  • theme
  • variant

ThemeType

src/core/enums/theme.enum.ts

ThemeType define os temas usados em TemplateFactory e TemplateService.

Valores: SYSTEM, MONOKAI, MODERN, CORPORATE, MINIMAL.

TemplatePart

src/core/enums/template-part.enum.ts

TemplatePart descreve as partes estruturais do email renderizado.

Valores: HEADER, BODY, FOOTER, BUTTON.

Temas disponíveis

ITheme

src/templates/themes/theme.interface.ts

| Propriedade | Tipo | Descrição | | --- | --- | --- | | id | ThemeType | Identificador do tema. | | name | string | Nome humano do tema. | | light | IThemeColors | Paleta para variante clara. | | dark | IThemeColors | Paleta para variante escura. | | typography | ITypography | Tipografia do tema. | | spacing | ISpacing | Escala de espaçamento do tema. |

IThemeColors

src/templates/themes/theme.interface.ts

| Propriedade | Tipo | Descrição | | --- | --- | --- | | primary | string | Cor principal. | | secondary | string | Cor secundária. | | background | string | Cor de fundo. | | text | string | Cor de texto principal. | | textMuted | string | Cor de texto secundário. | | border | string | Cor de borda. | | success | string | Cor de sucesso. | | error | string | Cor de erro. | | warning | string | Cor de aviso. |

ITypography

src/templates/themes/theme.interface.ts

| Propriedade | Tipo | Descrição | | --- | --- | --- | | fontFamily | string | Família tipográfica base. | | fontSizes | { small: string; medium: string; large: string; xlarge: string } | Escala de tamanhos. | | fontWeights | { normal: number; medium: number; bold: number } | Pesos tipográficos. |

ISpacing

src/templates/themes/theme.interface.ts

| Propriedade | Tipo | Descrição | | --- | --- | --- | | xs | string | Espaçamento extra pequeno. | | sm | string | Espaçamento pequeno. | | md | string | Espaçamento médio. | | lg | string | Espaçamento grande. | | xl | string | Espaçamento extra grande. |

SystemTheme

src/templates/themes/system.theme.ts

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | id | ThemeType | Valor SYSTEM. | | name | string | Nome System. | | light | { primary; secondary; background; text; textMuted; border; success; error; warning } | Paleta clara. | | dark | { primary; secondary; background; text; textMuted; border; success; error; warning } | Paleta escura. | | typography | { fontFamily; fontSizes; fontWeights } | Tipografia base do tema. | | spacing | { xs; sm; md; lg; xl } | Escala de espaçamento. |

MonokaiTheme

src/templates/themes/monokai.theme.ts

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | id | ThemeType | Valor MONOKAI. | | name | string | Nome Monokai. | | light | IThemeColors | Paleta clara com acentos fortes. | | dark | IThemeColors | Paleta escura Monokai. | | typography | ITypography | Tipografia monoespaçada. | | spacing | ISpacing | Escala compacta. | | codeHighlight | { comment; keyword; string; number; function; variable } | Cores de destaque para blocos de código. | | borderStyle | { radius: string; width: string; style: string } | Estilo de borda do tema. | | effects | { glow; shadow; transition } | Efeitos visuais do tema. |

ModernTheme

src/templates/themes/modern.theme.ts

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | id | ThemeType | Valor MODERN. | | name | string | Nome Modern. | | light | IThemeColors | Paleta clara contemporânea. | | dark | IThemeColors | Paleta escura contemporânea. | | typography | ITypography | Tipografia moderna. | | spacing | ISpacing | Escala de espaçamento. | | gradients | { primary; secondary; accent; dark; light } | Gradientes usados pelo builder. | | borderStyle | { radius: { small; medium; large; full }; width: string; style: string } | Raio e borda do tema. | | glassmorphism | { light; dark; blur } | Cores e blur para efeito glass. | | animations | { hover; fade; slide } | Transições do tema. |

CorporateTheme

src/templates/themes/corporate.theme.ts

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | id | ThemeType | Valor CORPORATE. | | name | string | Nome Corporate. | | light | IThemeColors | Paleta clara corporativa. | | dark | IThemeColors | Paleta escura corporativa. | | typography | ITypography | Tipografia serifada. | | spacing | ISpacing | Escala de espaçamento. | | corporateColors | { gold; silver; bronze; navy; charcoal; ivory } | Paleta de apoio corporativa. | | borderStyle | { radius: { small; medium; large; pill }; width: { thin; medium; thick }; style: string } | Bordas do tema. | | elevation | { shadow; card; modal; hover } | Sombras e elevação. | | branding | { logoSize; letterSpacing; textTransform } | Regras de marca. | | layout | { maxWidth; contentWidth; sidebarWidth; headerHeight; footerHeight } | Medidas de layout. |

MinimalTheme

src/templates/themes/minimal.theme.ts

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | id | ThemeType | Valor MINIMAL. | | name | string | Nome Minimal. | | light | IThemeColors | Paleta clara minimalista. | | dark | IThemeColors | Paleta escura minimalista. | | typography | ITypography | Tipografia sem serifa. | | spacing | ISpacing | Escala expandida. | | minimalColors | { white; black; gray100; gray200; gray300; gray400; gray500; gray600; gray700; gray800; gray900 } | Paleta neutra. | | borderStyle | { radius: { none; small; medium; large; full }; width: { thin; medium }; style: string } | Bordas minimalistas. | | effects | { shadow; transition; opacity } | Efeitos suaves e opacidade. | | layout | { maxWidth; contentWidth; spacingMultiplier; lineHeight; paragraphSpacing } | Regras de layout. | | designSystem | { grid; breakpoints; zIndex } | Grid e breakpoints do tema. |

Fábrica de email e inicialização do fluxo

EmailFactory

src/factories/email-factory.ts

EmailFactory centraliza a criação do transporte SMTP, o serviço de email, o serviço de templates e o serviço de anexos. A classe funciona como singleton global do pacote.

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | instance | EmailFactory undefined | Instância única mantida pela fábrica. | | emailService | EmailService | Serviço de envio usado por sendEmail(). | | templateService | TemplateService | Serviço de criação e renderização de templates. | | attachmentService | AttachmentService | Serviço de anexos criado junto com a fábrica. |

Dependências do construtor

| Tipo | Descrição | | --- | --- | | IEmailConfig | Configuração SMTP e defaultFrom. | | any | templateOptions repassado para TemplateService. |

Métodos públicos

| Método | Descrição | | --- | --- | | initialize | Cria a instância única com SMTP e serviços internos. | | getInstance | Retorna a instância criada ou lança erro se não houver inicialização. | | sendEmail | Encaminha o envio para EmailService.send(). | | getTemplateService | Expõe a instância de TemplateService. | | getAttachmentService | Expõe a instância de AttachmentService. | | previewTemplate | Delegada para TemplateService.previewTemplate(). | | getThemeInfo | Delegada para TemplateService.getThemeInfo(). | | listThemes | Delegada para TemplateService.listThemes(). | | getTemplateStats | Delegada para TemplateService.getTemplateStats(). |

Relação de uso no bootstrap

  1. EmailFactory.initialize(SMTP_CONFIG) cria o transporter com nodemailer.createTransport(config).
  2. O EmailService recebe o transporter e config.defaultFrom.
  3. O TemplateService é criado com templateOptions quando fornecidas.
  4. O AttachmentService fica disponível para montagem de anexos.
  5. A aplicação recupera templateService com getTemplateService() e gera os templates usados no primeiro envio.

Nota sobre reconfiguração

Fluxo funcional do primeiro email

Funções de demonstração em

A fábrica não recria o transporte após a primeira inicialização. Isso significa que mudanças em SMTP_CONFIG só têm efeito antes da primeira chamada de initialize().

src/index.ts

Estas funções mostram como a fábrica é consumida no exemplo de servidor Express.

| Função | Descrição | | --- | --- | | sendWelcomeEmail | Envia um email com modernTemplate e assunto de boas-vindas. | | sendTechNewsletter | Envia uma newsletter técnica com monokaiTemplate. | | sendCorporateReport | Envia um relatório corporativo com corporateTemplate. | | sendMinimalNewsletter | Envia uma newsletter minimalista com anexo vindo de AttachmentService.addFromPath(). |

Fluxo mínimo usado no exemplo

  1. dotenv.config() carrega SMTP_USER e SMTP_PASS.
  2. SMTP_CONFIG é montado com host, port, secure, auth.user, auth.pass e defaultFrom.
  3. EmailFactory.initialize(SMTP_CONFIG) cria a fábrica.
  4. emailFactory.getTemplateService() expõe o serviço de templates.
  5. templateService.createTemplate(...) monta um template com tema e configuração.
  6. emailFactory.sendEmail({ to, subject, template }) envia a mensagem.
  7. EmailService.send() resolve from com defaultFrom, renderiza o template e chama o transporter.
  8. O resultado retorna como JSON.

Exemplo mínimo de envio

const templateService = emailFactory.getTemplateService();

const modernTemplate = templateService.createTemplate(
  ThemeType.MODERN,
  'light',
  {
    header: {
      show: true,
      logo: {
        type: 'image',
        imageUrl: 'https://talkspace-ten.vercel.app/_next/image?url=%2Flogo%2Ftalkspace-banner.png&w=640&q=75',
        size: 'large'
      }
    },
    body: {
      title: 'Bem-vindo ao LyraX!',
      message: 'Estamos felizes em tê-lo conosco.',
      buttonText: 'Começar Agora',
      buttonUrl: 'https://meuapp.com/get-started',
      buttonVariant: 'primary',
      alignment: 'center',
      fontSize: 16
    },
    footer: {
      show: true,
      copyrightText: '© 2024 Meu App'
    },
    layout: 'full',
    spacing: 'normal',
    borderRadius: 'medium'
  }
);

await emailFactory.sendEmail({
  to: '[email protected]',
  subject: 'Bem-vindo ao Meu App!',
  template: modernTemplate
});

Fluxo com anexo no exemplo

sendMinimalNewsletter() cria um AttachmentService localmente, chama addFromPath('uploads/PHOTO.jpg') e injeta o retorno em attachments. O envio segue o mesmo caminho do email comum, mas com o anexo repassado para Nodemailer.

sequenceDiagram
    participant U as Usuario
    participant E as Express
    participant S as sendMinimalNewsletter
    participant A as AttachmentService
    participant F as EmailFactory
    participant M as EmailService
    participant T as Template
    participant B as TemplateBuilder
    participant N as Nodemailer
    participant Smtp as SMTP

    U->>E: GET test
    E->>S: sendMinimalNewsletter
    S->>A: addFromPath uploads PHOTO jpg
    A-->>S: IAttachment
    S->>F: sendEmail
    F->>M: send
    M->>T: render
    T->>B: buildHeader buildBody buildFooter build
    B-->>T: HTML
    T-->>M: HTML final
    M->>N: sendMail
    N->>Smtp: entregar email
    Smtp-->>N: resposta SMTP
    N-->>M: info
    M-->>F: { success, messageId, response }
    F-->>E: JSON
    E-->>U: resposta do endpoint

Servidor de demonstração e ponto de entrada

Endpoint de teste

Executar envio de teste

src/index.ts

{
    "title": "Executar envio de teste",
    "description": "Dispara o fluxo de demonstra\u00e7\u00e3o que cria um anexo a partir de uploads/PHOTO.jpg, envia um email com o tema Minimal em modo dark e retorna o resultado do envio em JSON.",
    "method": "GET",
    "baseUrl": "<DemoServerBaseUrl>",
    "endpoint": "/test",
    "headers": [],
    "queryParams": [],
    "pathParams": [],
    "bodyType": "none",
    "requestBody": "",
    "formData": [],
    "rawBody": "",
    "responses": {
        "200": {
            "description": "Resultado retornado diretamente por res.json(result).",
            "body": "{\n    \"success\": true,\n    \"messageId\": \"[email protected]\",\n    \"response\": \"250 2.0.0 OK\"\n}"
        }
    }
}

Comportamento real do endpoint

  • O endpoint é GET /test.
  • Ele chama sendMinimalNewsletter('[email protected]').
  • O retorno de emailFactory.sendEmail() é enviado diretamente com res.json(result).
  • Não há middleware de autenticação nem validação adicional além dos middlewares globais express.json() e express.urlencoded() montados no bootstrap.

Inicialização do servidor

sendMinimalNewsletter() não possui try/catch. Se addFromPath('uploads/PHOTO.jpg') falhar ou se o envio SMTP lançar exceção antes de retornar, a requisição deixa de responder com o objeto de sucesso e a exceção sobe para o fluxo do Express.

também define:

  • PORT = 3001
  • app.use(express.json())
  • app.use(express.urlencoded({ extended: true }))
  • app.listen(PORT, ...) com banner de inicialização no console

Estado, cache e tratamento de erros

Estado de inicialização

  • EmailFactory mantém estado global por meio de private static instance.
  • TemplateService mantém estado em memória por templateCache e templateHistory.
  • TemplateService agenda limpeza automática com setInterval(..., 3600000).

Cache de templates

| Elemento | Valor | | --- | --- | | Chave do cache | ${themeType}_${variant}_${hash} | | Dado armazenado | ITemplate enriquecido | | Contador de uso | hits | | Expiração | expiresAt calculado em segundos e convertido para milissegundos | | Limpeza automática | cleanExpiredCache() a cada hora | | Limpeza manual | clearCache() | | Histórico | Últimas 10 versões por templateId |

Tratamento de erros por componente

  • EmailFactory.getInstance() lança erro se initialize() ainda não foi chamado.
  • TemplateFactory.createTemplate() lança erro quando o tema não existe no mapa themes.
  • TemplateService.validateTemplateConfig() lança um único erro com todos os problemas encontrados.
  • TemplateService.renderTemplate() captura falhas e relança com contexto: Failed to render template: ...
  • EmailService.send() nunca lança erro diretamente; retorna success: false com o objeto de erro.
  • AttachmentService.addFromPath() lança erro se o caminho não for arquivo.
  • AttachmentService.addFromUrl() lança erro fixo de método não implementado.

Dependências e integração

Dependências externas

  • express
  • nodemailer
  • dotenv
  • fs
  • path

Entradas de ambiente usadas no bootstrap

  • SMTP_USER
  • SMTP_PASS

Integrações internas

  • consome EmailFactory e TemplateService.
  • EmailFactory instancia EmailService, TemplateService e AttachmentService.
  • TemplateService depende de TemplateFactory.
  • TemplateFactory depende das classes de tema e de TemplateBuilder.
  • EmailService depende do Transporter do Nodemailer.
  • AttachmentService é usado tanto no exemplo de anexo quanto como serviço exposto pela fábrica.

Considerações de teste

  • Validar que EmailFactory.initialize() foi chamado antes de qualquer getInstance().
  • Verificar se SMTP_USER e SMTP_PASS estão definidos antes do bootstrap.
  • Confirmar que defaultFrom aparece no envelope do email quando options.from não é enviado.
  • Testar sendEmail() com:- template apenas
  • html apenas
  • template e html juntos
  • attachments com arquivo válido
  • Confirmar que addFromPath() falha para diretório ou caminho inexistente.
  • Confirmar que GET /test retorna JSON com o formato devolvido por sendEmail().

Referência rápida das classes-chave

| Class | Responsibility | | --- | --- | | email-factory.ts | Centraliza a inicialização SMTP e expõe EmailService, TemplateService e AttachmentService. | | email.service.ts | Constrói mailOptions e envia emails via Nodemailer. | | template.service.ts | Cria, renderiza, cacheia e versiona templates. | | template-factory.ts | Transforma tema e configuração em um ITemplate renderizável. | | template-builder.ts | Monta o HTML final do email com header, body, button e footer. | | attachment.service.ts | Converte arquivos e buffers em anexos Nodemailer. | | system.theme.ts | Define o tema base SYSTEM. | | monokai.theme.ts | Define o tema MONOKAI com destaque de código. | | modern.theme.ts | Define o tema MODERN com gradientes e glassmorphism. | | corporate.theme.ts | Define o tema CORPORATE com linguagem visual executiva. | | minimal.theme.ts | Define o tema MINIMAL com layout enxuto e neutro. |


Gerenciamento de Templates/Temas concretos: System, Monokai, Modern, Corporate e Minimal

Gerenciamento de Templates - Temas concretos

Visão geral

Este recorte concentra os cinco temas concretos do mecanismo de templates de email do projeto: System, Monokai, Modern, Corporate e Minimal. Eles formam a camada visual base que define cores, tipografia, espaçamento e extensões temáticas usadas na composição final do HTML.

O fluxo visível no código parte do contrato ITheme, passa pelo registro de temas em TemplateFactory e chega à montagem visual em TemplateBuilder. Na prática, o tema selecionado determina como cabeçalho, corpo, botão e rodapé são estilizados, além de habilitar comportamentos especiais como realce de código, gradientes, glassmorphism, branding corporativo e layout minimalista.

Comparação rápida dos temas

| Tema | Paleta visual | Tipografia | Espaçamento | Extensões específicas | | --- | --- | --- | --- | --- | | System | Azul padrão e neutros claros/escuros | Sans system default | Compacto a normal | Nenhuma extensão extra | | Monokai | Paleta técnica com magenta, verde e roxo | Monospace | Compacto | codeHighlight, effects, borderStyle | | Modern | Neutros com azul e gradientes | Inter com suporte a UI moderna | Médio a relaxado | gradients, glassmorphism, animations, borderStyle | | Corporate | Azul executivo com dourado e tons institucionais | Serifada | Médio | corporateColors, branding, elevation, layout, borderStyle | | Minimal | Preto, branco e cinzas | Inter limpa | Generoso | minimalColors, effects, layout, designSystem, borderStyle |

Arquitetura de composição dos temas

flowchart LR
    subgraph Contratos[Contratos]
        ThemeType[ThemeType]
        ITheme[ITheme]
        IThemeColors[IThemeColors]
        ITypography[ITypography]
        ISpacing[ISpacing]
    end

    subgraph TemasConcretos[Temas concretos]
        SystemTheme[SystemTheme]
        MonokaiTheme[MonokaiTheme]
        ModernTheme[ModernTheme]
        CorporateTheme[CorporateTheme]
        MinimalTheme[MinimalTheme]
    end

    subgraph Composicao[Composição]
        TemplateFactory[TemplateFactory]
        TemplateBuilder[TemplateBuilder]
    end

    ThemeType --> TemplateFactory
    ITheme --> SystemTheme
    ITheme --> MonokaiTheme
    ITheme --> ModernTheme
    ITheme --> CorporateTheme
    ITheme --> MinimalTheme

    TemplateFactory --> SystemTheme
    TemplateFactory --> MonokaiTheme
    TemplateFactory --> ModernTheme
    TemplateFactory --> CorporateTheme
    TemplateFactory --> MinimalTheme

    TemplateBuilder --> SystemTheme
    TemplateBuilder --> MonokaiTheme
    TemplateBuilder --> ModernTheme
    TemplateBuilder --> CorporateTheme
    TemplateBuilder --> MinimalTheme

O contrato ITheme padroniza os tokens visuais obrigatórios. TemplateFactory mantém a instância concreta em um Map<ThemeType, ITheme>, enquanto TemplateBuilder lê esses tokens e monta as variações de HTML conforme variant e theme.id.

Contratos compartilhados

theme.interface.ts

src/templates/themes/theme.interface.ts

ITheme

| Propriedade | Tipo | Descrição | | --- | --- | --- | | id | ThemeType | Identificador do tema | | name | string | Nome legível do tema | | light | IThemeColors | Paleta para modo claro | | dark | IThemeColors | Paleta para modo escuro | | typography | ITypography | Sistema tipográfico do tema | | spacing | ISpacing | Escala de espaçamento do tema |

IThemeColors

| Propriedade | Tipo | | --- | --- | | primary | string | | secondary | string | | background | string | | text | string | | textMuted | string | | border | string | | success | string | | error | string | | warning | string |

ITypography

| Propriedade | Tipo | | --- | --- | | fontFamily | string | | fontSizes.small | string | | fontSizes.medium | string | | fontSizes.large | string | | fontSizes.xlarge | string | | fontWeights.normal | number | | fontWeights.medium | number | | fontWeights.bold | number |

ISpacing

| Propriedade | Tipo | | --- | --- | | xs | string | | sm | string | | md | string | | lg | string | | xl | string |

ThemeType

Valores definidos: system, monokai, modern, corporate, minimal.

TemplateFactory

src/factories/template-factory.ts

A fábrica registra os cinco temas concretos em um Map<ThemeType, ITheme> e materializa um ITemplate com name, theme, variant, config e render.

Métodos públicos

| Método | Descrição | | --- | --- | | createTemplate | Resolve o tema pelo ThemeType, cria um ITemplate e associa o render à montagem via TemplateBuilder | | getTheme | Retorna a instância concreta do tema para um ThemeType | | listThemes | Lista os temas registrados no mapa interno | | getThemeInfo | Expõe nome, descrição e lista de recursos do tema |

Metadados de tema expostos por getThemeInfo

| Tema | Nome | Descrição | Recursos | | --- | --- | --- | --- | | SYSTEM | System | Tema limpo e profissional com cores adaptativas | Design minimalista, alta acessibilidade, compatibilidade total | | MONOKAI | Monokai | Inspirado no tema de código, ideal para conteúdo técnico | Cores vibrantes, destaque de sintaxe, efeitos glow | | MODERN | Modern | Design contemporâneo com gradientes e efeitos modernos | Gradientes elegantes, glassmorphism, animações suaves | | CORPORATE | Corporate | Design profissional e elegante para empresas | Tipografia serifada, detalhes em dourado, layout estruturado | | MINIMAL | Minimal | Design clean e focado no conteúdo | Sem distrações, espaçamento generoso, tipografia limpa |

TemplateBuilder

src/templates/base/template-builder.ts

O TemplateBuilder consome o tema concreto em cada etapa da composição do email. Ele aplica estilos de cabeçalho, corpo, botão, rodapé e container final com ramificações específicas para monokai, modern, corporate e minimal.

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | template | string | HTML acumulado durante a construção | | theme | ITheme | Tema concreto usado na renderização | | config | ITemplateConfig | Configuração visual do template | | variant | 'light' 'dark' | Variante visual ativa |

Métodos públicos

| Método | Descrição | | --- | --- | | buildHeader | Monta o cabeçalho e aplica ajustes específicos por tema | | buildBody | Monta o corpo do email e processa conteúdo especial por tema | | buildButton | Monta o botão de CTA com variações visuais por tema | | buildFooter | Monta o rodapé com links, redes sociais e texto institucional | | build | Finaliza o HTML completo do template |

Extensões específicas aplicadas por tema

| Tema | Propriedades consumidas | Efeito gerado | | --- | --- | --- | | System | light, dark, typography, spacing | Estilo base com bordas e espaçamentos padrão | | Monokai | codeHighlight, effects, borderStyle | Realce de código, brilho, transições e borda técnica | | Modern | gradients, glassmorphism, animations, borderStyle | Botões com gradiente, blur e cantos arredondados | | Corporate | corporateColors, branding, elevation, borderStyle | Dourado institucional, caixa com sombra e tipografia serifada | | Minimal | layout, designSystem, effects, borderStyle | Layout centralizado, conteúdo arejado e aparência sem distrações |

Helpers internos relevantes

| Método | Função | | --- | --- | | buildLogo | Renderiza logo em texto ou imagem com ajustes por tema | | formatCorporateContent | Adiciona estilos corporativos a blockquote e highlight | | formatMinimalContent | Simplifica títulos e parágrafos para o tema minimalista | | highlightCode | Converte blocos <code> em <pre> com estilização Monokai | | applySyntaxHighlighting | Aplica coloração por palavra-chave, string, número e função | | buildFooterLinks | Monta links do rodapé com variações por tema | | buildSocialLinks | Monta ícones sociais a partir de URLs fixas | | getSocialIcon | Resolve o ícone do serviço social pela plataforma |

Fluxo de criação e renderização de um tema

sequenceDiagram
    participant Dev as Desenvolvedor
    participant TemplateFactory as TemplateFactory
    participant ITemplate as ITemplate
    participant TemplateBuilder as TemplateBuilder

    Dev->>TemplateFactory: createTemplate
    TemplateFactory->>TemplateFactory: resolve tema por ThemeType
    TemplateFactory-->>Dev: ITemplate
    Dev->>ITemplate: render
    ITemplate->>TemplateBuilder: buildHeader
    ITemplate->>TemplateBuilder: buildBody
    ITemplate->>TemplateBuilder: buildButton
    ITemplate->>TemplateBuilder: buildFooter
    ITemplate->>TemplateBuilder: build
    TemplateBuilder-->>ITemplate: HTML final
    ITemplate-->>Dev: HTML renderizado

Os blocos de estilo criados em buildButton, buildFooterLinks e trechos similares incluem &:hover dentro de atributos style. O HTML inline gerado por build() preserva esse texto, mas pseudo-classes não são interpretadas como CSS ativo no markup final.

Esse fluxo é o mesmo para os cinco temas concretos; o que muda é o conjunto de tokens expostos pelo tema e as ramificações internas que TemplateBuilder ativa com base em theme.id.

Temas concretos

SystemTheme

src/templates/themes/system.theme.ts

Tema base com visual neutro e suporte direto a modos claro e escuro. Ele usa azul como cor primária e neutros para texto, borda e superfícies, com tipografia sans-serif do sistema.

Propriedades

| Propriedade | Tipo | | --- | --- | | id | ThemeType.SYSTEM | | name | string | | light | IThemeColors | | dark | IThemeColors | | typography | ITypography | | spacing | ISpacing |

Paleta

| Token | Light | Dark | | --- | --- | --- | | primary | #3b82f6 | #3b82f6 | | secondary | #6b7280 | #9ca3af | | background | #ffffff | #111827 | | text | #111827 | #f9fafb | | textMuted | #6b7280 | #9ca3af | | border | #e5e7eb | #374151 | | success | #10b981 | #10b981 | | error | #ef4444 | #ef4444 | | warning | #f59e0b | #f59e0b |

Tipografia

| Propriedade | Valor | | --- | --- | | fontFamily | -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif | | fontSizes.small | 12px | | fontSizes.medium | 14px | | fontSizes.large | 16px | | fontSizes.xlarge | 20px | | fontWeights.normal | 400 | | fontWeights.medium | 500 | | fontWeights.bold | 700 |

Espaçamento

| Propriedade | Valor | | --- | --- | | xs | 4px | | sm | 8px | | md | 16px | | lg | 24px | | xl | 32px |

Leitura visual

  • Cabeçalho e rodapé usam os tokens base de fundo, borda e texto.
  • Não há propriedades extras além do contrato ITheme.
  • A aplicação em TemplateBuilder segue o caminho padrão, sem ramificações visuais adicionais.

MonokaiTheme

src/templates/themes/monokai.theme.ts

Tema voltado para conteúdo técnico, com identidade inspirada em editores de código. A paleta mantém magenta e verde como destaques, e o tema adiciona realce semântico para blocos de código.

Propriedades

| Propriedade | Tipo | | --- | --- | | id | ThemeType.MONOKAI | | name | string | | light | IThemeColors | | dark | IThemeColors | | typography | ITypography | | spacing | ISpacing | | codeHighlight | { comment: string; keyword: string; string: string; number: string; function: string; variable: string } | | borderStyle | { radius: string; width: string; style: string } | | effects | { glow: string; shadow: string; transition: string } |

Paleta

| Token | Light | Dark | | --- | --- | --- | | primary | #f92672 | #f92672 | | secondary | #a6e22e | #a6e22e | | background | #f9f9f9 | #272822 | | text | #272822 | #f8f8f2 | | textMuted | #75715e | #75715e | | border | #e5e5e5 | #3e3d32 | | success | #a6e22e | #a6e22e | | error | #f92672 | #f92672 | | warning | #fd971f | #fd971f |

Tipografia

| Propriedade | Valor | | --- | --- | | fontFamily | SF Mono, Monaco, Inconsolata, Fira Code, monospace | | fontSizes.small | 12px | | fontSizes.medium | 14px | | fontSizes.large | 16px | | fontSizes.xlarge | 20px | | fontWeights.normal | 400 | | fontWeights.medium | 500 | | fontWeights.bold | 700 |

Espaçamento

| Propriedade | Valor | | --- | --- | | xs | 4px | | sm | 8px | | md | 16px | | lg | 24px | | xl | 32px |

Extensões específicas

codeHighlight

| Token | Cor | | --- | --- | | comment | #75715e | | keyword | #f92672 | | string | #e6db74 | | number | #ae81ff | | function | #a6e22e | | variable | #fd971f |

borderStyle

| Propriedade | Valor | | --- | --- | | radius | 4px | | width | 2px | | style | solid |

effects

| Propriedade | Valor | | --- | --- | | glow | 0 0 10px rgba(249, 38, 114, 0.3) | | shadow | 0 4px 6px rgba(0, 0, 0, 0.1) | | transition | all 0.3s ease |

Leitura visual

  • TemplateBuilder.highlightCode usa codeHighlight para colorir keywords, strings, números e nomes de função.
  • O cabeçalho e os botões recebem brilho e transição via effects.
  • O layout privilegia blocos com borda técnica e acento visual marcante.

ModernTheme

src/templates/themes/modern.theme.ts

Tema contemporâneo com uso de gradientes, blur e transições suaves. O conjunto de tokens foi desenhado para dar mais profundidade visual a botões, contêineres e cabeçalhos.

Propriedades

| Propriedade | Tipo | | --- | --- | | id | ThemeType.MODERN | | name | string | | light | IThemeColors | | dark | IThemeColors | | typography | ITypography | | spacing | ISpacing | | gradients | { primary: string; secondary: string; accent: string; dark: string; light: string } | | borderStyle | { radius: { small: string; medium: string; large: string; full: string }; width: string; style: string } | | glassmorphism | { light: string; dark: string; blur: string } | | animations | { hover: string; fade: string; slide: string } |

Paleta

| Token | Light | Dark | | --- | --- | --- | | primary | #0f172a | #38bdf8 | | secondary | #64748b | #94a3b8 | | background | #ffffff | #0f172a | | text | #0f172a | #f1f5f9 | | textMuted | #64748b | #94a3b8 | | border | #e2e8f0 | #1e293b | | success | #10b981 | #34d399 | | error | #ef4444 | #f87171 | | warning | #f59e0b | #fbbf24 |

Tipografia

| Propriedade | Valor | | --- | --- | | fontFamily | Inter, SF Pro Display, Segoe UI, system-ui, sans-serif | | fontSizes.small | 13px | | fontSizes.medium | 15px | | fontSizes.large | 17px | | fontSizes.xlarge | 24px | | fontWeights.normal | 400 | | fontWeights.medium | 500 | | fontWeights.bold | 600 |

Espaçamento

| Propriedade | Valor | | --- | --- | | xs | 6px | | sm | 12px | | md | 20px | | lg | 32px | | xl | 48px |

Extensões específicas

gradients

| Token | Valor | | --- | --- | | primary | linear-gradient(135deg, #0f172a 0%, #1e293b 100%) | | secondary | linear-gradient(135deg, #64748b 0%, #94a3b8 100%) | | accent | linear-gradient(135deg, #38bdf8 0%, #0f172a 100%) | | dark | linear-gradient(135deg, #0f172a 0%, #020617 100%) | | light | linear-gradient(135deg, #f8fafc 0%, #ffffff 100%) |

borderStyle

| Propriedade | Valor | | --- | --- | | radius.small | 8px | | radius.medium | 12px | | radius.large | 16px | | radius.full | 9999px | | width | 1px | | style | solid |

glassmorphism

| Propriedade | Valor | | --- | --- | | light | rgba(255, 255, 255, 0.8) | | dark | rgba(15, 23, 42, 0.8) | | blur | 12px |

animations

| Propriedade | Valor | | --- | --- | | hover | transform 0.2s ease, box-shadow 0.2s ease | | fade | opacity 0.3s ease | | slide | transform 0.3s cubic-bezier(0.4, 0, 0.2, 1) |

Leitura visual

  • TemplateBuilder usa gradients.primary no botão principal e no texto do logo.
  • glassmorphism.blur entra no cabeçalho e no rodapé para criar profundidade.
  • animations.hover é aplicado a botões e links de navegação do tema.

CorporateTheme

src/templates/themes/corporate.theme.ts

Tema voltado para comunicação empresarial, com base serifada, tons institucionais e acentos dourados. O tema expande o contrato base com tokens de marca, elevação e layout.

Propriedades

| Propriedade | Tipo | | --- | --- | | id | ThemeType.CORPORATE | | name | string | | light | IThemeColors | | dark | IThemeColors | | typography | ITypography | | spacing | ISpacing | | corporateColors | { gold: string; silver: string; bronze: string; navy: string; charcoal: string; ivory: string } | | borderStyle | { radius: { small: string; medium: string; large: string; pill: string }; width: { thin: string; medium: string; thick: string }; style: string } | | elevation | { shadow: string; card: string; modal: string; hover: string } | | branding | { logoSize: { small: string; medium: string; large: string }; letterSpacing: { tight: string; normal: string; wide: string; wider: string }; textTransform: { uppercase: string; lowercase: string; capitalize: string; normal: string } } | | layout | { maxWidth: string; contentWidth: string; sidebarWidth: string; headerHeight: string; footerHeight: string } |

Paleta

| Token | Light | Dark | | --- | --- | --- | | primary | #1e40af | #3b82f6 | | secondary | #334155 | #64748b | | background | #ffffff | #0f172a | | text | #0f172a | #f1f5f9 | | textMuted | #475569 | #94a3b8 | | border | #e2e8f0 | #1e293b | | success | #059669 | #10b981 | | error | #dc2626 | #ef4444 | | warning | #d97706 | #f59e0b |

Tipografia

| Propriedade | Valor | | --- | --- | | fontFamily | "Playfair Display", "Georgia", "Times New Roman", serif | | fontSizes.small | 12px | | fontSizes.medium | 14px | | fontSizes.large | 16px | | fontSizes.xlarge | 24px | | fontWeights.normal | 400 | | fontWeights.medium | 500 | | fontWeights.bold | 700 |

Espaçamento

| Propriedade | Valor | | --- | --- | | xs | 4px | | sm | 8px | | md | 16px | | lg | 24px | | xl | 32px |

Extensões específicas

corporateColors

| Token | Valor | | --- | --- | | gold | #d4af37 | | silver | #c0c0c0 | | bronze | #cd7f32 | | navy | #0a2540 | | charcoal | #36454f | | ivory | #fffff0 |

borderStyle

| Propriedade | Valor | | --- | --- | | radius.small | 2px | | radius.medium | 4px | | radius.large | 8px | | radius.pill | 20px | | width.thin | 1px | | width.medium | 2px | | width.thick | 3px | | style | solid |

elevation

| Propriedade | Valor | | --- | --- | | shadow | 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04) | | card | 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06) | | modal | 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.02) | | hover | 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05) |

branding

| Propriedade | Valor | | --- | --- | | logoSize.small | 32px | | logoSize.medium | 48px | | logoSize.large | 64px | | letterSpacing.tight | -0.5px | | letterSpacing.normal | 0px | | letterSpacing.wide | 0.5px | | letterSpacing.wider | 1px | | textTransform.uppercase | uppercase | | textTransform.lowercase | lowercase | | textTransform.capitalize | capitalize | | textTransform.normal | none |

layout

| Propriedade | Valor | | --- | --- | | maxWidth | 600px | | contentWidth | 560px | | sidebarWidth | 200px | | headerHeight | 80px | | footerHeight | 120px |

Leitura visual

  • O cabeçalho recebe dourado corporativo, uppercase e tracking mais largo.
  • buildBody adiciona borda lateral dourada e sombra de cartão.
  • O rodapé usa fonte menor, letterSpacing.normal e borda superior mais forte.

MinimalTheme

src/templates/themes/minimal.theme.ts

Tema orientado ao conteúdo, com menos elementos decorativos e maior respiro entre blocos. A superfície visual é reduzida ao essencial, com um sistema de layout e design próprio.

Propriedades

| Propriedade | Tipo | | --- | --- | | id | ThemeType.MINIMAL | | name | string | | light | IThemeColors | | dark | IThemeColors | | typography | ITypography | | spacing | ISpacing | | minimalColors | { white: string; black: string; gray100: string; gray200: string; gray300: string; gray400: string; gray500: string; gray600: string; gray700: string; gray800: string; gray900: string } | | borderStyle | { radius: { none: string; small: string; medium: string; large: string; full: string }; width: { thin: string; medium: string }; style: string } | | effects | { shadow: string; transition: string; opacity: { hover: string; disabled: string } } | | layout | { maxWidth: string; contentWidth: string; spacingMultiplier: number; lineHeight: number; paragraphSpacing: string } | | designSystem | { grid: { columns: number; gutter: string; margin: string }; breakpoints: { mobile: string; tablet: string; desktop: string }; zIndex: { base: number; overlay: number; modal: number } } |

Paleta

| Token | Light | Dark | | --- | --- | --- | | primary | #000000 | #ffffff | | secondary | #404040 | #a3a3a3 | | background | #ffffff | #000000 | | text | #111111 | #ffffff | | textMuted | #666666 | #737373 | | border | #e5e5e5 | #262626 | | success | #22c55e | #22c55e | | error | #ef4444 | #ef4444 | | warning | #f97316 | #f97316 |

Tipografia

| Propriedade | Valor | | --- | --- | | fontFamily | Inter, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif | | fontSizes.small | 13px | | fontSizes.medium | 15px | | fontSizes.large | 17px | | fontSizes.xlarge | 21px | | fontWeights.normal | 400 | | fontWeights.medium | 500 | | fontWeights.bold | 600 |

Espaçamento

| Propriedade | Valor | | --- | --- | | xs | 8px | | sm | 16px | | md | 24px | | lg | 32px | | xl | 48px |

Extensões específicas

minimalColors

| Token | Valor | | --- | --- | | white | #ffffff | | black | #000000 | | gray100 | #f5f5f5 | | gray200 | #e5e5e5 | | gray300 | #d4d4d4 | | gray400 | #a3a3a3 | | gray500 | #737373 | | gray600 | #525252 | | gray700 | #404040 | | gray800 | #262626 | | gray900 | #171717 |

borderStyle

| Propriedade | Valor | | --- | --- | | radius.none | 0px | | radius.small | 2px | | radius.medium | 4px | | radius.large | 8px | | radius.full | 9999px | | width.thin | 1px | | width.medium | 2px | | style | solid |

effects

| Propriedade | Valor | | --- | --- | | shadow | none | | transition | all 0.2s ease | | opacity.hover | 0.7 | | opacity.disabled | 0.5 |

layout

| Propriedade | Valor | | --- | --- | | maxWidth | 640px | | contentWidth | 560px | | spacingMultiplier | 1.5 | | lineHeight | 1.6 | | paragraphSpacing | 1.5em |

designSystem

| Bloco | Propriedade | Valor | | --- | --- | --- | | grid | columns | 12 | | grid | gutter | 20px | | grid | margin | 20px | | breakpoints | mobile | 480px | | breakpoints | tablet | 768px | | breakpoints | desktop | 1024px | | zIndex | base | 1 | | zIndex | overlay | 10 | | zIndex | modal | 100 |

Leitura visual

  • buildBody centraliza o conteúdo em contentWidth e amplia o respiro lateral.
  • build ajusta a largura máxima para 640px e remove bordas no contêiner final.
  • O sistema designSystem formaliza grid, breakpoints e camadas visuais para uso do tema.

Referência rápida das decisões por tema

| Tema | Cabeçalho | Corpo | Botão | Rodapé | | --- | --- | --- | --- | --- | | SystemTheme | Borda simples e cores base | Texto e fundo do contrato padrão | Botão padrão | Links e textos padrão | | MonokaiTheme | Borda técnica, sombra e transição | codeHighlight e borda lateral magenta | Borda magenta e glow | Borda superior destacada | | ModernTheme | Blur e borda suave | Margem e raio moderados | Gradiente e sombra leve | Glassmorphism e radius | | CorporateTheme | Dourado, uppercase e tracking | Borda lateral dourada e sombra de cartão | Letras em uppercase e hover com elevação | Borda superior dourada | | MinimalTheme | Borda fina e peso tipográfico contido | Max width e layout centralizado | Botão contornado e sem preenchimento | Rodapé enxuto e espaçado |

Key Classes Reference

| Class | Responsibility | | --- | --- | | theme.interface.ts | Define o contrato comum ITheme e os tokens de cor, tipografia e espaçamento | | system.theme.ts | Implementa o tema base com paleta neutra e tipografia do sistema | | monokai.theme.ts | Implementa o tema técnico com realce de código e efeitos visuais | | modern.theme.ts | Implementa o tema contemporâneo com gradientes, blur e animações | | corporate.theme.ts | Implementa o tema corporativo com branding, dourado e layout executivo | | minimal.theme.ts | Implementa o tema minimalista com layout enxuto e design system próprio | | template-factory.ts | Registra e instancia os temas concretos por ThemeType | | template-builder.ts | Aplica os tokens dos temas na construção final do HTML do email |


Primeiros passos e uso básico/Instalação, scripts de execução e artefatos publicados

Primeiros passos e uso básico

package.json, tsconfig.json, src/index.ts, dist/index.js, dist/index.d.ts

Visão geral

A biblioteca é publicada como um pacote TypeScript centrado em Node.js + SMTP/Nodemailer, com artefatos prontos para consumo em dist/. O objetivo prático do primeiro uso é simples: instalar as dependências, compilar o projeto e consumir o ponto de entrada publicado sem depender do código-fonte em src/.

O pacote declara next e nodemailer em peerDependencies, então o projeto que instala a biblioteca precisa resolver essas dependências por conta própria. Isso é relevante tanto para consumidores quanto para contribuidores, porque a saída compilada e os tipos publicados são o contrato real do pacote.

Arquitetura de publicação

flowchart TB
    subgraph Repo [tzMail]
        Pkg[package json]
        TsConfig[tsconfig json]
        SrcIndex[src index ts]
        Build[build]
        Dev[dev]
        Start[start]
        Test[test]
        Lint[lint]
        DistJS[dist index js]
        DistDTS[dist index d ts]
    end

    subgraph Consumer [Projeto consumidor]
        App[Aplicação Node.js ou Next.js]
        NextDep[next peer dependency]
        NodemailerDep[nodemailer peer dependency]
    end

    Pkg --> Build
    Pkg --> Dev
    Pkg --> Start
    Pkg --> Test
    Pkg --> Lint

    TsConfig --> Build
    SrcIndex --> Build

    Build --> DistJS
    Build --> DistDTS

    App --> DistJS
    App --> DistDTS
    App --> NextDep
    App --> NodemailerDep

Instalação

npm install tzmail

Gerenciamento de Templates/Catálogo de temas e seleção por metadados

Gerenciamento de Templates - Catálogo de temas e seleção por metadados

Visão geral

Esta parte do projeto concentra o registro dos temas visuais disponíveis e a descoberta guiada por metadados para que a escolha do template seja feita antes da renderização. O fluxo começa em TemplateFactory, que mantém o catálogo concreto de temas, e continua em TemplateService, que expõe uma visão pronta para consumo com nome amigável, descrição, recursos, variantes suportadas e configuração padrão por tema.

Na prática, esse catálogo permite que a aplicação apresente opções visuais coerentes ao usuário, sem exigir que ele conheça os detalhes internos de cada tema. O resultado é uma seleção mais previsível de ThemeType, variant e ITemplateConfig, com defaults específicos que orientam a composição correta do email.

Arquitetura do catálogo de temas

flowchart TB
    subgraph DemoApp [Servidor de Demonstração]
        Demo[src index ts]
    end

    subgraph Catalog [Catálogo de Temas]
        Service[TemplateService]
        Factory[TemplateFactory]
        Registry[Map ThemeType to ITheme]
        SystemTheme[SystemTheme]
        MonokaiTheme[MonokaiTheme]
        ModernTheme[ModernTheme]
        CorporateTheme[CorporateTheme]
        MinimalTheme[MinimalTheme]
        Builder[TemplateBuilder]
    end

    subgraph Metadata [Metadados para seleção]
        ThemeInfo[getThemeInfo]
        ThemeList[listThemes]
        DefaultConfig[defaultConfig]
        Variants[availableVariants]
    end

    Demo -->|createTemplate| Service
    Demo -->|getThemeInfo| Service
    Demo -->|listThemes| Service

    Service -->|delegates| Factory
    Service -->|adds metadata| Metadata

    Factory -->|resolves| Registry
    Registry --> SystemTheme
    Registry --> MonokaiTheme
    Registry --> ModernTheme
    Registry --> CorporateTheme
    Registry --> MinimalTheme
    Factory -->|builds template| Builder

    Factory --> ThemeInfo
    Factory --> ThemeList
    Service --> DefaultConfig
    Service --> Variants

Componentes principais

TemplateFactory

src/factories/template-factory.ts

TemplateFactory é o registro estático do catálogo de temas. Ela associa cada ThemeType a uma instância concreta de ITheme, resolve o tema solicitado, lista os temas cadastrados e produz o objeto de template usado pelo restante do fluxo.

Propriedades

| Propriedade | Tipo | Descrição | | --- | --- | --- | | themes | Map<ThemeType, ITheme> | Catálogo estático com SystemTheme, MonokaiTheme, ModernTheme, CorporateTheme e MinimalTheme. |

Métodos públicos

| Método | Descrição | | --- | --- | | createTemplate | Resolve o tema pelo ThemeType, valida a existência no catálogo e retorna um ITemplate com name, theme, variant, config e render. | | getTheme | Retorna a instância concreta de ITheme associada ao ThemeType solicitado. | | listThemes | Retorna a lista de ThemeType atualmente registrados no catálogo. | | getThemeInfo | Retorna metadados estáticos do tema: name, description e features. |

Registro de temas

A ordem de listThemes() segue a ordem de inserção do Map:

  • system
  • monokai
  • modern
  • corporate
  • minimal

Como o template é montado

`createTempl